From: Po Lu Date: Tue, 24 Jan 2023 02:23:52 +0000 (+0800) Subject: Update android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=de3d8ae71b43f80244c4d813ff1503b8551f0026;p=emacs.git Update android port * xcompile: Move to cross. * cross: New directory. --- diff --git a/cross/lib/COPYING b/cross/lib/COPYING new file mode 100644 index 00000000000..f288702d2fa --- /dev/null +++ b/cross/lib/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/cross/lib/acl-errno-valid.c b/cross/lib/acl-errno-valid.c new file mode 100644 index 00000000000..a4fd575e3f3 --- /dev/null +++ b/cross/lib/acl-errno-valid.c @@ -0,0 +1,52 @@ +/* Test whether ACLs are well supported on this system. + + Copyright 2013-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert. */ + +#include + +#include + +#include + +/* Return true if errno value ERRNUM indicates that ACLs are well + supported on this system. ERRNUM should be an errno value obtained + after an ACL-related system call fails. */ +bool +acl_errno_valid (int errnum) +{ + /* Recognize some common errors such as from an NFS mount that does + not support ACLs, even when local drives do. */ + switch (errnum) + { + case EBUSY: return false; + case EINVAL: return false; +#if defined __APPLE__ && defined __MACH__ + case ENOENT: return false; +#endif + case ENOSYS: return false; + +#if defined ENOTSUP && ENOTSUP != EOPNOTSUPP +# if ENOTSUP != ENOSYS /* Needed for the MS-Windows port of GNU Emacs. */ + case ENOTSUP: return false; +# endif +#endif + + case EOPNOTSUPP: return false; + default: return true; + } +} diff --git a/cross/lib/acl-internal.c b/cross/lib/acl-internal.c new file mode 100644 index 00000000000..fbe9b2c9a06 --- /dev/null +++ b/cross/lib/acl-internal.c @@ -0,0 +1,507 @@ +/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include "acl-internal.h" + +#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + +/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial. */ +int +acl_extended_nontrivial (acl_t acl) +{ + /* acl is non-trivial if it is non-empty. */ + return (acl_entries (acl) > 0); +} + +# else /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ + +/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. + Return -1 and set errno upon failure to determine it. */ +int +acl_access_nontrivial (acl_t acl) +{ + /* acl is non-trivial if it has some entries other than for "user::", + "group::", and "other::". Normally these three should be present + at least, allowing us to write + return (3 < acl_entries (acl)); + but the following code is more robust. */ +# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Cygwin >= 2.5 */ + + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one > 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + { + acl_tag_t tag; + if (acl_get_tag_type (ace, &tag) < 0) + return -1; + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) + return 1; + } + return got_one; + +# elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */ + /* Don't use acl_get_entry: it is undocumented. */ + + int count = acl->acl_cnt; + int i; + + for (i = 0; i < count; i++) + { + acl_entry_t ace = &acl->acl_entry[i]; + acl_tag_t tag = ace->ae_tag; + + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ + || tag == ACL_OTHER_OBJ)) + return 1; + } + return 0; + +# elif HAVE_ACL_FREE_TEXT /* Tru64 */ + /* Don't use acl_get_entry: it takes only one argument and does not work. */ + + int count = acl->acl_num; + acl_entry_t ace; + + for (ace = acl->acl_first; count > 0; ace = ace->next, count--) + { + acl_tag_t tag; + acl_perm_t perm; + + tag = ace->entry->acl_type; + if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) + return 1; + + perm = ace->entry->acl_perm; + /* On Tru64, perm can also contain non-standard bits such as + PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */ + if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0) + return 1; + } + return 0; + +# else + + errno = ENOSYS; + return -1; +# endif +} + +int +acl_default_nontrivial (acl_t acl) +{ + /* acl is non-trivial if it is non-empty. */ + return (acl_entries (acl) > 0); +} + +# endif + +#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ + +/* Test an ACL retrieved with GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, aclent_t *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + aclent_t *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ + || ace->a_type == GROUP_OBJ + || ace->a_type == OTHER_OBJ + /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry + sometimes. */ + || ace->a_type == CLASS_OBJ)) + return 1; + } + return 0; +} + +# ifdef ACE_GETACL + +/* A shortcut for a bitmask. */ +# define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA) + +/* Test an ACL retrieved with ACE_GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_ace_nontrivial (int count, ace_t *entries) +{ + int i; + + /* The flags in the ace_t structure changed in a binary incompatible way + when ACL_NO_TRIVIAL etc. were introduced in version 1.15. + How to distinguish the two conventions at runtime? + In the old convention, usually three ACEs have a_flags = ACE_OWNER / + ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new + convention, these values are not used. */ + int old_convention = 0; + + for (i = 0; i < count; i++) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) + { + old_convention = 1; + break; + } + + if (old_convention) + /* Running on Solaris 10. */ + for (i = 0; i < count; i++) + { + ace_t *ace = &entries[i]; + + /* Note: + If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat(). + If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat(). + We don't need to check ace->a_who in these cases. */ + if (!(ace->a_type == OLD_ALLOW + && (ace->a_flags == OLD_ACE_OWNER + || ace->a_flags == OLD_ACE_GROUP + || ace->a_flags == OLD_ACE_OTHER))) + return 1; + } + else + { + /* Running on Solaris 10 (newer version) or Solaris 11. */ + unsigned int access_masks[6] = + { + 0, /* owner@ deny */ + 0, /* owner@ allow */ + 0, /* group@ deny */ + 0, /* group@ allow */ + 0, /* everyone@ deny */ + 0 /* everyone@ allow */ + }; + + for (i = 0; i < count; i++) + { + ace_t *ace = &entries[i]; + unsigned int index1; + unsigned int index2; + + if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE) + index1 = 1; + else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE) + index1 = 0; + else + return 1; + + if (ace->a_flags == NEW_ACE_OWNER) + index2 = 0; + else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP)) + index2 = 2; + else if (ace->a_flags == NEW_ACE_EVERYONE) + index2 = 4; + else + return 1; + + access_masks[index1 + index2] |= ace->a_access_mask; + } + + /* The same bit shouldn't be both allowed and denied. */ + if (access_masks[0] & access_masks[1]) + return 1; + if (access_masks[2] & access_masks[3]) + return 1; + if (access_masks[4] & access_masks[5]) + return 1; + + /* Check minimum masks. */ + if ((NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER) + & ~ access_masks[1]) + return 1; + access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER); + if ((NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE) + & ~ access_masks[5]) + return 1; + access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE); + + /* Check the allowed or denied bits. */ + switch ((access_masks[0] | access_masks[1]) + & ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + switch ((access_masks[2] | access_masks[3]) + & ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + switch ((access_masks[4] | access_masks[5]) + & ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER)) + { + case 0: + case NEW_ACE_READ_DATA: + case NEW_ACE_WRITEA_DATA: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: + case NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: + break; + default: + return 1; + } + + /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are + either both allowed or both denied. */ + if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + } + + return 0; +} + +# endif + +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, struct acl_entry *entries) +{ + int i; + + if (count > 3) + return 1; + + for (i = 0; i < count; i++) + { + struct acl_entry *ace = &entries[i]; + + if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP) + return 1; + } + return 0; +} + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +aclv_nontrivial (int count, struct acl *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ + || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ + || ace->a_type == CLASS_OBJ + || ace->a_type == OTHER_OBJ)) + return 1; + } + return 0; +} + +# endif + +#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (struct acl *a) +{ + /* The normal way to iterate through an ACL is like this: + struct acl_entry *ace; + for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace)) + { + struct ace_id *aei; + switch (ace->ace_type) + { + case ACC_PERMIT: + case ACC_DENY: + case ACC_SPECIFY: + ...; + } + for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei)) + ... + } + */ + return (acl_last (a) != a->acl_ext ? 1 : 0); +} + +# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nfs4_nontrivial (nfs4_acl_int_t *a) +{ +# if 1 /* let's try this first */ + return (a->aclEntryN > 0 ? 1 : 0); +# else + int count = a->aclEntryN; + int i; + + for (i = 0; i < count; i++) + { + nfs4_ace_int_t *ace = &a->aclEntry[i]; + + if (!((ace->flags & ACE4_ID_SPECIAL) != 0 + && (ace->aceWho.special_whoid == ACE4_WHO_OWNER + || ace->aceWho.special_whoid == ACE4_WHO_GROUP + || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE) + && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE + && ace->aceFlags == 0 + && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY + | ACE4_WRITE_DATA | ACE4_ADD_FILE + | ACE4_EXECUTE)) == 0)) + return 1; + } + return 0; +# endif +} + +# endif + +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + +/* Test an ACL retrieved with ACL_GET. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, struct acl *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ + || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ + || ace->a_type == CLASS_OBJ + || ace->a_type == OTHER_OBJ)) + return 1; + } + return 0; +} + +#endif + +void +free_permission_context (struct permission_context *ctx) +{ +#if USE_ACL +# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + if (ctx->acl) + acl_free (ctx->acl); +# if !HAVE_ACL_TYPE_EXTENDED + if (ctx->default_acl) + acl_free (ctx->default_acl); +# endif + +# elif defined GETACL /* Solaris, Cygwin < 2.5 */ + free (ctx->entries); +# ifdef ACE_GETACL + free (ctx->ace_entries); +# endif + +# elif HAVE_GETACL /* HP-UX */ + +# if HAVE_ACLV_H +# endif + +# elif HAVE_STATACL /* older AIX */ + +# elif HAVE_ACLSORT /* NonStop Kernel */ + +# endif +#endif +} diff --git a/cross/lib/acl-internal.h b/cross/lib/acl-internal.h new file mode 100644 index 00000000000..c97e847cdc5 --- /dev/null +++ b/cross/lib/acl-internal.h @@ -0,0 +1,301 @@ +/* Internal implementation of access control lists. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include "acl.h" + +#include + +/* All systems define the ACL related API in . */ +#if HAVE_SYS_ACL_H +# include +#endif +#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT +# define GETACLCNT ACL_CNT +#endif + +/* On Linux and Cygwin >= 2.5, additional ACL related API is available in + . */ +#ifdef HAVE_ACL_LIBACL_H +# include +#endif + +/* On HP-UX >= 11.11, additional ACL API is available in . */ +#if HAVE_ACLV_H +# include +# include +/* HP-UX 11.11 lacks these declarations. */ +extern int acl (char *, int, int, struct acl *); +extern int aclsort (int, int, struct acl *); +#endif + +#include + +#include +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#ifndef HAVE_FCHMOD +# define HAVE_FCHMOD false +# define fchmod(fd, mode) (-1) +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef ACL_INTERNAL_INLINE +# define ACL_INTERNAL_INLINE _GL_INLINE +#endif + +#if USE_ACL + +# if HAVE_ACL_GET_FILE +/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ +/* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + +# ifndef MIN_ACL_ENTRIES +# define MIN_ACL_ENTRIES 4 +# endif + +/* POSIX 1003.1e (draft 17) */ +# ifdef HAVE_ACL_GET_FD +/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument + macro(!). */ +# if HAVE_ACL_FREE_TEXT /* OSF/1 */ +ACL_INTERNAL_INLINE acl_t +rpl_acl_get_fd (int fd) +{ + return acl_get_fd (fd, ACL_TYPE_ACCESS); +} +# undef acl_get_fd +# define acl_get_fd rpl_acl_get_fd +# endif +# else +# define HAVE_ACL_GET_FD false +# undef acl_get_fd +# define acl_get_fd(fd) (NULL) +# endif + +/* POSIX 1003.1e (draft 17) */ +# ifdef HAVE_ACL_SET_FD +/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument + macro(!). */ +# if HAVE_ACL_FREE_TEXT /* OSF/1 */ +ACL_INTERNAL_INLINE int +rpl_acl_set_fd (int fd, acl_t acl) +{ + return acl_set_fd (fd, ACL_TYPE_ACCESS, acl); +} +# undef acl_set_fd +# define acl_set_fd rpl_acl_set_fd +# endif +# else +# define HAVE_ACL_SET_FD false +# undef acl_set_fd +# define acl_set_fd(fd, acl) (-1) +# endif + +/* POSIX 1003.1e (draft 13) */ +# if ! HAVE_ACL_FREE_TEXT +# define acl_free_text(buf) acl_free (buf) +# endif + +/* Linux-specific */ +/* Cygwin >= 2.5 implements this function, but it returns 1 for all + directories, thus is unusable. */ +# if !defined HAVE_ACL_EXTENDED_FILE || defined __CYGWIN__ +# undef HAVE_ACL_EXTENDED_FILE +# define HAVE_ACL_EXTENDED_FILE false +# define acl_extended_file(name) (-1) +# endif + +# if ! defined HAVE_ACL_FROM_MODE && ! defined HAVE_ACL_FROM_TEXT +# define acl_from_mode (NULL) +# endif + +/* Set to 0 if a file's mode is stored independently from the ACL. */ +# if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */ +# define MODE_INSIDE_ACL 0 +# endif + +/* Return the number of entries in ACL. + Return -1 and set errno upon failure to determine it. */ +/* Define a replacement for acl_entries if needed. (Only Linux has it.) */ +# if !HAVE_ACL_ENTRIES +# define acl_entries rpl_acl_entries +extern int acl_entries (acl_t); +# endif + +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ +/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial. */ +extern int acl_extended_nontrivial (acl_t); +# else +/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. + Return -1 and set errno upon failure to determine it. */ +extern int acl_access_nontrivial (acl_t); + +/* ACL is an ACL, from a file, stored as type ACL_TYPE_DEFAULT. + Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. + Return -1 and set errno upon failure to determine it. */ +extern int acl_default_nontrivial (acl_t); +# endif + +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ + +/* Set to 0 if a file's mode is stored independently from the ACL. */ +# if defined __CYGWIN__ /* Cygwin */ +# define MODE_INSIDE_ACL 0 +# endif + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE; + +# ifdef ACE_GETACL /* Solaris 10 */ + +/* Test an ACL retrieved with ACE_GETACL. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE; + +/* Definitions for when the built executable is executed on Solaris 10 + (newer version) or Solaris 11. */ +/* For a_type. */ +# define OLD_ALLOW 0 +# define OLD_DENY 1 +# define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */ +# define NEW_ACE_ACCESS_DENIED_ACE_TYPE 1 /* replaces DENY */ +/* For a_flags. */ +# define OLD_ACE_OWNER 0x0100 +# define OLD_ACE_GROUP 0x0200 +# define OLD_ACE_OTHER 0x0400 +# define NEW_ACE_OWNER 0x1000 +# define NEW_ACE_GROUP 0x2000 +# define NEW_ACE_IDENTIFIER_GROUP 0x0040 +# define NEW_ACE_EVERYONE 0x4000 +/* For a_access_mask. */ +# define NEW_ACE_READ_DATA 0x001 /* corresponds to 'r' */ +# define NEW_ACE_WRITE_DATA 0x002 /* corresponds to 'w' */ +# define NEW_ACE_APPEND_DATA 0x004 +# define NEW_ACE_READ_NAMED_ATTRS 0x008 +# define NEW_ACE_WRITE_NAMED_ATTRS 0x010 +# define NEW_ACE_EXECUTE 0x020 +# define NEW_ACE_DELETE_CHILD 0x040 +# define NEW_ACE_READ_ATTRIBUTES 0x080 +# define NEW_ACE_WRITE_ATTRIBUTES 0x100 +# define NEW_ACE_DELETE 0x10000 +# define NEW_ACE_READ_ACL 0x20000 +# define NEW_ACE_WRITE_ACL 0x40000 +# define NEW_ACE_WRITE_OWNER 0x80000 +# define NEW_ACE_SYNCHRONIZE 0x100000 + +# endif + +# elif HAVE_GETACL /* HP-UX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, struct acl_entry *entries); + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int aclv_nontrivial (int count, struct acl *entries); + +# endif + +# elif HAVE_ACLX_GET && 0 /* AIX */ + +/* TODO */ + +# elif HAVE_STATACL /* older AIX */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (struct acl *a); + +# elif HAVE_ACLSORT /* NonStop Kernel */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, struct acl *entries); + +# endif + +/* Set to 1 if a file's mode is implicit by the ACL. */ +# ifndef MODE_INSIDE_ACL +# define MODE_INSIDE_ACL 1 +# endif + +#endif + +struct permission_context { + mode_t mode; +#if USE_ACL +# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + acl_t acl; +# if !HAVE_ACL_TYPE_EXTENDED + acl_t default_acl; +# endif + bool acls_not_supported; + +# elif defined GETACL /* Solaris, Cygwin < 2.5 */ + int count; + aclent_t *entries; +# ifdef ACE_GETACL + int ace_count; + ace_t *ace_entries; +# endif + +# elif HAVE_GETACL /* HP-UX */ + struct acl_entry entries[NACLENTRIES]; + int count; +# if HAVE_ACLV_H + struct acl aclv_entries[NACLVENTRIES]; + int aclv_count; +# endif + +# elif HAVE_STATACL /* older AIX */ + union { struct acl a; char room[4096]; } u; + bool have_u; + +# elif HAVE_ACLSORT /* NonStop Kernel */ + struct acl entries[NACLENTRIES]; + int count; + +# endif +#endif +}; + +int get_permissions (const char *, int, mode_t, struct permission_context *); +int set_permissions (struct permission_context *, const char *, int); +void free_permission_context (struct permission_context *); + +_GL_INLINE_HEADER_END diff --git a/cross/lib/acl.h b/cross/lib/acl.h new file mode 100644 index 00000000000..58e5797179e --- /dev/null +++ b/cross/lib/acl.h @@ -0,0 +1,34 @@ +/* acl.c - access control lists + + Copyright (C) 2002, 2008-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert. */ + +#ifndef _GL_ACL_H +#define _GL_ACL_H 1 + +#include +#include + +bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; +int file_has_acl (char const *, struct stat const *); +int qset_acl (char const *, int, mode_t); +int set_acl (char const *, int, mode_t); +int qcopy_acl (char const *, int, char const *, int, mode_t); +int copy_acl (char const *, int, char const *, int, mode_t); +int chmod_or_fchmod (char const *, int, mode_t); + +#endif diff --git a/cross/lib/acl_entries.c b/cross/lib/acl_entries.c new file mode 100644 index 00000000000..a59ace3f404 --- /dev/null +++ b/cross/lib/acl_entries.c @@ -0,0 +1,75 @@ +/* Return the number of entries in an ACL. + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert and Andreas Gruenbacher. */ + +#include + +#include "acl-internal.h" + +/* This file assumes POSIX-draft like ACLs + (Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5). */ + +/* Return the number of entries in ACL. + Return -1 and set errno upon failure to determine it. */ + +int +acl_entries (acl_t acl) +{ + int count = 0; + + if (acl != NULL) + { +#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X, Cygwin >= 2.5 */ +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + /* acl_get_entry returns 0 when it successfully fetches an entry, + and -1/EINVAL at the end. */ + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one >= 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + count++; +# else /* Linux, FreeBSD, Cygwin >= 2.5 */ + /* acl_get_entry returns 1 when it successfully fetches an entry, + and 0 at the end. */ + acl_entry_t ace; + int got_one; + + for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); + got_one > 0; + got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) + count++; + if (got_one < 0) + return -1; +# endif +#else /* IRIX, Tru64 */ +# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */ + /* Don't use acl_get_entry: it is undocumented. */ + count = acl->acl_cnt; +# endif +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + /* Don't use acl_get_entry: it takes only one argument and does not + work. */ + count = acl->acl_num; +# endif +#endif + } + + return count; +} diff --git a/cross/lib/af_alg.h b/cross/lib/af_alg.h new file mode 100644 index 00000000000..e8ffb3f7a09 --- /dev/null +++ b/cross/lib/af_alg.h @@ -0,0 +1,115 @@ +/* af_alg.h - Compute message digests from file streams and buffers. + Copyright (C) 2018-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Matteo Croce , 2018. + Documentation by Bruno Haible , 2018. */ + +/* Declare specific functions for computing message digests + using the Linux kernel crypto API, if available. This kernel API gives + access to specialized crypto instructions (that would also be available + in user space) or to crypto devices (not directly available in user space). + + For a more complete set of facilities that use the Linux kernel crypto API, + look at libkcapi. */ + +#ifndef AF_ALG_H +# define AF_ALG_H 1 + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_LINUX_CRYPTO_API + +/* Compute a message digest of a memory region. + + The memory region starts at BUFFER and is LEN bytes long. + + ALG is the message digest algorithm; see the file /proc/crypto. + + RESBLOCK points to a block of HASHLEN bytes, for the result. + HASHLEN must be the length of the message digest, in bytes, in particular: + + alg | hashlen + -------+-------- + md5 | 16 + sha1 | 20 + sha224 | 28 + sha256 | 32 + sha384 | 48 + sha512 | 64 + + If successful, fill RESBLOCK and return 0. + Upon failure, return a negated error number. */ +int +afalg_buffer (const char *buffer, size_t len, const char *alg, + void *resblock, ssize_t hashlen); + +/* Compute a message digest of data read from STREAM. + + STREAM is an open file stream. The last operation on STREAM should + not be 'ungetc', and if STREAM is also open for writing it should + have been fflushed since its last write. Read from the current + position to the end of STREAM. Handle regular files efficiently. + + ALG is the message digest algorithm; see the file /proc/crypto. + + RESBLOCK points to a block of HASHLEN bytes, for the result. + HASHLEN must be the length of the message digest, in bytes, in particular: + + alg | hashlen + -------+-------- + md5 | 16 + sha1 | 20 + sha224 | 28 + sha256 | 32 + sha384 | 48 + sha512 | 64 + + If successful, fill RESBLOCK and return 0. + Upon failure, return a negated error number. + Unless returning 0 or -EIO, restore STREAM's file position so that + the caller can fall back on some other method. */ +int +afalg_stream (FILE *stream, const char *alg, + void *resblock, ssize_t hashlen); + +# else + +static inline int +afalg_buffer (const char *buffer, size_t len, const char *alg, + void *resblock, ssize_t hashlen) +{ + return -EAFNOSUPPORT; +} + +static inline int +afalg_stream (FILE *stream, const char *alg, + void *resblock, ssize_t hashlen) +{ + return -EAFNOSUPPORT; +} + +# endif + +# ifdef __cplusplus +} +# endif + +#endif /* AF_ALG_H */ diff --git a/cross/lib/alloca.in.h b/cross/lib/alloca.in.h new file mode 100644 index 00000000000..a1bb3d758dc --- /dev/null +++ b/cross/lib/alloca.in.h @@ -0,0 +1,72 @@ +/* Memory allocation on the stack. + + Copyright (C) 1995, 1999, 2001-2004, 2006-2023 Free Software Foundation, + Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H + means there is a real alloca function. */ +#ifndef _GL_ALLOCA_H +#define _GL_ALLOCA_H + +/* alloca (N) returns a pointer to N bytes of memory + allocated on the stack, which will last until the function returns. + Use of alloca should be avoided: + - inside arguments of function calls - undefined behaviour, + - in inline functions - the allocation may actually last until the + calling function returns, + - for huge N (say, N >= 65536) - you never know how large (or small) + the stack is, and when the stack cannot fulfill the memory allocation + request, the program just crashes. + */ + +#ifndef alloca + /* Some version of mingw have an that causes trouble when + included after 'alloca' gets defined as a macro. As a workaround, + include this first and define 'alloca' as a macro afterwards + if needed. */ +# if defined __GNUC__ && (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@ +# include_next +# endif +#endif +#ifndef alloca +# if defined __GNUC__ || (__clang_major__ >= 4) +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include +# define alloca _alloca +# elif defined __DECC && defined __VMS +# define alloca __ALLOCA +# elif defined __TANDEM && defined _TNS_E_TARGET +# ifdef __cplusplus +extern "C" +# endif +void *_alloca (unsigned short); +# pragma intrinsic (_alloca) +# define alloca _alloca +# elif defined __MVS__ +# include +# else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#endif /* _GL_ALLOCA_H */ diff --git a/cross/lib/allocator.c b/cross/lib/allocator.c new file mode 100644 index 00000000000..922be1fce8d --- /dev/null +++ b/cross/lib/allocator.c @@ -0,0 +1,22 @@ +/* Memory allocators such as malloc+free. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include +#include "allocator.h" +#include +struct allocator const stdlib_allocator = { malloc, realloc, free, NULL }; diff --git a/cross/lib/allocator.h b/cross/lib/allocator.h new file mode 100644 index 00000000000..0c830d01cda --- /dev/null +++ b/cross/lib/allocator.h @@ -0,0 +1,58 @@ +/* Memory allocators such as malloc+free. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_ALLOCATOR_H +#define _GL_ALLOCATOR_H + +#include + +/* An object describing a memory allocator family. */ + +struct allocator +{ + /* Do not use GCC attributes such as __attribute__ ((malloc)) with + the function types pointed at by these members, because these + attributes do not work with pointers to functions. See + . */ + + /* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE + should return NULL, though not necessarily set errno. When given + a zero size it may return NULL even if successful. */ + void *(*allocate) (size_t); + + /* If nonnull, call REALLOCATE to reallocate memory, like 'realloc'. + On failure REALLOCATE should return NULL, though not necessarily set + errno. When given a zero size it may return NULL even if + successful. */ + void *(*reallocate) (void *, size_t); + + /* Call FREE to free memory, like 'free'. */ + void (*free) (void *); + + /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (..., + SIZE) fails. DIE should not return. SIZE should equal SIZE_MAX + if size_t overflow was detected while calculating sizes to be + passed to MALLOC or REALLOC. */ + void (*die) (size_t); +}; + +/* An allocator using the stdlib functions and a null DIE function. */ +extern struct allocator const stdlib_allocator; + +#endif /* _GL_ALLOCATOR_H */ diff --git a/cross/lib/arg-nonnull.h b/cross/lib/arg-nonnull.h new file mode 100644 index 00000000000..9498ae1f7da --- /dev/null +++ b/cross/lib/arg-nonnull.h @@ -0,0 +1,26 @@ +/* A C macro for declaring that specific arguments must not be NULL. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 program. If not, see . */ + +/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools + that the values passed as arguments n, ..., m must be non-NULL pointers. + n = 1 stands for the first argument, n = 2 for the second argument etc. */ +#ifndef _GL_ARG_NONNULL +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__ +# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) +# else +# define _GL_ARG_NONNULL(params) +# endif +#endif diff --git a/cross/lib/assert.in.h b/cross/lib/assert.in.h new file mode 100644 index 00000000000..b0ab99c776e --- /dev/null +++ b/cross/lib/assert.in.h @@ -0,0 +1,27 @@ +/* Substitute for and wrapper around + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Do not guard the include, since is supposed to define + the assert macro each time it is included. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#@INCLUDE_NEXT@ @NEXT_ASSERT_H@ + +/* The definition of static_assert is copied here. */ diff --git a/cross/lib/at-func.c b/cross/lib/at-func.c new file mode 100644 index 00000000000..13e3fb32056 --- /dev/null +++ b/cross/lib/at-func.c @@ -0,0 +1,146 @@ +/* Define at-style functions like fstatat, unlinkat, fchownat, etc. + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Jim Meyering */ + +#include "filename.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ + +#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD +# include +# ifndef ENOTSUP +# define ENOTSUP EINVAL +# endif +#else +# include "openat.h" +# include "openat-priv.h" +# include "save-cwd.h" +#endif + +#ifdef AT_FUNC_USE_F1_COND +# define CALL_FUNC(F) \ + (flag == AT_FUNC_USE_F1_COND \ + ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ + : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) \ + if (flag & ~AT_FUNC_USE_F1_COND) \ + { \ + errno = EINVAL; \ + return FUNC_FAIL; \ + } +#else +# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) /* empty */ +#endif + +#ifdef AT_FUNC_RESULT +# define FUNC_RESULT AT_FUNC_RESULT +#else +# define FUNC_RESULT int +#endif + +#ifdef AT_FUNC_FAIL +# define FUNC_FAIL AT_FUNC_FAIL +#else +# define FUNC_FAIL -1 +#endif + +/* Call AT_FUNC_F1 to operate on FILE, which is in the directory + open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, + AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag; + call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than + AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT + or AT_FUNC_FAIL are defined. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, + then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ +FUNC_RESULT +AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) +{ + VALIDATE_FLAG (flag); + + if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) + return CALL_FUNC (file); + +#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD + errno = ENOTSUP; + return FUNC_FAIL; +#else + { + /* Be careful to choose names unlikely to conflict with + AT_FUNC_POST_FILE_PARAM_DECLS. */ + struct saved_cwd saved_cwd; + int saved_errno; + FUNC_RESULT err; + + { + char proc_buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (proc_buf, fd, file); + if (proc_file) + { + FUNC_RESULT proc_result = CALL_FUNC (proc_file); + int proc_errno = errno; + if (proc_file != proc_buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (FUNC_FAIL != proc_result) + return proc_result; + if (! EXPECTED_ERRNO (proc_errno)) + { + errno = proc_errno; + return proc_result; + } + } + } + + if (save_cwd (&saved_cwd) != 0) + openat_save_fail (errno); + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return FUNC_FAIL; + } + + if (fchdir (fd) != 0) + { + saved_errno = errno; + free_cwd (&saved_cwd); + errno = saved_errno; + return FUNC_FAIL; + } + + err = CALL_FUNC (file); + saved_errno = (err == FUNC_FAIL ? errno : 0); + + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + + free_cwd (&saved_cwd); + + if (saved_errno) + errno = saved_errno; + return err; + } +#endif +} +#undef CALL_FUNC +#undef FUNC_RESULT +#undef FUNC_FAIL diff --git a/cross/lib/attribute.h b/cross/lib/attribute.h new file mode 100644 index 00000000000..130644d8798 --- /dev/null +++ b/cross/lib/attribute.h @@ -0,0 +1,226 @@ +/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers + + Copyright 2020-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_* + macros used within Gnulib. */ + +/* These attributes can be placed in two ways: + - At the start of a declaration (i.e. even before storage-class + specifiers!); then they apply to all entities that are declared + by the declaration. + - Immediately after the name of an entity being declared by the + declaration; then they apply to that entity only. */ + +#ifndef _GL_ATTRIBUTE_H +#define _GL_ATTRIBUTE_H + + +/* This file defines two types of attributes: + * C23 standard attributes. These have macro names that do not begin with + 'ATTRIBUTE_'. + * Selected GCC attributes; see: + https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html + https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html + https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html + These names begin with 'ATTRIBUTE_' to avoid name clashes. */ + + +/* =============== Attributes for specific kinds of functions =============== */ + +/* Attributes for functions that should not be used. */ + +/* Warn if the entity is used. */ +/* Applies to: + - function, variable, + - struct, union, struct/union member, + - enumeration, enumeration item, + - typedef, + in C++ also: namespace, class, template specialization. */ +#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED + +/* If a function call is not optimized way, warn with MSG. */ +/* Applies to: functions. */ +#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg) + +/* If a function call is not optimized way, report an error with MSG. */ +/* Applies to: functions. */ +#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg) + + +/* Attributes for memory-allocating functions. */ + +/* The function returns a pointer to freshly allocated memory. */ +/* Applies to: functions. */ +#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC + +/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function + is the size of the returned memory block. + ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments + to determine the size of the returned memory block. */ +/* Applies to: function, pointer to function, function types. */ +#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args) + +/* ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. + ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that + can be freed via 'free'; it can be used only after declaring 'free'. */ +/* Applies to: functions. Cannot be used on inline functions. */ +#define ATTRIBUTE_DEALLOC(f, i) _GL_ATTRIBUTE_DEALLOC(f, i) +#define ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC_FREE + +/* Attributes for variadic functions. */ + +/* The variadic function expects a trailing NULL argument. + ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99). + ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */ +/* Applies to: functions. */ +#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos) + + +/* ================== Attributes for compiler diagnostics ================== */ + +/* Attributes that help the compiler diagnose programmer mistakes. + Some of them may also help for some compiler optimizations. */ + +/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) - + The STRING-INDEXth function argument is a format string of style + ARCHETYPE, which is one of: + printf, gnu_printf + scanf, gnu_scanf, + strftime, gnu_strftime, + strfmon, + or the same thing prefixed and suffixed with '__'. + If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK + are suitable for the format string. */ +/* Applies to: functions. */ +#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec) + +/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL. + ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args) + +/* The function's return value is a non-NULL pointer. */ +/* Applies to: functions. */ +#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL + +/* Warn if the caller does not use the return value, + unless the caller uses something like ignore_value. */ +/* Applies to: function, enumeration, class. */ +#define NODISCARD _GL_ATTRIBUTE_NODISCARD + + +/* Attributes that disable false alarms when the compiler diagnoses + programmer "mistakes". */ + +/* Do not warn if the entity is not used. */ +/* Applies to: + - function, variable, + - struct, union, struct/union member, + - enumeration, enumeration item, + - typedef, + in C++ also: class. */ +#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED + +/* The contents of a character array is not meant to be NUL-terminated. */ +/* Applies to: struct/union members and variables that are arrays of element + type '[[un]signed] char'. */ +#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING + +/* Do not warn if control flow falls through to the immediately + following 'case' or 'default' label. */ +/* Applies to: Empty statement (;), inside a 'switch' statement. */ +#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH + + +/* ================== Attributes for debugging information ================== */ + +/* Attributes regarding debugging information emitted by the compiler. */ + +/* Omit the function from stack traces when debugging. */ +/* Applies to: function. */ +#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL + +/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */ +/* Applies to: functions, variables. */ +#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE + + +/* ========== Attributes that mainly direct compiler optimizations ========== */ + +/* The function does not throw exceptions. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW + +/* Do not inline the function. */ +/* Applies to: functions. */ +#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE + +/* Always inline the function, and report an error if the compiler + cannot inline. */ +/* Applies to: function. */ +#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE + +/* It is OK for a compiler to omit duplicate calls with the same arguments. + This attribute is safe for a function that neither depends on + nor affects observable state, and always returns exactly once - + e.g., does not loop forever, and does not call longjmp. + (This attribute is stricter than ATTRIBUTE_PURE.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST + +/* It is OK for a compiler to omit duplicate calls with the same + arguments if observable state is not changed between calls. + This attribute is safe for a function that does not affect + observable state, and always returns exactly once. + (This attribute is looser than ATTRIBUTE_CONST.) */ +/* Applies to: functions. */ +#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE + +/* The function is rarely executed. */ +/* Applies to: functions. */ +#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD + +/* If called from some other compilation unit, the function executes + code from that unit only by return or by exception handling, + letting the compiler optimize that unit more aggressively. */ +/* Applies to: functions. */ +#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF + +/* For struct members: The member has the smallest possible alignment. + For struct, union, class: All members have the smallest possible alignment, + minimizing the memory required. */ +/* Applies to: struct members, struct, union, + in C++ also: class. */ +#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED + + +/* ================ Attributes that make invalid code valid ================ */ + +/* Attributes that prevent fatal compiler optimizations for code that is not + fully ISO C compliant. */ + +/* Pointers to the type may point to the same storage as pointers to + other types, thus disabling strict aliasing optimization. */ +/* Applies to: types. */ +#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS + + +#endif /* _GL_ATTRIBUTE_H */ diff --git a/cross/lib/binary-io.c b/cross/lib/binary-io.c new file mode 100644 index 00000000000..28a9e6ed69c --- /dev/null +++ b/cross/lib/binary-io.c @@ -0,0 +1,39 @@ +/* Binary mode I/O. + Copyright 2017-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define BINARY_IO_INLINE _GL_EXTERN_INLINE +#include "binary-io.h" + +#if defined __DJGPP__ || defined __EMX__ +# include + +int +set_binary_mode (int fd, int mode) +{ + if (isatty (fd)) + /* If FD refers to a console (not a pipe, not a regular file), + O_TEXT is the only reasonable mode, both on input and on output. + Silently ignore the request. If we were to return -1 here, + all programs that use xset_binary_mode would fail when run + with console input or console output. */ + return O_TEXT; + else + return __gl_setmode (fd, mode); +} + +#endif diff --git a/cross/lib/binary-io.h b/cross/lib/binary-io.h new file mode 100644 index 00000000000..6f4db253354 --- /dev/null +++ b/cross/lib/binary-io.h @@ -0,0 +1,77 @@ +/* Binary mode I/O. + Copyright (C) 2001, 2003, 2005, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _BINARY_H +#define _BINARY_H + +/* For systems that distinguish between text and binary I/O. + O_BINARY is guaranteed by the gnulib . */ +#include + +/* The MSVC7 doesn't like to be included after '#define fileno ...', + so we include it here first. */ +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef BINARY_IO_INLINE +# define BINARY_IO_INLINE _GL_INLINE +#endif + +#if O_BINARY +# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__ +# include /* declares setmode() */ +# define __gl_setmode setmode +# else +# define __gl_setmode _setmode +# undef fileno +# define fileno _fileno +# endif +#else + /* On reasonable systems, binary I/O is the only choice. */ + /* Use a function rather than a macro, to avoid gcc warnings + "warning: statement with no effect". */ +BINARY_IO_INLINE int +__gl_setmode (_GL_UNUSED int fd, _GL_UNUSED int mode) +{ + return O_BINARY; +} +#endif + +/* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY. + Return the old mode if successful, -1 (setting errno) on failure. + Ordinarily this function would be called 'setmode', since that is + its old name on MS-Windows, but it is called 'set_binary_mode' here + to avoid colliding with a BSD function of another name. */ + +#if defined __DJGPP__ || defined __EMX__ +extern int set_binary_mode (int fd, int mode); +#else +BINARY_IO_INLINE int +set_binary_mode (int fd, int mode) +{ + return __gl_setmode (fd, mode); +} +#endif + +/* This macro is obsolescent. */ +#define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY)) + +_GL_INLINE_HEADER_END + +#endif /* _BINARY_H */ diff --git a/cross/lib/byteswap.in.h b/cross/lib/byteswap.in.h new file mode 100644 index 00000000000..e61be27e917 --- /dev/null +++ b/cross/lib/byteswap.in.h @@ -0,0 +1,44 @@ +/* byteswap.h - Byte swapping + Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc. + Written by Oskar Liljeblad , 2005. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GL_BYTESWAP_H +#define _GL_BYTESWAP_H + +/* Given an unsigned 16-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_16(x) ((((x) & 0x00FF) << 8) | \ + (((x) & 0xFF00) >> 8)) + +/* Given an unsigned 32-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | \ + (((x) & 0xFF000000) >> 24)) + +/* Given an unsigned 64-bit argument X, return the value corresponding to + X with reversed byte order. */ +#define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ + (((x) & 0x000000000000FF00ULL) << 40) | \ + (((x) & 0x0000000000FF0000ULL) << 24) | \ + (((x) & 0x00000000FF000000ULL) << 8) | \ + (((x) & 0x000000FF00000000ULL) >> 8) | \ + (((x) & 0x0000FF0000000000ULL) >> 24) | \ + (((x) & 0x00FF000000000000ULL) >> 40) | \ + (((x) & 0xFF00000000000000ULL) >> 56)) + +#endif /* _GL_BYTESWAP_H */ diff --git a/cross/lib/c++defs.h b/cross/lib/c++defs.h new file mode 100644 index 00000000000..8ad46951ad4 --- /dev/null +++ b/cross/lib/c++defs.h @@ -0,0 +1,331 @@ +/* C++ compatible function declaration macros. + Copyright (C) 2010-2023 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GL_CXXDEFS_H +#define _GL_CXXDEFS_H + +/* Begin/end the GNULIB_NAMESPACE namespace. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE { +# define _GL_END_NAMESPACE } +#else +# define _GL_BEGIN_NAMESPACE +# define _GL_END_NAMESPACE +#endif + +/* The three most frequent use cases of these macros are: + + * For providing a substitute for a function that is missing on some + platforms, but is declared and works fine on the platforms on which + it exists: + + #if @GNULIB_FOO@ + # if !@HAVE_FOO@ + _GL_FUNCDECL_SYS (foo, ...); + # endif + _GL_CXXALIAS_SYS (foo, ...); + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif + + * For providing a replacement for a function that exists on all platforms, + but is broken/insufficient and needs to be replaced on some platforms: + + #if @GNULIB_FOO@ + # if @REPLACE_FOO@ + # if !(defined __cplusplus && defined GNULIB_NAMESPACE) + # undef foo + # define foo rpl_foo + # endif + _GL_FUNCDECL_RPL (foo, ...); + _GL_CXXALIAS_RPL (foo, ...); + # else + _GL_CXXALIAS_SYS (foo, ...); + # endif + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif + + * For providing a replacement for a function that exists on some platforms + but is broken/insufficient and needs to be replaced on some of them and + is additionally either missing or undeclared on some other platforms: + + #if @GNULIB_FOO@ + # if @REPLACE_FOO@ + # if !(defined __cplusplus && defined GNULIB_NAMESPACE) + # undef foo + # define foo rpl_foo + # endif + _GL_FUNCDECL_RPL (foo, ...); + _GL_CXXALIAS_RPL (foo, ...); + # else + # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ + _GL_FUNCDECL_SYS (foo, ...); + # endif + _GL_CXXALIAS_SYS (foo, ...); + # endif + _GL_CXXALIASWARN (foo); + #elif defined GNULIB_POSIXCHECK + ... + #endif +*/ + +/* _GL_EXTERN_C declaration; + performs the declaration with C linkage. */ +#if defined __cplusplus +# define _GL_EXTERN_C extern "C" +#else +# define _GL_EXTERN_C extern +#endif + +/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); + declares a replacement function, named rpl_func, with the given prototype, + consisting of return type, parameters, and attributes. + Example: + _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); + */ +#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ + _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) +#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C rettype rpl_func parameters_and_attributes + +/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); + declares the system function, named func, with the given prototype, + consisting of return type, parameters, and attributes. + Example: + _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); + */ +#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C rettype func parameters_and_attributes + +/* _GL_CXXALIAS_RPL (func, rettype, parameters); + declares a C++ alias called GNULIB_NAMESPACE::func + that redirects to rpl_func, if GNULIB_NAMESPACE is defined. + Example: + _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); + + Wrapping rpl_func in an object with an inline conversion operator + avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is + actually used in the program. */ +#define _GL_CXXALIAS_RPL(func,rettype,parameters) \ + _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return ::rpl_func; \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_MDA (func, rettype, parameters); + is to be used when func is a Microsoft deprecated alias, on native Windows. + It declares a C++ alias called GNULIB_NAMESPACE::func + that redirects to _func, if GNULIB_NAMESPACE is defined. + Example: + _GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); + */ +#define _GL_CXXALIAS_MDA(func,rettype,parameters) \ + _GL_CXXALIAS_RPL_1 (func, _##func, rettype, parameters) + +/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); + is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); + except that the C function rpl_func may have a slightly different + declaration. A cast is used to silence the "invalid conversion" error + that would otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast(::rpl_func); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_MDA_CAST (func, rettype, parameters); + is like _GL_CXXALIAS_MDA (func, rettype, parameters); + except that the C function func may have a slightly different declaration. + A cast is used to silence the "invalid conversion" error that would + otherwise occur. */ +#define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \ + _GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters) + +/* _GL_CXXALIAS_SYS (func, rettype, parameters); + declares a C++ alias called GNULIB_NAMESPACE::func + that redirects to the system provided function func, if GNULIB_NAMESPACE + is defined. + Example: + _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); + + Wrapping func in an object with an inline conversion operator + avoids a reference to func unless GNULIB_NAMESPACE::func is + actually used in the program. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return ::func; \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); + is like _GL_CXXALIAS_SYS (func, rettype, parameters); + except that the C function func may have a slightly different declaration. + A cast is used to silence the "invalid conversion" error that would + otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast(::func); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); + is like _GL_CXXALIAS_SYS (func, rettype, parameters); + except that the C function is picked among a set of overloaded functions, + namely the one with rettype2 and parameters2. Two consecutive casts + are used to silence the "cannot find a match" and "invalid conversion" + errors that would otherwise occur. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE + /* The outer cast must be a reinterpret_cast. + The inner cast: When the function is defined as a set of overloaded + functions, it works as a static_cast<>, choosing the designated variant. + When the function is defined as a single variant, it works as a + reinterpret_cast<>. The parenthesized cast syntax works both ways. */ +# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ + namespace GNULIB_NAMESPACE \ + { \ + static const struct _gl_ ## func ## _wrapper \ + { \ + typedef rettype (*type) parameters; \ + \ + inline operator type () const \ + { \ + return reinterpret_cast((rettype2 (*) parameters2)(::func)); \ + } \ + } func = {}; \ + } \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#else +# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIASWARN (func); + causes a warning to be emitted when ::func is used but not when + GNULIB_NAMESPACE::func is used. func must be defined without overloaded + variants. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIASWARN(func) \ + _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) +# define _GL_CXXALIASWARN_1(func,namespace) \ + _GL_CXXALIASWARN_2 (func, namespace) +/* To work around GCC bug , + we enable the warning only when not optimizing. */ +# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_WARN_ON_USE (func, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +# define _GL_CXXALIASWARN_2(func,namespace) \ + extern __typeof__ (func) func +# else +# define _GL_CXXALIASWARN_2(func,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif +#else +# define _GL_CXXALIASWARN(func) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); + causes a warning to be emitted when the given overloaded variant of ::func + is used but not when GNULIB_NAMESPACE::func is used. */ +#if defined __cplusplus && defined GNULIB_NAMESPACE +# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ + _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ + GNULIB_NAMESPACE) +# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ + _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) +/* To work around GCC bug , + we enable the warning only when not optimizing. */ +# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \ + "The symbol ::" #func " refers to the system function. " \ + "Use " #namespace "::" #func " instead.") +# else +# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +# endif +#else +# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ + _GL_EXTERN_C int _gl_cxxalias_dummy +#endif + +#endif /* _GL_CXXDEFS_H */ diff --git a/cross/lib/c-ctype.c b/cross/lib/c-ctype.c new file mode 100644 index 00000000000..a4343f445f0 --- /dev/null +++ b/cross/lib/c-ctype.c @@ -0,0 +1,21 @@ +/* Character handling in C locale. + + Copyright (C) 2003-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define C_CTYPE_INLINE _GL_EXTERN_INLINE +#include "c-ctype.h" diff --git a/cross/lib/c-ctype.h b/cross/lib/c-ctype.h new file mode 100644 index 00000000000..35ca83d7d43 --- /dev/null +++ b/cross/lib/c-ctype.h @@ -0,0 +1,364 @@ +/* Character handling in C locale. + + These functions work like the corresponding functions in , + except that they have the C (POSIX) locale hardwired, whereas the + functions' behaviour depends on the current locale set via + setlocale. + + Copyright (C) 2000-2003, 2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef C_CTYPE_H +#define C_CTYPE_H + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef C_CTYPE_INLINE +# define C_CTYPE_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* The functions defined in this file assume the "C" locale and a character + set without diacritics (ASCII-US or EBCDIC-US or something like that). + Even if the "C" locale on a particular system is an extension of the ASCII + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it + is ISO-8859-1), the functions in this file recognize only the ASCII + characters. */ + + +#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) +/* The character set is ASCII or one of its variants or extensions, not EBCDIC. + Testing the value of '\n' and '\r' is not relevant. */ +# define C_CTYPE_ASCII 1 +#elif ! (' ' == '\x40' && '0' == '\xf0' \ + && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \ + && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2') +# error "Only ASCII and EBCDIC are supported" +#endif + +#if 'A' < 0 +# error "EBCDIC and char is signed -- not supported" +#endif + +/* Cases for control characters. */ + +#define _C_CTYPE_CNTRL \ + case '\a': case '\b': case '\f': case '\n': \ + case '\r': case '\t': case '\v': \ + _C_CTYPE_OTHER_CNTRL + +/* ASCII control characters other than those with \-letter escapes. */ + +#if C_CTYPE_ASCII +# define _C_CTYPE_OTHER_CNTRL \ + case '\x00': case '\x01': case '\x02': case '\x03': \ + case '\x04': case '\x05': case '\x06': case '\x0e': \ + case '\x0f': case '\x10': case '\x11': case '\x12': \ + case '\x13': case '\x14': case '\x15': case '\x16': \ + case '\x17': case '\x18': case '\x19': case '\x1a': \ + case '\x1b': case '\x1c': case '\x1d': case '\x1e': \ + case '\x1f': case '\x7f' +#else + /* Use EBCDIC code page 1047's assignments for ASCII control chars; + assume all EBCDIC code pages agree about these assignments. */ +# define _C_CTYPE_OTHER_CNTRL \ + case '\x00': case '\x01': case '\x02': case '\x03': \ + case '\x07': case '\x0e': case '\x0f': case '\x10': \ + case '\x11': case '\x12': case '\x13': case '\x18': \ + case '\x19': case '\x1c': case '\x1d': case '\x1e': \ + case '\x1f': case '\x26': case '\x27': case '\x2d': \ + case '\x2e': case '\x32': case '\x37': case '\x3c': \ + case '\x3d': case '\x3f' +#endif + +/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */ + +#define _C_CTYPE_LOWER_A_THRU_F_N(N) \ + case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \ + case 'e' + (N): case 'f' + (N) +#define _C_CTYPE_LOWER_N(N) \ + _C_CTYPE_LOWER_A_THRU_F_N(N): \ + case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \ + case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \ + case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \ + case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \ + case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N) + +/* Cases for hex letters, digits, lower, punct, and upper. */ + +#define _C_CTYPE_A_THRU_F \ + _C_CTYPE_LOWER_A_THRU_F_N (0): \ + _C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a') +#define _C_CTYPE_DIGIT \ + case '0': case '1': case '2': case '3': \ + case '4': case '5': case '6': case '7': \ + case '8': case '9' +#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0) +#define _C_CTYPE_PUNCT \ + case '!': case '"': case '#': case '$': \ + case '%': case '&': case '\'': case '(': \ + case ')': case '*': case '+': case ',': \ + case '-': case '.': case '/': case ':': \ + case ';': case '<': case '=': case '>': \ + case '?': case '@': case '[': case '\\': \ + case ']': case '^': case '_': case '`': \ + case '{': case '|': case '}': case '~' +#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a') + + +/* Function definitions. */ + +/* Unlike the functions in , which require an argument in the range + of the 'unsigned char' type, the functions here operate on values that are + in the 'unsigned char' range or in the 'char' range. In other words, + when you have a 'char' value, you need to cast it before using it as + argument to a function: + + const char *s = ...; + if (isalpha ((unsigned char) *s)) ... + + but you don't need to cast it for the functions defined in this file: + + const char *s = ...; + if (c_isalpha (*s)) ... + */ + +C_CTYPE_INLINE bool +c_isalnum (int c) +{ + switch (c) + { + _C_CTYPE_DIGIT: + _C_CTYPE_LOWER: + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isalpha (int c) +{ + switch (c) + { + _C_CTYPE_LOWER: + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +/* The function isascii is not locale dependent. + Its use in EBCDIC is questionable. */ +C_CTYPE_INLINE bool +c_isascii (int c) +{ + switch (c) + { + case ' ': + _C_CTYPE_CNTRL: + _C_CTYPE_DIGIT: + _C_CTYPE_LOWER: + _C_CTYPE_PUNCT: + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isblank (int c) +{ + return c == ' ' || c == '\t'; +} + +C_CTYPE_INLINE bool +c_iscntrl (int c) +{ + switch (c) + { + _C_CTYPE_CNTRL: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isdigit (int c) +{ + switch (c) + { + _C_CTYPE_DIGIT: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isgraph (int c) +{ + switch (c) + { + _C_CTYPE_DIGIT: + _C_CTYPE_LOWER: + _C_CTYPE_PUNCT: + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_islower (int c) +{ + switch (c) + { + _C_CTYPE_LOWER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isprint (int c) +{ + switch (c) + { + case ' ': + _C_CTYPE_DIGIT: + _C_CTYPE_LOWER: + _C_CTYPE_PUNCT: + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_ispunct (int c) +{ + switch (c) + { + _C_CTYPE_PUNCT: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isspace (int c) +{ + switch (c) + { + case ' ': case '\t': case '\n': case '\v': case '\f': case '\r': + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isupper (int c) +{ + switch (c) + { + _C_CTYPE_UPPER: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE bool +c_isxdigit (int c) +{ + switch (c) + { + _C_CTYPE_DIGIT: + _C_CTYPE_A_THRU_F: + return true; + default: + return false; + } +} + +C_CTYPE_INLINE int +c_tolower (int c) +{ + switch (c) + { + _C_CTYPE_UPPER: + return c - 'A' + 'a'; + default: + return c; + } +} + +C_CTYPE_INLINE int +c_toupper (int c) +{ + switch (c) + { + _C_CTYPE_LOWER: + return c - 'a' + 'A'; + default: + return c; + } +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* C_CTYPE_H */ diff --git a/cross/lib/c-strcase.h b/cross/lib/c-strcase.h new file mode 100644 index 00000000000..9bcca01b27c --- /dev/null +++ b/cross/lib/c-strcase.h @@ -0,0 +1,56 @@ +/* Case-insensitive string comparison functions in C locale. + Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef C_STRCASE_H +#define C_STRCASE_H + +#include + + +/* The functions defined in this file assume the "C" locale and a character + set without diacritics (ASCII-US or EBCDIC-US or something like that). + Even if the "C" locale on a particular system is an extension of the ASCII + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it + is ISO-8859-1), the functions in this file recognize only the ASCII + characters. More precisely, one of the string arguments must be an ASCII + string; the other one can also contain non-ASCII characters (but then + the comparison result will be nonzero). */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Compare strings S1 and S2, ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less than, equal to or greater + than S2. */ +extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE; + +/* Compare no more than N characters of strings S1 and S2, ignoring case, + returning less than, equal to or greater than zero if S1 is + lexicographically less than, equal to or greater than S2. */ +extern int c_strncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} +#endif + + +#endif /* C_STRCASE_H */ diff --git a/cross/lib/c-strcasecmp.c b/cross/lib/c-strcasecmp.c new file mode 100644 index 00000000000..8a958dc4fd9 --- /dev/null +++ b/cross/lib/c-strcasecmp.c @@ -0,0 +1,56 @@ +/* c-strcasecmp.c -- case insensitive string comparator in C locale + Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include "c-strcase.h" + +#include + +#include "c-ctype.h" + +int +c_strcasecmp (const char *s1, const char *s2) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + c1 = c_tolower (*p1); + c2 = c_tolower (*p2); + + if (c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return _GL_CMP (c1, c2); +} diff --git a/cross/lib/c-strncasecmp.c b/cross/lib/c-strncasecmp.c new file mode 100644 index 00000000000..4ca8c5f4001 --- /dev/null +++ b/cross/lib/c-strncasecmp.c @@ -0,0 +1,56 @@ +/* c-strncasecmp.c -- case insensitive string comparator in C locale + Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include "c-strcase.h" + +#include + +#include "c-ctype.h" + +int +c_strncasecmp (const char *s1, const char *s2, size_t n) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2 || n == 0) + return 0; + + do + { + c1 = c_tolower (*p1); + c2 = c_tolower (*p2); + + if (--n == 0 || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) + return c1 - c2; + else + /* On machines where 'char' and 'int' are types of the same size, the + difference of two 'unsigned char' values - including the sign bit - + doesn't fit in an 'int'. */ + return _GL_CMP (c1, c2); +} diff --git a/cross/lib/canonicalize-lgpl.c b/cross/lib/canonicalize-lgpl.c new file mode 100644 index 00000000000..e701297d84b --- /dev/null +++ b/cross/lib/canonicalize-lgpl.c @@ -0,0 +1,469 @@ +/* Return the canonical absolute name of a given file. + Copyright (C) 1996-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the name == NULL test below. */ +# define _GL_ARG_NONNULL(params) + +# include +#endif + +/* Specification. */ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef _LIBC +# include +# define GCC_LINT 1 +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +# define __canonicalize_file_name canonicalize_file_name +# define __realpath realpath +# define __strdup strdup +# include "pathmax.h" +# define __faccessat faccessat +# if defined _WIN32 && !defined __CYGWIN__ +# define __getcwd _getcwd +# elif HAVE_GETCWD +# if IN_RELOCWRAPPER + /* When building the relocatable program wrapper, use the system's getcwd + function, not the gnulib override, otherwise we would get a link error. + */ +# undef getcwd +# endif +# if defined VMS && !defined getcwd + /* We want the directory in Unix syntax, not in VMS syntax. + The gnulib override of 'getcwd' takes 2 arguments; the original VMS + 'getcwd' takes 3 arguments. */ +# define __getcwd(buf, max) getcwd (buf, max, 0) +# else +# define __getcwd getcwd +# endif +# else +# define __getcwd(buf, max) getwd (buf) +# endif +# define __mempcpy mempcpy +# define __pathconf pathconf +# define __rawmemchr rawmemchr +# define __readlink readlink +# if IN_RELOCWRAPPER + /* When building the relocatable program wrapper, use the system's memmove + function, not the gnulib override, otherwise we would get a link error. + */ +# undef memmove +# endif +#endif + +/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */ +#if defined GCC_LINT || defined lint +# define IF_LINT(Code) Code +#else +# define IF_LINT(Code) /* empty */ +#endif + +#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT false +#endif + +#if defined _LIBC || !FUNC_REALPATH_WORKS + +/* Return true if FILE's existence can be shown, false (setting errno) + otherwise. Follow symbolic links. */ +static bool +file_accessible (char const *file) +{ +# if defined _LIBC || HAVE_FACCESSAT + return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0; +# else + struct stat st; + return stat (file, &st) == 0 || errno == EOVERFLOW; +# endif +} + +/* True if concatenating END as a suffix to a file name means that the + code needs to check that the file name is that of a searchable + directory, since the canonicalize_filename_mode_stk code won't + check this later anyway when it checks an ordinary file name + component within END. END must either be empty, or start with a + slash. */ + +static bool _GL_ATTRIBUTE_PURE +suffix_requires_dir_check (char const *end) +{ + /* If END does not start with a slash, the suffix is OK. */ + while (ISSLASH (*end)) + { + /* Two or more slashes act like a single slash. */ + do + end++; + while (ISSLASH (*end)); + + switch (*end++) + { + default: return false; /* An ordinary file name component is OK. */ + case '\0': return true; /* Trailing "/" is trouble. */ + case '.': break; /* Possibly "." or "..". */ + } + /* Trailing "/.", or "/.." even if not trailing, is trouble. */ + if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1])))) + return true; + } + + return false; +} + +/* Append this to a file name to test whether it is a searchable directory. + On POSIX platforms "/" suffices, but "/./" is sometimes needed on + macOS 10.13 , and should also work on + platforms like AIX 7.2 that need at least "/.". */ + +# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK +static char const dir_suffix[] = "/"; +# else +static char const dir_suffix[] = "/./"; +# endif + +/* Return true if DIR is a searchable dir, false (setting errno) otherwise. + DIREND points to the NUL byte at the end of the DIR string. + Store garbage into DIREND[0 .. strlen (dir_suffix)]. */ + +static bool +dir_check (char *dir, char *dirend) +{ + strcpy (dirend, dir_suffix); + return file_accessible (dir); +} + +static idx_t +get_path_max (void) +{ +# ifdef PATH_MAX + long int path_max = PATH_MAX; +# else + /* The caller invoked realpath with a null RESOLVED, even though + PATH_MAX is not defined as a constant. The glibc manual says + programs should not do this, and POSIX says the behavior is undefined. + Historically, glibc here used the result of pathconf, or 1024 if that + failed; stay consistent with this (dubious) historical practice. */ + int err = errno; + long int path_max = __pathconf ("/", _PC_PATH_MAX); + __set_errno (err); +# endif + return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX; +} + +/* Scratch buffers used by realpath_stk and managed by __realpath. */ +struct realpath_bufs +{ + struct scratch_buffer rname; + struct scratch_buffer extra; + struct scratch_buffer link; +}; + +static char * +realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs) +{ + char *dest; + char const *start; + char const *end; + int num_links = 0; + + if (name == NULL) + { + /* As per Single Unix Specification V2 we must return an error if + either parameter is a null pointer. We extend this to allow + the RESOLVED parameter to be NULL in case the we are expected to + allocate the room for the return value. */ + __set_errno (EINVAL); + return NULL; + } + + if (name[0] == '\0') + { + /* As per Single Unix Specification V2 we must return an error if + the name argument points to an empty string. */ + __set_errno (ENOENT); + return NULL; + } + + char *rname = bufs->rname.data; + bool end_in_extra_buffer = false; + bool failed = true; + + /* This is always zero for Posix hosts, but can be 2 for MS-Windows + and MS-DOS X:/foo/bar file names. */ + idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + if (!IS_ABSOLUTE_FILE_NAME (name)) + { + while (!__getcwd (bufs->rname.data, bufs->rname.length)) + { + if (errno != ERANGE) + { + dest = rname; + goto error; + } + if (!scratch_buffer_grow (&bufs->rname)) + return NULL; + rname = bufs->rname.data; + } + dest = __rawmemchr (rname, '\0'); + start = name; + prefix_len = FILE_SYSTEM_PREFIX_LEN (rname); + } + else + { + dest = __mempcpy (rname, name, prefix_len); + *dest++ = '/'; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT) + { + if (prefix_len == 0 /* implies ISSLASH (name[0]) */ + && ISSLASH (name[1]) && !ISSLASH (name[2])) + *dest++ = '/'; + *dest = '\0'; + } + start = name + prefix_len; + } + + for ( ; *start; start = end) + { + /* Skip sequence of multiple file name separators. */ + while (ISSLASH (*start)) + ++start; + + /* Find end of component. */ + for (end = start; *end && !ISSLASH (*end); ++end) + /* Nothing. */; + + /* Length of this file name component; it can be zero if a file + name ends in '/'. */ + idx_t startlen = end - start; + + if (startlen == 0) + break; + else if (startlen == 1 && start[0] == '.') + /* nothing */; + else if (startlen == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rname + prefix_len + 1) + for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) + continue; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT + && dest == rname + 1 && !prefix_len + && ISSLASH (*dest) && !ISSLASH (dest[1])) + dest++; + } + else + { + if (!ISSLASH (dest[-1])) + *dest++ = '/'; + + while (rname + bufs->rname.length - dest + < startlen + sizeof dir_suffix) + { + idx_t dest_offset = dest - rname; + if (!scratch_buffer_grow_preserve (&bufs->rname)) + return NULL; + rname = bufs->rname.data; + dest = rname + dest_offset; + } + + dest = __mempcpy (dest, start, startlen); + *dest = '\0'; + + char *buf; + ssize_t n; + while (true) + { + buf = bufs->link.data; + idx_t bufsize = bufs->link.length; + n = __readlink (rname, buf, bufsize - 1); + if (n < bufsize - 1) + break; + if (!scratch_buffer_grow (&bufs->link)) + return NULL; + } + if (0 <= n) + { + if (++num_links > __eloop_threshold ()) + { + __set_errno (ELOOP); + goto error; + } + + buf[n] = '\0'; + + char *extra_buf = bufs->extra.data; + idx_t end_idx IF_LINT (= 0); + if (end_in_extra_buffer) + end_idx = end - extra_buf; + size_t len = strlen (end); + if (INT_ADD_OVERFLOW (len, n)) + { + __set_errno (ENOMEM); + return NULL; + } + while (bufs->extra.length <= len + n) + { + if (!scratch_buffer_grow_preserve (&bufs->extra)) + return NULL; + extra_buf = bufs->extra.data; + } + if (end_in_extra_buffer) + end = extra_buf + end_idx; + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + end_in_extra_buffer = true; + + if (IS_ABSOLUTE_FILE_NAME (buf)) + { + idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); + + dest = __mempcpy (rname, buf, pfxlen); + *dest++ = '/'; /* It's an absolute symlink */ + if (DOUBLE_SLASH_IS_DISTINCT_ROOT) + { + if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen) + *dest++ = '/'; + *dest = '\0'; + } + /* Install the new prefix to be in effect hereafter. */ + prefix_len = pfxlen; + } + else + { + /* Back up to previous component, ignore if at root + already: */ + if (dest > rname + prefix_len + 1) + for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) + continue; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 + && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) + dest++; + } + } + else if (! (suffix_requires_dir_check (end) + ? dir_check (rname, dest) + : errno == EINVAL)) + goto error; + } + } + if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1])) + --dest; + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len + && ISSLASH (*dest) && !ISSLASH (dest[1])) + dest++; + failed = false; + +error: + *dest++ = '\0'; + if (resolved != NULL) + { + /* Copy the full result on success or partial result if failure was due + to the path not existing or not being accessible. */ + if ((!failed || errno == ENOENT || errno == EACCES) + && dest - rname <= get_path_max ()) + { + strcpy (resolved, rname); + if (failed) + return NULL; + else + return resolved; + } + if (!failed) + __set_errno (ENAMETOOLONG); + return NULL; + } + else + { + if (failed) + return NULL; + else + return __strdup (bufs->rname.data); + } +} + +/* Return the canonical absolute name of file NAME. A canonical name + does not contain any ".", ".." components nor any repeated file name + separators ('/') or symlinks. All file name components must exist. If + RESOLVED is null, the result is malloc'd; otherwise, if the + canonical name is PATH_MAX chars or more, returns null with 'errno' + set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, + returns the name in RESOLVED. If the name cannot be resolved and + RESOLVED is non-NULL, it contains the name of the first component + that cannot be resolved. If the name can be resolved, RESOLVED + holds the same value as the value returned. */ + +char * +__realpath (const char *name, char *resolved) +{ + struct realpath_bufs bufs; + scratch_buffer_init (&bufs.rname); + scratch_buffer_init (&bufs.extra); + scratch_buffer_init (&bufs.link); + char *result = realpath_stk (name, resolved, &bufs); + scratch_buffer_free (&bufs.link); + scratch_buffer_free (&bufs.extra); + scratch_buffer_free (&bufs.rname); + return result; +} +libc_hidden_def (__realpath) +versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); + +#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */ + + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) +char * +attribute_compat_text_section +__old_realpath (const char *name, char *resolved) +{ + if (resolved == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + return __realpath (name, resolved); +} +compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); +#endif + + +char * +__canonicalize_file_name (const char *name) +{ + return __realpath (name, NULL); +} +weak_alias (__canonicalize_file_name, canonicalize_file_name) diff --git a/cross/lib/careadlinkat.c b/cross/lib/careadlinkat.c new file mode 100644 index 00000000000..359d497396c --- /dev/null +++ b/cross/lib/careadlinkat.c @@ -0,0 +1,184 @@ +/* Read symbolic links into a buffer without size limitation, relative to fd. + + Copyright (C) 2001, 2003-2004, 2007, 2009-2023 Free Software Foundation, + Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#include + +#include "careadlinkat.h" + +#include "idx.h" +#include "minmax.h" + +#include +#include +#include +#include + +/* Define this independently so that stdint.h is not a prerequisite. */ +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#include "allocator.h" + +enum { STACK_BUF_SIZE = 1024 }; + +/* Act like careadlinkat (see below), with an additional argument + STACK_BUF that can be used as temporary storage. + + If GCC_LINT is defined, do not inline this function with GCC 10.1 + and later, to avoid creating a pointer to the stack that GCC + -Wreturn-local-addr incorrectly complains about. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644 + Although the noinline attribute can hurt performance a bit, no better way + to pacify GCC is known; even an explicit #pragma does not pacify GCC. + When the GCC bug is fixed this workaround should be limited to the + broken GCC versions. */ +#if _GL_GNUC_PREREQ (10, 1) +# if defined GCC_LINT || defined lint +__attribute__ ((__noinline__)) +# elif __OPTIMIZE__ && !__NO_INLINE__ +# define GCC_BOGUS_WRETURN_LOCAL_ADDR +# endif +#endif +static char * +readlink_stk (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, char *, size_t), + char stack_buf[STACK_BUF_SIZE]) +{ + if (! alloc) + alloc = &stdlib_allocator; + + if (!buffer) + { + buffer = stack_buf; + buffer_size = STACK_BUF_SIZE; + } + + char *buf = buffer; + idx_t buf_size_max = MIN (IDX_MAX, MIN (SSIZE_MAX, SIZE_MAX)); + idx_t buf_size = MIN (buffer_size, buf_size_max); + + while (buf) + { + /* Attempt to read the link into the current buffer. */ + idx_t link_length = preadlinkat (fd, filename, buf, buf_size); + if (link_length < 0) + { + if (buf != buffer) + { + int readlinkat_errno = errno; + alloc->free (buf); + errno = readlinkat_errno; + } + return NULL; + } + + idx_t link_size = link_length; + + if (link_size < buf_size) + { + buf[link_size++] = '\0'; + + if (buf == stack_buf) + { + char *b = alloc->allocate (link_size); + buf_size = link_size; + if (! b) + break; + return memcpy (b, buf, link_size); + } + + if (link_size < buf_size && buf != buffer && alloc->reallocate) + { + /* Shrink BUF before returning it. */ + char *b = alloc->reallocate (buf, link_size); + if (b) + return b; + } + + return buf; + } + + if (buf != buffer) + alloc->free (buf); + + if (buf_size_max / 2 <= buf_size) + { + errno = ENAMETOOLONG; + return NULL; + } + + buf_size = 2 * buf_size + 1; + buf = alloc->allocate (buf_size); + } + + if (alloc->die) + alloc->die (buf_size); + errno = ENOMEM; + return NULL; +} + + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. A null + ALLOC stands for the standard allocator. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char * +careadlinkat (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, char *, size_t)) +{ + /* Allocate the initial buffer on the stack. This way, in the + common case of a symlink of small size, we get away with a + single small malloc instead of a big malloc followed by a + shrinking realloc. */ + #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR + #warning "GCC might issue a bogus -Wreturn-local-addr warning here." + #warning "See ." + #endif + char stack_buf[STACK_BUF_SIZE]; + return readlink_stk (fd, filename, buffer, buffer_size, alloc, + preadlinkat, stack_buf); +} diff --git a/cross/lib/careadlinkat.h b/cross/lib/careadlinkat.h new file mode 100644 index 00000000000..201d0415fff --- /dev/null +++ b/cross/lib/careadlinkat.h @@ -0,0 +1,67 @@ +/* Read symbolic links into a buffer without size limitation, relative to fd. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_CAREADLINKAT_H +#define _GL_CAREADLINKAT_H + +#include +#include + +struct allocator; + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char *careadlinkat (int fd, char const *filename, + char *restrict buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, + char *, size_t)); + +/* Suitable value for careadlinkat's FD argument. */ +#if HAVE_READLINKAT +/* AT_FDCWD is declared in . */ +#else +/* Define AT_FDCWD independently, so that the careadlinkat module does + not depend on the fcntl-h module. We might as well use the same value + as fcntl-h. */ +# ifndef AT_FDCWD +# define AT_FDCWD (-3041965) +# endif +#endif + +#endif /* _GL_CAREADLINKAT_H */ diff --git a/cross/lib/cdefs.h b/cross/lib/cdefs.h new file mode 100644 index 00000000000..09a3d19b23b --- /dev/null +++ b/cross/lib/cdefs.h @@ -0,0 +1,707 @@ +/* Copyright (C) 1992-2023 Free Software Foundation, Inc. + Copyright The GNU Toolchain Authors. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _SYS_CDEFS_H +#define _SYS_CDEFS_H 1 + +/* We are almost always included from features.h. */ +#ifndef _FEATURES_H +# include +#endif + +/* The GNU libc does not support any K&R compilers or the traditional mode + of ISO C compilers anymore. Check for some of the combinations not + supported anymore. */ +#if defined __GNUC__ && !defined __STDC__ +# error "You need a ISO C conforming compiler to use the glibc headers" +#endif + +/* Some user header file might have defined this before. */ +#undef __P +#undef __PMT + +/* Compilers that lack __has_attribute may object to + #if defined __has_attribute && __has_attribute (...) + even though they do not need to evaluate the right-hand side of the &&. + Similarly for __has_builtin, etc. */ +#if (defined __has_attribute \ + && (!defined __clang_minor__ \ + || (defined __apple_build_version__ \ + ? 6000000 <= __apple_build_version__ \ + : 3 < __clang_major__ + (5 <= __clang_minor__)))) +# define __glibc_has_attribute(attr) __has_attribute (attr) +#else +# define __glibc_has_attribute(attr) 0 +#endif +#ifdef __has_builtin +# define __glibc_has_builtin(name) __has_builtin (name) +#else +# define __glibc_has_builtin(name) 0 +#endif +#ifdef __has_extension +# define __glibc_has_extension(ext) __has_extension (ext) +#else +# define __glibc_has_extension(ext) 0 +#endif + +#if defined __GNUC__ || defined __clang__ + +/* All functions, except those with callbacks or those that + synchronize memory, are leaf functions. */ +# if __GNUC_PREREQ (4, 6) && !defined _LIBC +# define __LEAF , __leaf__ +# define __LEAF_ATTR __attribute__ ((__leaf__)) +# else +# define __LEAF +# define __LEAF_ATTR +# endif + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this only works with + gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions + as non-throwing using a function attribute since programs can use + the -fexceptions options for C code as well. */ +# if !defined __cplusplus \ + && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__)) +# define __THROW __attribute__ ((__nothrow__ __LEAF)) +# define __THROWNL __attribute__ ((__nothrow__)) +# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct +# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct +# else +# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4) +# if __cplusplus >= 201103L +# define __THROW noexcept (true) +# else +# define __THROW throw () +# endif +# define __THROWNL __THROW +# define __NTH(fct) __LEAF_ATTR fct __THROW +# define __NTHNL(fct) fct __THROW +# else +# define __THROW +# define __THROWNL +# define __NTH(fct) fct +# define __NTHNL(fct) fct +# endif +# endif + +#else /* Not GCC or clang. */ + +# if (defined __cplusplus \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) +# define __inline inline +# else +# define __inline /* No inline functions. */ +# endif + +# define __THROW +# define __THROWNL +# define __NTH(fct) fct + +#endif /* GCC || clang. */ + +/* These two macros are not used in glibc anymore. They are kept here + only because some other projects expect the macros to be defined. */ +#define __P(args) args +#define __PMT(args) args + +/* For these things, GCC behaves the ANSI way normally, + and the non-ANSI way under -traditional. */ + +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +/* This is not a typedef so `const __ptr_t' does the right thing. */ +#define __ptr_t void * + + +/* C++ needs to know that types and declarations are C, not C++. */ +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + + +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) + +/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ +#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \ + || __GNUC_PREREQ (12, 0)) +# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) +# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) +#else +# define __glibc_objsize0(__o) __bos0 (__o) +# define __glibc_objsize(__o) __bos (__o) +#endif + +/* Compile time conditions to choose between the regular, _chk and _chk_warn + variants. These conditions should get evaluated to constant and optimized + away. */ + +#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s)) +#define __glibc_unsigned_or_positive(__l) \ + ((__typeof (__l)) 0 < (__typeof (__l)) -1 \ + || (__builtin_constant_p (__l) && (__l) > 0)) + +/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ + condition can be folded to a constant and if it is true, or unknown (-1) */ +#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ + ((__osz) == (__SIZE_TYPE__) -1 \ + || (__glibc_unsigned_or_positive (__l) \ + && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ + (__s), (__osz))) \ + && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz)))) + +/* Conversely, we know at compile time that the length is unsafe if the + __L * __S <= __OBJSZ condition can be folded to a constant and if it is + false. */ +#define __glibc_unsafe_len(__l, __s, __osz) \ + (__glibc_unsigned_or_positive (__l) \ + && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ + __s, __osz)) \ + && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) + +/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be + declared. */ + +#define __glibc_fortify(f, __l, __s, __osz, ...) \ + (__glibc_safe_or_unknown_len (__l, __s, __osz) \ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ + : __ ## f ## _chk (__VA_ARGS__, __osz))) \ + +/* Fortify function f, where object size argument passed to f is the number of + elements and not total size. */ + +#define __glibc_fortify_n(f, __l, __s, __osz, ...) \ + (__glibc_safe_or_unknown_len (__l, __s, __osz) \ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ + : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \ + +#if __GNUC_PREREQ (4,3) +# define __warnattr(msg) __attribute__((__warning__ (msg))) +# define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) +#else +# define __warnattr(msg) +# define __errordecl(name, msg) extern void name (void) +#endif + +/* Support for flexible arrays. + Headers that should use flexible arrays only if they're "real" + (e.g. only if they won't affect sizeof()) should test + #if __glibc_c99_flexarr_available. */ +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc +# define __flexarr [] +# define __glibc_c99_flexarr_available 1 +#elif __GNUC_PREREQ (2,97) || defined __clang__ +/* GCC 2.97 and clang support C99 flexible array members as an extension, + even when in C89 mode or compiling C++ (any version). */ +# define __flexarr [] +# define __glibc_c99_flexarr_available 1 +#elif defined __GNUC__ +/* Pre-2.97 GCC did not support C99 flexible arrays but did have + an equivalent extension with slightly different notation. */ +# define __flexarr [0] +# define __glibc_c99_flexarr_available 1 +#else +/* Some other non-C99 compiler. Approximate with [1]. */ +# define __flexarr [1] +# define __glibc_c99_flexarr_available 0 +#endif + + +/* __asm__ ("xyz") is used throughout the headers to rename functions + at the assembly language level. This is wrapped by the __REDIRECT + macro, in order to support compilers that can do this some other + way. When compilers don't support asm-names at all, we have to do + preprocessor tricks instead (which don't have exactly the right + semantics, but it's the best we can do). + + Example: + int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ + +#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4) + +# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) +# ifdef __cplusplus +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __THROW __asm__ (__ASMNAME (#alias)) +# define __REDIRECT_NTHNL(name, proto, alias) \ + name proto __THROWNL __asm__ (__ASMNAME (#alias)) +# else +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROW +# define __REDIRECT_NTHNL(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROWNL +# endif +# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) +# define __ASMNAME2(prefix, cname) __STRING (prefix) cname + +/* +#elif __SOME_OTHER_COMPILER__ + +# define __REDIRECT(name, proto, alias) name proto; \ + _Pragma("let " #name " = " #alias) +*/ +#endif + +/* GCC and clang have various useful declarations that can be made with + the '__attribute__' syntax. All of the ways we use this do fine if + they are omitted for compilers that don't understand it. */ +#if !(defined __GNUC__ || defined __clang__) +# define __attribute__(xyz) /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `malloc' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__) +# define __attribute_malloc__ __attribute__ ((__malloc__)) +#else +# define __attribute_malloc__ /* Ignore */ +#endif + +/* Tell the compiler which arguments to an allocation function + indicate the size of the allocation. */ +#if __GNUC_PREREQ (4, 3) +# define __attribute_alloc_size__(params) \ + __attribute__ ((__alloc_size__ params)) +#else +# define __attribute_alloc_size__(params) /* Ignore. */ +#endif + +/* Tell the compiler which argument to an allocation function + indicates the alignment of the allocation. */ +#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__) +# define __attribute_alloc_align__(param) \ + __attribute__ ((__alloc_align__ param)) +#else +# define __attribute_alloc_align__(param) /* Ignore. */ +#endif + +/* At some point during the gcc 2.96 development the `pure' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__) +# define __attribute_pure__ __attribute__ ((__pure__)) +#else +# define __attribute_pure__ /* Ignore */ +#endif + +/* This declaration tells the compiler that the value is constant. */ +#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__) +# define __attribute_const__ __attribute__ ((__const__)) +#else +# define __attribute_const__ /* Ignore */ +#endif + +#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__) +# define __attribute_maybe_unused__ __attribute__ ((__unused__)) +#else +# define __attribute_maybe_unused__ /* Ignore */ +#endif + +/* At some point during the gcc 3.1 development the `used' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__) +# define __attribute_used__ __attribute__ ((__used__)) +# define __attribute_noinline__ __attribute__ ((__noinline__)) +#else +# define __attribute_used__ __attribute__ ((__unused__)) +# define __attribute_noinline__ /* Ignore */ +#endif + +/* Since version 3.2, gcc allows marking deprecated functions. */ +#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__) +# define __attribute_deprecated__ __attribute__ ((__deprecated__)) +#else +# define __attribute_deprecated__ /* Ignore */ +#endif + +/* Since version 4.5, gcc also allows one to specify the message printed + when a deprecated function is used. clang claims to be gcc 4.2, but + may also support this feature. */ +#if __GNUC_PREREQ (4,5) \ + || __glibc_has_extension (__attribute_deprecated_with_message__) +# define __attribute_deprecated_msg__(msg) \ + __attribute__ ((__deprecated__ (msg))) +#else +# define __attribute_deprecated_msg__(msg) __attribute_deprecated__ +#endif + +/* At some point during the gcc 2.8 development the `format_arg' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. + If several `format_arg' attributes are given for the same function, in + gcc-3.0 and older, all but the last one are ignored. In newer gccs, + all designated arguments are considered. */ +#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__) +# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) +#else +# define __attribute_format_arg__(x) /* Ignore */ +#endif + +/* At some point during the gcc 2.97 development the `strfmon' format + attribute for functions was introduced. We don't want to use it + unconditionally (although this would be possible) since it + generates warnings. */ +#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__) +# define __attribute_format_strfmon__(a,b) \ + __attribute__ ((__format__ (__strfmon__, a, b))) +#else +# define __attribute_format_strfmon__(a,b) /* Ignore */ +#endif + +/* The nonnull function attribute marks pointer parameters that + must not be NULL. This has the name __nonnull in glibc, + and __attribute_nonnull__ in files shared with Gnulib to avoid + collision with a different __nonnull in DragonFlyBSD 5.9. */ +#ifndef __attribute_nonnull__ +# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__) +# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params)) +# else +# define __attribute_nonnull__(params) +# endif +#endif +#ifndef __nonnull +# define __nonnull(params) __attribute_nonnull__ (params) +#endif + +/* The returns_nonnull function attribute marks the return type of the function + as always being non-null. */ +#ifndef __returns_nonnull +# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__) +# define __returns_nonnull __attribute__ ((__returns_nonnull__)) +# else +# define __returns_nonnull +# endif +#endif + +/* If fortification mode, we warn about unused results of certain + function calls which can lead to problems. */ +#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0 +# define __wur __attribute_warn_unused_result__ +# endif +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif +#ifndef __wur +# define __wur /* Ignore */ +#endif + +/* Forces a function to be always inlined. */ +#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__) +/* The Linux kernel defines __always_inline in stddef.h (283d7573), and + it conflicts with this definition. Therefore undefine it first to + allow either header to be included first. */ +# undef __always_inline +# define __always_inline __inline __attribute__ ((__always_inline__)) +#else +# undef __always_inline +# define __always_inline __inline +#endif + +/* Associate error messages with the source location of the call site rather + than with the source location inside the function. */ +#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__) +# define __attribute_artificial__ __attribute__ ((__artificial__)) +#else +# define __attribute_artificial__ /* Ignore */ +#endif + +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__ + or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions + older than 4.3 may define these macros and still not guarantee GNU inlining + semantics. + + clang++ identifies itself as gcc-4.2, but has support for GNU inlining + semantics, that can be checked for by using the __GNUC_STDC_INLINE_ and + __GNUC_GNU_INLINE__ macro definitions. */ +#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \ + || (defined __clang__ && (defined __GNUC_STDC_INLINE__ \ + || defined __GNUC_GNU_INLINE__))) +# if defined __GNUC_STDC_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +#endif + +#ifdef __extern_always_inline +# define __fortify_function __extern_always_inline __attribute_artificial__ +#endif + +/* GCC 4.3 and above allow passing all anonymous arguments of an + __extern_always_inline function to some other vararg function. */ +#if __GNUC_PREREQ (4,3) +# define __va_arg_pack() __builtin_va_arg_pack () +# define __va_arg_pack_len() __builtin_va_arg_pack_len () +#endif + +/* It is possible to compile containing GCC extensions even if GCC is + run in pedantic mode if the uses are carefully marked using the + `__extension__' keyword. But this is not generally available before + version 2.8. */ +#if !(__GNUC_PREREQ (2,8) || defined __clang__) +# define __extension__ /* Ignore */ +#endif + +/* __restrict is known in EGCS 1.2 and above, and in clang. + It works also in C++ mode (outside of arrays), but only when spelled + as '__restrict', not 'restrict'. */ +#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3) +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict restrict +# else +# define __restrict /* Ignore */ +# endif +#endif + +/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is + array_name[restrict] + GCC 3.1 and clang support this. + This syntax is not usable in C++ mode. */ +#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus +# define __restrict_arr __restrict +#else +# ifdef __GNUC__ +# define __restrict_arr /* Not supported in old GCC. */ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict_arr restrict +# else +/* Some other non-C99 compiler. */ +# define __restrict_arr /* Not supported. */ +# endif +# endif +#endif + +#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect) +# define __glibc_unlikely(cond) __builtin_expect ((cond), 0) +# define __glibc_likely(cond) __builtin_expect ((cond), 1) +#else +# define __glibc_unlikely(cond) (cond) +# define __glibc_likely(cond) (cond) +#endif + +#if (!defined _Noreturn \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && !(__GNUC_PREREQ (4,7) \ + || (3 < __clang_major__ + (5 <= __clang_minor__)))) +# if __GNUC_PREREQ (2,8) +# define _Noreturn __attribute__ ((__noreturn__)) +# else +# define _Noreturn +# endif +#endif + +#if __GNUC_PREREQ (8, 0) +/* Describes a char array whose address can safely be passed as the first + argument to strncpy and strncat, as the char array is not necessarily + a NUL-terminated string. */ +# define __attribute_nonstring__ __attribute__ ((__nonstring__)) +#else +# define __attribute_nonstring__ +#endif + +/* Undefine (also defined in libc-symbols.h). */ +#undef __attribute_copy__ +#if __GNUC_PREREQ (9, 0) +/* Copies attributes from the declaration or type referenced by + the argument. */ +# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg))) +#else +# define __attribute_copy__(arg) +#endif + +#if (!defined _Static_assert && !defined __cplusplus \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \ + || defined __STRICT_ANSI__)) +# define _Static_assert(expr, diagnostic) \ + extern int (*__Static_assert_function (void)) \ + [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] +#endif + +/* Gnulib avoids including these, as they don't work on non-glibc or + older glibc platforms. */ +#ifndef __GNULIB_CDEFS +# include +# include +#endif + +#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 +# ifdef __REDIRECT + +/* Alias name defined automatically. */ +# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir +# define __LDBL_REDIR_DECL(name) \ + extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128")); + +/* Alias name defined automatically, with leading underscores. */ +# define __LDBL_REDIR2_DECL(name) \ + extern __typeof (__##name) __##name \ + __asm (__ASMNAME ("__" #name "ieee128")); + +/* Alias name defined manually. */ +# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1 +# define __LDBL_REDIR1_DECL(name, alias) \ + extern __typeof (name) name __asm (__ASMNAME (#alias)); + +# define __LDBL_REDIR1_NTH(name, proto, alias) \ + __REDIRECT_NTH (name, proto, alias) +# define __REDIRECT_NTH_LDBL(name, proto, alias) \ + __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128) + +/* Unused. */ +# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl +# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth + +# else +_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform"); +# endif +#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH +# define __LDBL_COMPAT 1 +# ifdef __REDIRECT +# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias) +# define __LDBL_REDIR(name, proto) \ + __LDBL_REDIR1 (name, proto, __nldbl_##name) +# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias) +# define __LDBL_REDIR_NTH(name, proto) \ + __LDBL_REDIR1_NTH (name, proto, __nldbl_##name) +# define __LDBL_REDIR2_DECL(name) \ + extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name)); +# define __LDBL_REDIR1_DECL(name, alias) \ + extern __typeof (name) name __asm (__ASMNAME (#alias)); +# define __LDBL_REDIR_DECL(name) \ + extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name)); +# define __REDIRECT_LDBL(name, proto, alias) \ + __LDBL_REDIR1 (name, proto, __nldbl_##alias) +# define __REDIRECT_NTH_LDBL(name, proto, alias) \ + __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias) +# endif +#endif +#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \ + || !defined __REDIRECT +# define __LDBL_REDIR1(name, proto, alias) name proto +# define __LDBL_REDIR(name, proto) name proto +# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW +# define __LDBL_REDIR_NTH(name, proto) name proto __THROW +# define __LDBL_REDIR2_DECL(name) +# define __LDBL_REDIR_DECL(name) +# ifdef __REDIRECT +# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias) +# define __REDIRECT_NTH_LDBL(name, proto, alias) \ + __REDIRECT_NTH (name, proto, alias) +# endif +#endif + +/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is + intended for use in preprocessor macros. + + Note: MESSAGE must be a _single_ string; concatenation of string + literals is not supported. */ +#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5) +# define __glibc_macro_warning1(message) _Pragma (#message) +# define __glibc_macro_warning(message) \ + __glibc_macro_warning1 (GCC warning message) +#else +# define __glibc_macro_warning(msg) +#endif + +/* Generic selection (ISO C11) is a C-only feature, available in GCC + since version 4.9. Previous versions do not provide generic + selection, even though they might set __STDC_VERSION__ to 201112L, + when in -std=c11 mode. Thus, we must check for !defined __GNUC__ + when testing __STDC_VERSION__ for generic selection support. + On the other hand, Clang also defines __GNUC__, so a clang-specific + check is required to enable the use of generic selection. */ +#if !defined __cplusplus \ + && (__GNUC_PREREQ (4, 9) \ + || __glibc_has_extension (c_generic_selections) \ + || (!defined __GNUC__ && defined __STDC_VERSION__ \ + && __STDC_VERSION__ >= 201112L)) +# define __HAVE_GENERIC_SELECTION 1 +#else +# define __HAVE_GENERIC_SELECTION 0 +#endif + +#if __GNUC_PREREQ (10, 0) +/* Designates a 1-based positional argument ref-index of pointer type + that can be used to access size-index elements of the pointed-to + array according to access mode, or at least one element when + size-index is not provided: + access (access-mode, [, ]) */ +# define __attr_access(x) __attribute__ ((__access__ x)) +/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may + use the access attribute to get object sizes from function definition + arguments, so we can't use them on functions we fortify. Drop the object + size hints for such functions. */ +# if __USE_FORTIFY_LEVEL == 3 +# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o))) +# else +# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s)) +# endif +# if __GNUC_PREREQ (11, 0) +# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno))) +# else +# define __attr_access_none(argno) +# endif +#else +# define __fortified_attr_access(a, o, s) +# define __attr_access(x) +# define __attr_access_none(argno) +#endif + +#if __GNUC_PREREQ (11, 0) +/* Designates dealloc as a function to call to deallocate objects + allocated by the declared function. */ +# define __attr_dealloc(dealloc, argno) \ + __attribute__ ((__malloc__ (dealloc, argno))) +# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1) +#else +# define __attr_dealloc(dealloc, argno) +# define __attr_dealloc_free +#endif + +/* Specify that a function such as setjmp or vfork may return + twice. */ +#if __GNUC_PREREQ (4, 1) +# define __attribute_returns_twice__ __attribute__ ((__returns_twice__)) +#else +# define __attribute_returns_twice__ /* Ignore. */ +#endif + +#endif /* sys/cdefs.h */ diff --git a/cross/lib/cloexec.c b/cross/lib/cloexec.c new file mode 100644 index 00000000000..e4cecbd2e8a --- /dev/null +++ b/cross/lib/cloexec.c @@ -0,0 +1,83 @@ +/* cloexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 1991, 2004-2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* The code is taken from glibc/manual/llio.texi */ + +#include + +#include "cloexec.h" + +#include +#include +#include + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int +set_cloexec_flag (int desc, bool value) +{ +#ifdef F_SETFD + + int flags = fcntl (desc, F_GETFD, 0); + + if (0 <= flags) + { + int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); + + if (flags == newflags + || fcntl (desc, F_SETFD, newflags) != -1) + return 0; + } + + return -1; + +#else /* !F_SETFD */ + + /* Use dup2 to reject invalid file descriptors; the cloexec flag + will be unaffected. */ + if (desc < 0) + { + errno = EBADF; + return -1; + } + if (dup2 (desc, desc) < 0) + /* errno is EBADF here. */ + return -1; + + /* There is nothing we can do on this kind of platform. Punt. */ + return 0; +#endif /* !F_SETFD */ +} + + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int +dup_cloexec (int fd) +{ + return fcntl (fd, F_DUPFD_CLOEXEC, 0); +} diff --git a/cross/lib/cloexec.h b/cross/lib/cloexec.h new file mode 100644 index 00000000000..057fd668c9b --- /dev/null +++ b/cross/lib/cloexec.h @@ -0,0 +1,34 @@ +/* cloexec.c - set or clear the close-on-exec descriptor flag + + Copyright (C) 2004, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, + or clear the flag if VALUE is false. + Return 0 on success, or -1 on error with 'errno' set. + + Note that on MingW, this function does NOT protect DESC from being + inherited into spawned children. Instead, either use dup_cloexec + followed by closing the original DESC, or use interfaces such as + open or pipe2 that accept flags like O_CLOEXEC to create DESC + non-inheritable in the first place. */ + +int set_cloexec_flag (int desc, bool value); + +/* Duplicates a file handle FD, while marking the copy to be closed + prior to exec or spawn. Returns -1 and sets errno if FD could not + be duplicated. */ + +int dup_cloexec (int fd); diff --git a/cross/lib/close-stream.c b/cross/lib/close-stream.c new file mode 100644 index 00000000000..ab686bac2ae --- /dev/null +++ b/cross/lib/close-stream.c @@ -0,0 +1,77 @@ +/* Close a stream, with nicer error checking than fclose's. + + Copyright (C) 1998-2002, 2004, 2006-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +#include + +#include "close-stream.h" + +#include + +#include "fpending.h" + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +/* Close STREAM. Return 0 if successful, EOF (setting errno) + otherwise. A failure might set errno to 0 if the error number + cannot be determined. + + A failure with errno set to EPIPE may or may not indicate an error + situation worth signaling to the user. See the documentation of the + close_stdout_set_ignore_EPIPE function for details. + + If a program writes *anything* to STREAM, that program should close + STREAM and make sure that it succeeds before exiting. Otherwise, + suppose that you go to the extreme of checking the return status + of every function that does an explicit write to STREAM. The last + printf can succeed in writing to the internal stream buffer, and yet + the fclose(STREAM) could still fail (due e.g., to a disk full error) + when it tries to write out that buffered data. Thus, you would be + left with an incomplete output file and the offending program would + exit successfully. Even calling fflush is not always sufficient, + since some file systems (NFS and CODA) buffer written/flushed data + until an actual close call. + + Besides, it's wasteful to check the return value from every call + that writes to STREAM -- just let the internal stream state record + the failure. That's what the ferror test is checking below. */ + +int +close_stream (FILE *stream) +{ + const bool some_pending = (__fpending (stream) != 0); + const bool prev_fail = (ferror (stream) != 0); + const bool fclose_fail = (fclose (stream) != 0); + + /* Return an error indication if there was a previous failure or if + fclose failed, with one exception: ignore an fclose failure if + there was no previous error, no data remains to be flushed, and + fclose failed with EBADF. That can happen when a program like cp + is invoked like this 'cp a b >&-' (i.e., with standard output + closed) and doesn't generate any output (hence no previous error + and nothing to be flushed). */ + + if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) + { + if (! fclose_fail) + errno = 0; + return EOF; + } + + return 0; +} diff --git a/cross/lib/close-stream.h b/cross/lib/close-stream.h new file mode 100644 index 00000000000..3b52cc66c3d --- /dev/null +++ b/cross/lib/close-stream.h @@ -0,0 +1,20 @@ +/* Close a stream, with nicer error checking than fclose's. + + Copyright (C) 2006-2023 Free Software Foundation, Inc. + + This file is free software: you can 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 file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 . */ + +#include + +int close_stream (FILE *stream); diff --git a/cross/lib/copy-file-range.c b/cross/lib/copy-file-range.c new file mode 100644 index 00000000000..747a5a8ad1d --- /dev/null +++ b/cross/lib/copy-file-range.c @@ -0,0 +1,67 @@ +/* Stub for copy_file_range + Copyright 2019-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#include + +#include + +#if defined __linux__ && HAVE_COPY_FILE_RANGE +# include +#endif + +ssize_t +copy_file_range (int infd, off_t *pinoff, + int outfd, off_t *poutoff, + size_t length, unsigned int flags) +{ +#undef copy_file_range + +#if defined __linux__ && HAVE_COPY_FILE_RANGE + /* The implementation of copy_file_range (which first appeared in + Linux kernel release 4.5) had many issues before release 5.3 + , so fail with ENOSYS for Linux + kernels 5.2 and earlier. + + This workaround, and the configure-time check for Linux, can be + removed when such kernels (released March 2016 through September + 2019) are no longer a consideration. As of January 2021, the + furthest-future planned kernel EOL is December 2024 for kernel + release 4.19. */ + + static signed char ok; + + if (! ok) + { + struct utsname name; + uname (&name); + char *p = name.release; + ok = ((p[1] != '.' || '5' < p[0] + || (p[0] == '5' && (p[3] != '.' || '2' < p[2]))) + ? 1 : -1); + } + + if (0 < ok) + return copy_file_range (infd, pinoff, outfd, poutoff, length, flags); +#endif + + /* There is little need to emulate copy_file_range with read+write, + since programs that use copy_file_range must fall back on + read+write anyway. */ + errno = ENOSYS; + return -1; +} diff --git a/cross/lib/count-leading-zeros.c b/cross/lib/count-leading-zeros.c new file mode 100644 index 00000000000..949f156eab1 --- /dev/null +++ b/cross/lib/count-leading-zeros.c @@ -0,0 +1,21 @@ +/* Count the number of leading 0 bits in a word. + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE +#include "count-leading-zeros.h" diff --git a/cross/lib/count-leading-zeros.h b/cross/lib/count-leading-zeros.h new file mode 100644 index 00000000000..99151d695bf --- /dev/null +++ b/cross/lib/count-leading-zeros.h @@ -0,0 +1,136 @@ +/* count-leading-zeros.h -- counts the number of leading 0 bits in a word. + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Eric Blake. */ + +#ifndef COUNT_LEADING_ZEROS_H +#define COUNT_LEADING_ZEROS_H 1 + +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef COUNT_LEADING_ZEROS_INLINE +# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN, + expand to code that computes the number of leading zeros of the local + variable 'x' of type TYPE (an unsigned integer type) and return it + from the current function. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \ + || (__clang_major__ >= 4) +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + return x ? BUILTIN (x) : CHAR_BIT * sizeof x; +#elif _MSC_VER +# pragma intrinsic (_BitScanReverse) +# if defined _M_X64 +# pragma intrinsic (_BitScanReverse64) +# endif +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + unsigned long result; \ + if (MSC_BUILTIN (&result, x)) \ + return CHAR_BIT * sizeof x - 1 - result; \ + return CHAR_BIT * sizeof x; \ + } \ + while (0) +#else +# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + int count; \ + unsigned int leading_32; \ + if (! x) \ + return CHAR_BIT * sizeof x; \ + for (count = 0; \ + (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32)) \ + & 0xffffffffU), \ + count < CHAR_BIT * sizeof x - 32 && !leading_32); \ + count += 32) \ + x = x << 31 << 1; \ + return count + count_leading_zeros_32 (leading_32); \ + } \ + while (0) + +/* Compute and return the number of leading zeros in X, + where 0 < X < 2**32. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_32 (unsigned int x) +{ + /* + */ + static const char de_Bruijn_lookup[32] = { + 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1, + 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0 + }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27]; +} +#endif + +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros (unsigned int x) +{ + COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int); +} + +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_l (unsigned long int x) +{ + COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int); +} + +/* Compute and return the number of leading zeros in X. */ +COUNT_LEADING_ZEROS_INLINE int +count_leading_zeros_ll (unsigned long long int x) +{ +#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64 + /* 32-bit MSVC does not have _BitScanReverse64, only _BitScanReverse. */ + unsigned long result; + if (_BitScanReverse (&result, (unsigned long) (x >> 32))) + return CHAR_BIT * sizeof x - 1 - 32 - result; + if (_BitScanReverse (&result, (unsigned long) x)) + return CHAR_BIT * sizeof x - 1 - result; + return CHAR_BIT * sizeof x; +#else + COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64, + unsigned long long int); +#endif +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* COUNT_LEADING_ZEROS_H */ diff --git a/cross/lib/count-one-bits.c b/cross/lib/count-one-bits.c new file mode 100644 index 00000000000..8a348f2e5a0 --- /dev/null +++ b/cross/lib/count-one-bits.c @@ -0,0 +1,25 @@ +/* Count the number of 1-bits in a word. + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE +#include "count-one-bits.h" + +#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) +int popcount_support = -1; +#endif diff --git a/cross/lib/count-one-bits.h b/cross/lib/count-one-bits.h new file mode 100644 index 00000000000..01a60b77b85 --- /dev/null +++ b/cross/lib/count-one-bits.h @@ -0,0 +1,164 @@ +/* count-one-bits.h -- counts the number of 1-bits in a word. + Copyright (C) 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Ben Pfaff. */ + +#ifndef COUNT_ONE_BITS_H +#define COUNT_ONE_BITS_H 1 + +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef COUNT_ONE_BITS_INLINE +# define COUNT_ONE_BITS_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN, + expand to code that computes the number of 1-bits of the local + variable 'x' of type TYPE (an unsigned integer type) and return it + from the current function. */ +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ + || (__clang_major__ >= 4) +# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ + return GCC_BUILTIN (x) +#else + +/* Compute and return the number of 1-bits set in the least + significant 32 bits of X. */ +COUNT_ONE_BITS_INLINE int +count_one_bits_32 (unsigned int x) +{ + x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U); + x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U); + x = (x >> 16) + (x & 0xffff); + x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f); + return (x >> 8) + (x & 0x00ff); +} + +/* Expand to code that computes the number of 1-bits of the local + variable 'x' of type TYPE (an unsigned integer type) and return it + from the current function. */ +# define COUNT_ONE_BITS_GENERIC(TYPE) \ + do \ + { \ + int count = 0; \ + int bits; \ + for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \ + { \ + count += count_one_bits_32 (x); \ + x = x >> 31 >> 1; \ + } \ + return count; \ + } \ + while (0) + +# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) + +/* While gcc falls back to its own generic code if the machine + on which it's running doesn't support popcount, with Microsoft's + compiler we need to detect and fallback ourselves. */ + +# if 0 +# include +# else + /* Don't pollute the namespace with too many MSVC intrinsics. */ +# pragma intrinsic (__cpuid) +# pragma intrinsic (__popcnt) +# if defined _M_X64 +# pragma intrinsic (__popcnt64) +# endif +# endif + +# if !defined _M_X64 +static inline __popcnt64 (unsigned long long x) +{ + return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x); +} +# endif + +/* Return nonzero if popcount is supported. */ + +/* 1 if supported, 0 if not supported, -1 if unknown. */ +extern int popcount_support; + +COUNT_ONE_BITS_INLINE int +popcount_supported (void) +{ + if (popcount_support < 0) + { + /* Do as described in + */ + int cpu_info[4]; + __cpuid (cpu_info, 1); + popcount_support = (cpu_info[2] >> 23) & 1; + } + return popcount_support; +} + +# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + if (popcount_supported ()) \ + return MSC_BUILTIN (x); \ + else \ + COUNT_ONE_BITS_GENERIC (TYPE); \ + } \ + while (0) + +# else + +# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ + COUNT_ONE_BITS_GENERIC (TYPE) + +# endif +#endif + +/* Compute and return the number of 1-bits set in X. */ +COUNT_ONE_BITS_INLINE int +count_one_bits (unsigned int x) +{ + COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int); +} + +/* Compute and return the number of 1-bits set in X. */ +COUNT_ONE_BITS_INLINE int +count_one_bits_l (unsigned long int x) +{ + COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int); +} + +/* Compute and return the number of 1-bits set in X. */ +COUNT_ONE_BITS_INLINE int +count_one_bits_ll (unsigned long long int x) +{ + COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int); +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* COUNT_ONE_BITS_H */ diff --git a/cross/lib/count-trailing-zeros.c b/cross/lib/count-trailing-zeros.c new file mode 100644 index 00000000000..f6fddab4232 --- /dev/null +++ b/cross/lib/count-trailing-zeros.c @@ -0,0 +1,21 @@ +/* Count the number of trailing 0 bits in a word. + + Copyright 2013-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE +#include "count-trailing-zeros.h" diff --git a/cross/lib/count-trailing-zeros.h b/cross/lib/count-trailing-zeros.h new file mode 100644 index 00000000000..ef8e164126a --- /dev/null +++ b/cross/lib/count-trailing-zeros.h @@ -0,0 +1,126 @@ +/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word. + Copyright 2013-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef COUNT_TRAILING_ZEROS_H +#define COUNT_TRAILING_ZEROS_H 1 + +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef COUNT_TRAILING_ZEROS_INLINE +# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN, + expand to code that computes the number of trailing zeros of the local + variable 'x' of type TYPE (an unsigned integer type) and return it + from the current function. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \ + || (__clang_major__ >= 4) +# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + return x ? BUILTIN (x) : CHAR_BIT * sizeof x; +#elif _MSC_VER +# pragma intrinsic (_BitScanForward) +# if defined _M_X64 +# pragma intrinsic (_BitScanForward64) +# endif +# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + unsigned long result; \ + return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \ + } \ + while (0) +#else +# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ + do \ + { \ + int count = 0; \ + if (! x) \ + return CHAR_BIT * sizeof x; \ + for (count = 0; \ + (count < CHAR_BIT * sizeof x - 32 \ + && ! (x & 0xffffffffU)); \ + count += 32) \ + x = x >> 31 >> 1; \ + return count + count_trailing_zeros_32 (x); \ + } \ + while (0) + +/* Compute and return the number of trailing zeros in the least + significant 32 bits of X. One of these bits must be nonzero. */ +COUNT_TRAILING_ZEROS_INLINE int +count_trailing_zeros_32 (unsigned int x) +{ + /* + */ + static const char de_Bruijn_lookup[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return de_Bruijn_lookup[(((x & -x) * 0x077cb531U) & 0xffffffffU) >> 27]; +} +#endif + +/* Compute and return the number of trailing zeros in X. */ +COUNT_TRAILING_ZEROS_INLINE int +count_trailing_zeros (unsigned int x) +{ + COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int); +} + +/* Compute and return the number of trailing zeros in X. */ +COUNT_TRAILING_ZEROS_INLINE int +count_trailing_zeros_l (unsigned long int x) +{ + COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int); +} + +/* Compute and return the number of trailing zeros in X. */ +COUNT_TRAILING_ZEROS_INLINE int +count_trailing_zeros_ll (unsigned long long int x) +{ +#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64 + /* 32-bit MSVC does not have _BitScanForward64, only _BitScanForward. */ + unsigned long result; + if (_BitScanForward (&result, (unsigned long) x)) + return result; + if (_BitScanForward (&result, (unsigned long) (x >> 32))) + return result + 32; + return CHAR_BIT * sizeof x; +#else + COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64, + unsigned long long int); +#endif +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif diff --git a/cross/lib/diffseq.h b/cross/lib/diffseq.h new file mode 100644 index 00000000000..dfaf4f295e8 --- /dev/null +++ b/cross/lib/diffseq.h @@ -0,0 +1,568 @@ +/* Analyze differences between two vectors. + + Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2023 Free Software + Foundation, Inc. + + This program is free software: you can 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 . */ + + +/* The basic idea is to consider two vectors as similar if, when + transforming the first vector into the second vector through a + sequence of edits (inserts and deletes of one element each), + this sequence is short - or equivalently, if the ordered list + of elements that are untouched by these edits is long. For a + good introduction to the subject, read about the "Levenshtein + distance" in Wikipedia. + + The basic algorithm is described in: + "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, + Algorithmica Vol. 1, 1986, pp. 251-266, + . + See especially section 4.2, which describes the variation used below. + + The basic algorithm was independently discovered as described in: + "Algorithms for Approximate String Matching", Esko Ukkonen, + Information and Control Vol. 64, 1985, pp. 100-118, + . + + Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE + heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) + at the price of producing suboptimal output for large inputs with + many differences. */ + +/* Before including this file, you need to define: + ELEMENT The element type of the vectors being compared. + EQUAL A two-argument macro that tests two elements for + equality. + OFFSET A signed integer type sufficient to hold the + difference between two indices. Usually + something like ptrdiff_t. + EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. + NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. + NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. + NOTE_ORDERED (Optional) A boolean expression saying that + NOTE_DELETE and NOTE_INSERT calls must be + issued in offset order. + EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an + early abort of the computation. + USE_HEURISTIC (Optional) Define if you want to support the + heuristic for large vectors. + + It is also possible to use this file with abstract arrays. In this case, + xvec and yvec are not represented in memory. They only exist conceptually. + In this case, the list of defines above is amended as follows: + ELEMENT Undefined. + EQUAL Undefined. + XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) + A three-argument macro: References xvec[xoff] and + yvec[yoff] and tests these elements for equality. + + Before including this file, you also need to include: + #include + #include "minmax.h" + */ + +/* Maximum value of type OFFSET. */ +#define OFFSET_MAX \ + ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) + +/* Default to no early abort. */ +#ifndef EARLY_ABORT +# define EARLY_ABORT(ctxt) false +#endif + +#ifndef NOTE_ORDERED +# define NOTE_ORDERED false +#endif + +/* Use this to suppress gcc's "...may be used before initialized" warnings. + Beware: The Code argument must not contain commas. */ +#ifndef IF_LINT +# if defined GCC_LINT || defined lint +# define IF_LINT(Code) Code +# else +# define IF_LINT(Code) /* empty */ +# endif +#endif + +/* + * Context of comparison operation. + */ +struct context +{ + #ifdef ELEMENT + /* Vectors being compared. */ + ELEMENT const *xvec; + ELEMENT const *yvec; + #endif + + /* Extra fields. */ + EXTRA_CONTEXT_FIELDS + + /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point + furthest along the given diagonal in the forward search of the edit + matrix. */ + OFFSET *fdiag; + + /* Vector, indexed by diagonal, containing the X coordinate of the point + furthest along the given diagonal in the backward search of the edit + matrix. */ + OFFSET *bdiag; + + #ifdef USE_HEURISTIC + /* This corresponds to the diff --speed-large-files flag. With this + heuristic, for vectors with a constant small density of changes, + the algorithm is linear in the vector size. */ + bool heuristic; + #endif + + /* Edit scripts longer than this are too expensive to compute. */ + OFFSET too_expensive; + + /* Snakes bigger than this are considered "big". */ + #define SNAKE_LIMIT 20 +}; + +struct partition +{ + /* Midpoints of this partition. */ + OFFSET xmid; + OFFSET ymid; + + /* True if low half will be analyzed minimally. */ + bool lo_minimal; + + /* Likewise for high half. */ + bool hi_minimal; +}; + + +/* Find the midpoint of the shortest edit script for a specified portion + of the two vectors. + + Scan from the beginnings of the vectors, and simultaneously from the ends, + doing a breadth-first search through the space of edit-sequence. + When the two searches meet, we have found the midpoint of the shortest + edit sequence. + + If FIND_MINIMAL is true, find the minimal edit script regardless of + expense. Otherwise, if the search is too expensive, use heuristics to + stop the search and report a suboptimal answer. + + Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number + XMID - YMID equals the number of inserted elements minus the number + of deleted elements (counting only elements before the midpoint). + + Set PART->lo_minimal to true iff the minimal edit script for the + left half of the partition is known; similarly for PART->hi_minimal. + + This function assumes that the first elements of the specified portions + of the two vectors do not match, and likewise that the last elements do not + match. The caller must trim matching elements from the beginning and end + of the portions it is going to specify. + + If we return the "wrong" partitions, the worst this can do is cause + suboptimal diff output. It cannot cause incorrect diff output. */ + +static void +diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal, + struct partition *part, struct context *ctxt) +{ + OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */ + OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */ +#ifdef ELEMENT + ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */ + ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */ + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */ + const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */ + const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */ + const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ + OFFSET fmin = fmid; + OFFSET fmax = fmid; /* Limits of top-down search. */ + OFFSET bmin = bmid; + OFFSET bmax = bmid; /* Limits of bottom-up search. */ + OFFSET c; /* Cost. */ + bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd + diagonal with respect to the northwest. */ + + fd[fmid] = xoff; + bd[bmid] = xlim; + + for (c = 1;; ++c) + { + OFFSET d; /* Active diagonal. */ + bool big_snake = false; + + /* Extend the top-down search by an edit step in each diagonal. */ + if (fmin > dmin) + fd[--fmin - 1] = -1; + else + ++fmin; + if (fmax < dmax) + fd[++fmax + 1] = -1; + else + --fmax; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = fd[d - 1]; + OFFSET thi = fd[d + 1]; + OFFSET x0 = tlo < thi ? thi : tlo + 1; + + for (x = x0, y = x0 - d; + x < xlim && y < ylim && XREF_YREF_EQUAL (x, y); + x++, y++) + continue; + if (x - x0 > SNAKE_LIMIT) + big_snake = true; + fd[d] = x; + if (odd && bmin <= d && d <= bmax && bd[d] <= x) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + /* Similarly extend the bottom-up search. */ + if (bmin > dmin) + bd[--bmin - 1] = OFFSET_MAX; + else + ++bmin; + if (bmax < dmax) + bd[++bmax + 1] = OFFSET_MAX; + else + --bmax; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x; + OFFSET y; + OFFSET tlo = bd[d - 1]; + OFFSET thi = bd[d + 1]; + OFFSET x0 = tlo < thi ? tlo : thi - 1; + + for (x = x0, y = x0 - d; + xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1); + x--, y--) + continue; + if (x0 - x > SNAKE_LIMIT) + big_snake = true; + bd[d] = x; + if (!odd && fmin <= d && d <= fmax && x <= fd[d]) + { + part->xmid = x; + part->ymid = y; + part->lo_minimal = part->hi_minimal = true; + return; + } + } + + if (find_minimal) + continue; + +#ifdef USE_HEURISTIC + bool heuristic = ctxt->heuristic; +#else + bool heuristic = false; +#endif + + /* Heuristic: check occasionally for a diagonal that has made lots + of progress compared with the edit distance. If we have any + such, find the one that has made the most progress and return it + as if it had succeeded. + + With this heuristic, for vectors with a constant small density + of changes, the algorithm is linear in the vector size. */ + + if (200 < c && big_snake && heuristic) + { + { + OFFSET best = 0; + + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET dd = d - fmid; + OFFSET x = fd[d]; + OFFSET y = x - d; + OFFSET v = (x - xoff) * 2 - dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff + SNAKE_LIMIT <= x && x < xlim + && yoff + SNAKE_LIMIT <= y && y < ylim) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++) + if (k == SNAKE_LIMIT) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = true; + part->hi_minimal = false; + return; + } + } + + { + OFFSET best = 0; + + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET dd = d - bmid; + OFFSET x = bd[d]; + OFFSET y = x - d; + OFFSET v = (xlim - x) * 2 + dd; + + if (v > 12 * (c + (dd < 0 ? -dd : dd))) + { + if (v > best + && xoff < x && x <= xlim - SNAKE_LIMIT + && yoff < y && y <= ylim - SNAKE_LIMIT) + { + /* We have a good enough best diagonal; now insist + that it end with a significant snake. */ + int k; + + for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++) + if (k == SNAKE_LIMIT - 1) + { + best = v; + part->xmid = x; + part->ymid = y; + break; + } + } + } + } + if (best > 0) + { + part->lo_minimal = false; + part->hi_minimal = true; + return; + } + } + } + + /* Heuristic: if we've gone well beyond the call of duty, give up + and report halfway between our best results so far. */ + if (c >= ctxt->too_expensive) + { + OFFSET fxybest; + OFFSET fxbest IF_LINT (= 0); + OFFSET bxybest; + OFFSET bxbest IF_LINT (= 0); + + /* Find forward diagonal that maximizes X + Y. */ + fxybest = -1; + for (d = fmax; d >= fmin; d -= 2) + { + OFFSET x = MIN (fd[d], xlim); + OFFSET y = x - d; + if (ylim < y) + { + x = ylim + d; + y = ylim; + } + if (fxybest < x + y) + { + fxybest = x + y; + fxbest = x; + } + } + + /* Find backward diagonal that minimizes X + Y. */ + bxybest = OFFSET_MAX; + for (d = bmax; d >= bmin; d -= 2) + { + OFFSET x = MAX (xoff, bd[d]); + OFFSET y = x - d; + if (y < yoff) + { + x = yoff + d; + y = yoff; + } + if (x + y < bxybest) + { + bxybest = x + y; + bxbest = x; + } + } + + /* Use the better of the two diagonals. */ + if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) + { + part->xmid = fxbest; + part->ymid = fxybest - fxbest; + part->lo_minimal = true; + part->hi_minimal = false; + } + else + { + part->xmid = bxbest; + part->ymid = bxybest - bxbest; + part->lo_minimal = false; + part->hi_minimal = true; + } + return; + } + } + #undef XREF_YREF_EQUAL +} + + +/* Compare in detail contiguous subsequences of the two vectors + which are known, as a whole, to match each other. + + The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1. + + Note that XLIM, YLIM are exclusive bounds. All indices into the vectors + are origin-0. + + If FIND_MINIMAL, find a minimal difference no matter how + expensive it is. + + The results are recorded by invoking NOTE_DELETE and NOTE_INSERT. + + Return false if terminated normally, or true if terminated through early + abort. */ + +static bool +compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, + bool find_minimal, struct context *ctxt) +{ +#ifdef ELEMENT + ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */ + ELEMENT const *yv = ctxt->yvec; + #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) +#else + #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) +#endif + + while (true) + { + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + { + xoff++; + yoff++; + } + + /* Slide up the top initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) + { + xlim--; + ylim--; + } + + /* Handle simple cases. */ + if (xoff == xlim) + { + while (yoff < ylim) + { + NOTE_INSERT (ctxt, yoff); + if (EARLY_ABORT (ctxt)) + return true; + yoff++; + } + break; + } + if (yoff == ylim) + { + while (xoff < xlim) + { + NOTE_DELETE (ctxt, xoff); + if (EARLY_ABORT (ctxt)) + return true; + xoff++; + } + break; + } + + struct partition part; + + /* Find a point of correspondence in the middle of the vectors. */ + diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt); + + /* Use the partitions to split this problem into subproblems. */ + OFFSET xoff1, xlim1, yoff1, ylim1, xoff2, xlim2, yoff2, ylim2; + bool find_minimal1, find_minimal2; + if (!NOTE_ORDERED + && ((xlim + ylim) - (part.xmid + part.ymid) + < (part.xmid + part.ymid) - (xoff + yoff))) + { + /* The second problem is smaller and the caller doesn't + care about order, so do the second problem first to + lessen recursion. */ + xoff1 = part.xmid; xlim1 = xlim; + yoff1 = part.ymid; ylim1 = ylim; + find_minimal1 = part.hi_minimal; + + xoff2 = xoff; xlim2 = part.xmid; + yoff2 = yoff; ylim2 = part.ymid; + find_minimal2 = part.lo_minimal; + } + else + { + xoff1 = xoff; xlim1 = part.xmid; + yoff1 = yoff; ylim1 = part.ymid; + find_minimal1 = part.lo_minimal; + + xoff2 = part.xmid; xlim2 = xlim; + yoff2 = part.ymid; ylim2 = ylim; + find_minimal2 = part.hi_minimal; + } + + /* Recurse to do one subproblem. */ + bool early = compareseq (xoff1, xlim1, yoff1, ylim1, find_minimal1, ctxt); + if (early) + return early; + + /* Iterate to do the other subproblem. */ + xoff = xoff2; xlim = xlim2; + yoff = yoff2; ylim = ylim2; + find_minimal = find_minimal2; + } + + return false; + #undef XREF_YREF_EQUAL +} + +#undef ELEMENT +#undef EQUAL +#undef OFFSET +#undef EXTRA_CONTEXT_FIELDS +#undef NOTE_DELETE +#undef NOTE_INSERT +#undef EARLY_ABORT +#undef USE_HEURISTIC +#undef XVECREF_YVECREF_EQUAL +#undef OFFSET_MAX diff --git a/cross/lib/dirent.in.h b/cross/lib/dirent.in.h new file mode 100644 index 00000000000..2aaabd054a8 --- /dev/null +++ b/cross/lib/dirent.in.h @@ -0,0 +1,321 @@ +/* A GNU-like . + Copyright (C) 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_DIRENT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_DIRENT_H@ +# @INCLUDE_NEXT@ @NEXT_DIRENT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_DIRENT_H +#define _@GUARD_PREFIX@_DIRENT_H + +/* Get ino_t. Needed on some systems, including glibc 2.8. */ +#include + +#if !@HAVE_DIRENT_H@ +/* Define types DIR and 'struct dirent'. */ +# if !GNULIB_defined_struct_dirent +struct dirent +{ + char d_type; + char d_name[1]; +}; +/* Possible values for 'd_type'. */ +# define DT_UNKNOWN 0 +# define DT_FIFO 1 /* FIFO */ +# define DT_CHR 2 /* character device */ +# define DT_DIR 4 /* directory */ +# define DT_BLK 6 /* block device */ +# define DT_REG 8 /* regular file */ +# define DT_LNK 10 /* symbolic link */ +# define DT_SOCK 12 /* socket */ +# define DT_WHT 14 /* whiteout */ +typedef struct gl_directory DIR; +# define GNULIB_defined_struct_dirent 1 +# endif +#endif + +/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. */ +#ifndef _GL_ATTRIBUTE_DEALLOC +# if __GNUC__ >= 11 +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) +# else +# define _GL_ATTRIBUTE_DEALLOC(f, i) +# endif +#endif + +/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly + allocated memory. */ +/* Applies to: functions. */ +#ifndef _GL_ATTRIBUTE_MALLOC +# if __GNUC__ >= 3 || defined __clang__ +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define _GL_ATTRIBUTE_MALLOC +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#ifndef _GL_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_CLOSEDIR@ +# if @REPLACE_CLOSEDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef closedir +# define closedir rpl_closedir +# define GNULIB_defined_closedir 1 +# endif +_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); +# else +# if !@HAVE_CLOSEDIR@ +_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp)); +# endif +_GL_CXXALIASWARN (closedir); +#elif defined GNULIB_POSIXCHECK +# undef closedir +# if HAVE_RAW_DECL_CLOSEDIR +_GL_WARN_ON_USE (closedir, "closedir is not portable - " + "use gnulib module closedir for portability"); +# endif +#endif + +#if @GNULIB_OPENDIR@ +# if @REPLACE_OPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef opendir +# define opendir rpl_opendir +# define GNULIB_defined_opendir 1 +# endif +_GL_FUNCDECL_RPL (opendir, DIR *, + (const char *dir_name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); +# else +# if !@HAVE_OPENDIR@ || __GNUC__ >= 11 +_GL_FUNCDECL_SYS (opendir, DIR *, + (const char *dir_name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +# endif +_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name)); +# endif +_GL_CXXALIASWARN (opendir); +#else +# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined opendir +/* For -Wmismatched-dealloc: Associate opendir with closedir or + rpl_closedir. */ +_GL_FUNCDECL_SYS (opendir, DIR *, + (const char *dir_name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef opendir +# if HAVE_RAW_DECL_OPENDIR +_GL_WARN_ON_USE (opendir, "opendir is not portable - " + "use gnulib module opendir for portability"); +# endif +# endif +#endif + +#if @GNULIB_READDIR@ +# if !@HAVE_READDIR@ +_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp)); +_GL_CXXALIASWARN (readdir); +#elif defined GNULIB_POSIXCHECK +# undef readdir +# if HAVE_RAW_DECL_READDIR +_GL_WARN_ON_USE (readdir, "readdir is not portable - " + "use gnulib module readdir for portability"); +# endif +#endif + +#if @GNULIB_REWINDDIR@ +# if !@HAVE_REWINDDIR@ +_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp)); +_GL_CXXALIASWARN (rewinddir); +#elif defined GNULIB_POSIXCHECK +# undef rewinddir +# if HAVE_RAW_DECL_REWINDDIR +_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " + "use gnulib module rewinddir for portability"); +# endif +#endif + +#if @GNULIB_DIRFD@ +/* Return the file descriptor associated with the given directory stream, + or -1 if none exists. */ +# if @REPLACE_DIRFD@ +/* On kLIBC, dirfd() is a macro that does not work. Undefine it. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) || defined dirfd +# undef dirfd +# define dirfd rpl_dirfd +# endif +_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (dirfd, int, (DIR *)); + +# ifdef __KLIBC__ +/* Gnulib internal hooks needed to maintain the dirfd metadata. */ +_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp) + _GL_ARG_NONNULL ((2)); +_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd); +# endif +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd + /* dirfd is defined as a macro and not as a function. + Turn it into a function and get rid of the macro. */ +static inline int (dirfd) (DIR *dp) { return dirfd (dp); } +# undef dirfd +# endif +# if !(@HAVE_DECL_DIRFD@ || defined dirfd) +_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (dirfd, int, (DIR *)); +# endif +_GL_CXXALIASWARN (dirfd); +#elif defined GNULIB_POSIXCHECK +# undef dirfd +# if HAVE_RAW_DECL_DIRFD +_GL_WARN_ON_USE (dirfd, "dirfd is unportable - " + "use gnulib module dirfd for portability"); +# endif +#endif + +#if @GNULIB_FDOPENDIR@ +/* Open a directory stream visiting the given directory file + descriptor. Return NULL and set errno if fd is not visiting a + directory. On success, this function consumes fd (it will be + implicitly closed either by this function or by a subsequent + closedir). */ +# if @REPLACE_FDOPENDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopendir +# define fdopendir rpl_fdopendir +# endif +_GL_FUNCDECL_RPL (fdopendir, DIR *, + (int fd) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd)); +# else +# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ || __GNUC__ >= 11 +_GL_FUNCDECL_SYS (fdopendir, DIR *, + (int fd) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +# endif +_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd)); +# endif +_GL_CXXALIASWARN (fdopendir); +#else +# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined fdopendir +/* For -Wmismatched-dealloc: Associate fdopendir with closedir or + rpl_closedir. */ +_GL_FUNCDECL_SYS (fdopendir, DIR *, + (int fd) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef fdopendir +# if HAVE_RAW_DECL_FDOPENDIR +_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - " + "use gnulib module fdopendir for portability"); +# endif +# endif +#endif + +#if @GNULIB_SCANDIR@ +/* Scan the directory DIR, calling FILTER on each directory entry. + Entries for which FILTER returns nonzero are individually malloc'd, + sorted using qsort with CMP, and collected in a malloc'd array in + *NAMELIST. Returns the number of entries selected, or -1 on error. */ +# if !@HAVE_SCANDIR@ +_GL_FUNCDECL_SYS (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **)) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +/* Need to cast, because on glibc systems, the fourth parameter is + int (*cmp) (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (scandir, int, + (const char *dir, struct dirent ***namelist, + int (*filter) (const struct dirent *), + int (*cmp) (const struct dirent **, const struct dirent **))); +_GL_CXXALIASWARN (scandir); +#elif defined GNULIB_POSIXCHECK +# undef scandir +# if HAVE_RAW_DECL_SCANDIR +_GL_WARN_ON_USE (scandir, "scandir is unportable - " + "use gnulib module scandir for portability"); +# endif +#endif + +#if @GNULIB_ALPHASORT@ +/* Compare two 'struct dirent' entries alphabetically. */ +# if !@HAVE_ALPHASORT@ +_GL_FUNCDECL_SYS (alphasort, int, + (const struct dirent **, const struct dirent **) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +/* Need to cast, because on glibc systems, the parameters are + (const void *, const void *). */ +_GL_CXXALIAS_SYS_CAST (alphasort, int, + (const struct dirent **, const struct dirent **)); +_GL_CXXALIASWARN (alphasort); +#elif defined GNULIB_POSIXCHECK +# undef alphasort +# if HAVE_RAW_DECL_ALPHASORT +_GL_WARN_ON_USE (alphasort, "alphasort is unportable - " + "use gnulib module alphasort for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_DIRENT_H */ +#endif /* _@GUARD_PREFIX@_DIRENT_H */ diff --git a/cross/lib/dirfd.c b/cross/lib/dirfd.c new file mode 100644 index 00000000000..b2b1d25cdbd --- /dev/null +++ b/cross/lib/dirfd.c @@ -0,0 +1,98 @@ +/* dirfd.c -- return the file descriptor associated with an open DIR* + + Copyright (C) 2001, 2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Jim Meyering. */ + +#include + +#include +#include + +#ifdef __KLIBC__ +# include +# include + +static struct dirp_fd_list +{ + DIR *dirp; + int fd; + struct dirp_fd_list *next; +} *dirp_fd_start = NULL; + +/* Register fd associated with dirp to dirp_fd_list. */ +int +_gl_register_dirp_fd (int fd, DIR *dirp) +{ + struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd); + if (!new_dirp_fd) + return -1; + + new_dirp_fd->dirp = dirp; + new_dirp_fd->fd = fd; + new_dirp_fd->next = dirp_fd_start; + + dirp_fd_start = new_dirp_fd; + + return 0; +} + +/* Unregister fd from dirp_fd_list with closing it */ +void +_gl_unregister_dirp_fd (int fd) +{ + struct dirp_fd_list *dirp_fd; + struct dirp_fd_list *dirp_fd_prev; + + for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd; + dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next) + { + if (dirp_fd->fd == fd) + { + if (dirp_fd_prev) + dirp_fd_prev->next = dirp_fd->next; + else /* dirp_fd == dirp_fd_start */ + dirp_fd_start = dirp_fd_start->next; + + close (fd); + free (dirp_fd); + break; + } + } +} +#endif + +int +dirfd (DIR *dir_p) +{ + int fd = DIR_TO_FD (dir_p); + if (fd == -1) +#ifndef __KLIBC__ + errno = ENOTSUP; +#else + { + struct dirp_fd_list *dirp_fd; + + for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next) + if (dirp_fd->dirp == dir_p) + return dirp_fd->fd; + + errno = EINVAL; + } +#endif + + return fd; +} diff --git a/cross/lib/dtoastr.c b/cross/lib/dtoastr.c new file mode 100644 index 00000000000..66b50995c79 --- /dev/null +++ b/cross/lib/dtoastr.c @@ -0,0 +1,19 @@ +/* Convert 'double' to accurate string. + + Copyright (C) 2010-2023 Free Software Foundation, Inc. + + This file is free software: you can 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 file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU 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 . */ + +#define LENGTH 2 +#include "ftoastr.c" diff --git a/cross/lib/dtotimespec.c b/cross/lib/dtotimespec.c new file mode 100644 index 00000000000..28a44b69171 --- /dev/null +++ b/cross/lib/dtotimespec.c @@ -0,0 +1,53 @@ +/* Convert double to timespec. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Paul Eggert */ + +/* Convert the double value SEC to a struct timespec. Round toward + positive infinity. On overflow, return an extremal value. */ + +#include + +#include "timespec.h" + +#include "intprops.h" + +struct timespec +dtotimespec (double sec) +{ + if (! (TYPE_MINIMUM (time_t) < sec)) + return make_timespec (TYPE_MINIMUM (time_t), 0); + else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) + return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1); + else + { + time_t s = sec; + double frac = TIMESPEC_HZ * (sec - s); + long ns = frac; + ns += ns < frac; + s += ns / TIMESPEC_HZ; + ns %= TIMESPEC_HZ; + + if (ns < 0) + { + s--; + ns += TIMESPEC_HZ; + } + + return make_timespec (s, ns); + } +} diff --git a/cross/lib/dup2.c b/cross/lib/dup2.c new file mode 100644 index 00000000000..7d197ca3123 --- /dev/null +++ b/cross/lib/dup2.c @@ -0,0 +1,189 @@ +/* Duplicate an open file descriptor to a specified file descriptor. + + Copyright (C) 1999, 2004-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Paul Eggert */ + +#include + +/* Specification. */ +#include + +#include +#include + +#undef dup2 + +#if defined _WIN32 && ! defined __CYGWIN__ + +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif + +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include +# endif + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +dup2_nothrow (int fd, int desired_fd) +{ + int result; + + TRY_MSVC_INVAL + { + result = _dup2 (fd, desired_fd); + } + CATCH_MSVC_INVAL + { + errno = EBADF; + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define dup2_nothrow _dup2 +# endif + +static int +ms_windows_dup2 (int fd, int desired_fd) +{ + int result; + + /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, + dup2 (fd, fd) returns 0, but all further attempts to use fd in + future dup2 calls will hang. */ + if (fd == desired_fd) + { + if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + return fd; + } + + /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: + https://bugs.winehq.org/show_bug.cgi?id=21289 */ + if (desired_fd < 0) + { + errno = EBADF; + return -1; + } + + result = dup2_nothrow (fd, desired_fd); + + if (result == 0) + result = desired_fd; + + return result; +} + +# define dup2 ms_windows_dup2 + +#elif defined __KLIBC__ + +# include + +static int +klibc_dup2dirfd (int fd, int desired_fd) +{ + int tempfd; + int dupfd; + + tempfd = open ("NUL", O_RDONLY); + if (tempfd == -1) + return -1; + + if (tempfd == desired_fd) + { + close (tempfd); + + char path[_MAX_PATH]; + if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) + return -1; + + return open(path, O_RDONLY); + } + + dupfd = klibc_dup2dirfd (fd, desired_fd); + + close (tempfd); + + return dupfd; +} + +static int +klibc_dup2 (int fd, int desired_fd) +{ + int dupfd; + struct stat sbuf; + + dupfd = dup2 (fd, desired_fd); + if (dupfd == -1 && errno == ENOTSUP \ + && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + close (desired_fd); + + return klibc_dup2dirfd (fd, desired_fd); + } + + return dupfd; +} + +# define dup2 klibc_dup2 +#endif + +int +rpl_dup2 (int fd, int desired_fd) +{ + int result; + +#ifdef F_GETFL + /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. + On Cygwin 1.5.x, dup2 (1, 1) returns 0. + On Cygwin 1.7.17, dup2 (1, -1) dumps core. + On Cygwin 1.7.25, dup2 (1, 256) can dump core. + On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ +# if HAVE_SETDTABLESIZE + setdtablesize (desired_fd + 1); +# endif + if (desired_fd < 0) + fd = desired_fd; + if (fd == desired_fd) + return fcntl (fd, F_GETFL) == -1 ? -1 : fd; +#endif + + result = dup2 (fd, desired_fd); + + /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ + if (result == -1 && errno == EMFILE) + errno = EBADF; +#if REPLACE_FCHDIR + if (fd != desired_fd && result != -1) + result = _gl_register_dup (fd, result); +#endif + return result; +} diff --git a/cross/lib/dynarray.h b/cross/lib/dynarray.h new file mode 100644 index 00000000000..9155910934f --- /dev/null +++ b/cross/lib/dynarray.h @@ -0,0 +1,284 @@ +/* Type-safe arrays which grow dynamically. + Copyright 2021-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert and Bruno Haible, 2021. */ + +#ifndef _GL_DYNARRAY_H +#define _GL_DYNARRAY_H + +/* Before including this file, you need to define: + + DYNARRAY_STRUCT + The struct tag of dynamic array to be defined. + + DYNARRAY_ELEMENT + The type name of the element type. Elements are copied + as if by memcpy, and can change address as the dynamic + array grows. + + DYNARRAY_PREFIX + The prefix of the functions which are defined. + + The following parameters are optional: + + DYNARRAY_ELEMENT_FREE + DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the + contents of elements. E is of type DYNARRAY_ELEMENT *. + + DYNARRAY_ELEMENT_INIT + DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new + element. E is of type DYNARRAY_ELEMENT *. + If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is + defined, new elements are automatically zero-initialized. + Otherwise, new elements have undefined contents. + + DYNARRAY_INITIAL_SIZE + The size of the statically allocated array (default: + at least 2, more elements if they fit into 128 bytes). + Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, + there is no statically allocated array at, and all non-empty + arrays are heap-allocated. + + DYNARRAY_FINAL_TYPE + The name of the type which holds the final array. If not + defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE + must be a struct type, with members of type DYNARRAY_ELEMENT and + size_t at the start (in this order). + + These macros are undefined after this header file has been + included. + + The following types are provided (their members are private to the + dynarray implementation): + + struct DYNARRAY_STRUCT + + The following functions are provided: + */ + +/* Initialize a dynamic array object. This must be called before any + use of the object. */ +#if 0 +static void + DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *list); +#endif + +/* Deallocate the dynamic array and its elements. */ +#if 0 +static void + DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *list); +#endif + +/* Return true if the dynamic array is in an error state. */ +#if 0 +static bool + DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *list); +#endif + +/* Mark the dynamic array as failed. All elements are deallocated as + a side effect. */ +#if 0 +static void + DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *list); +#endif + +/* Return the number of elements which have been added to the dynamic + array. */ +#if 0 +static size_t + DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *list); +#endif + +/* Return a pointer to the first array element, if any. For a + zero-length array, the pointer can be NULL even though the dynamic + array has not entered the failure state. */ +#if 0 +static DYNARRAY_ELEMENT * + DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *list); +#endif + +/* Return a pointer one element past the last array element. For a + zero-length array, the pointer can be NULL even though the dynamic + array has not entered the failure state. */ +#if 0 +static DYNARRAY_ELEMENT * + DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *list); +#endif + +/* Return a pointer to the array element at INDEX. Terminate the + process if INDEX is out of bounds. */ +#if 0 +static DYNARRAY_ELEMENT * + DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *list, size_t index); +#endif + +/* Add ITEM at the end of the array, enlarging it by one element. + Mark *LIST as failed if the dynamic array allocation size cannot be + increased. */ +#if 0 +static void + DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *list, + DYNARRAY_ELEMENT item); +#endif + +/* Allocate a place for a new element in *LIST and return a pointer to + it. The pointer can be NULL if the dynamic array cannot be + enlarged due to a memory allocation failure. */ +#if 0 +static DYNARRAY_ELEMENT * + DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *list); +#endif + +/* Change the size of *LIST to SIZE. If SIZE is larger than the + existing size, new elements are added (which can be initialized). + Otherwise, the list is truncated, and elements are freed. Return + false on memory allocation failure (and mark *LIST as failed). */ +#if 0 +static bool + DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *list, size_t size); +#endif + +/* Remove the last element of LIST if it is present. */ +#if 0 +static void + DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *list); +#endif + +/* Remove all elements from the list. The elements are freed, but the + list itself is not. */ +#if 0 +static void + DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *list); +#endif + +#if defined DYNARRAY_FINAL_TYPE +/* Transfer the dynamic array to a permanent location at *RESULT. + Returns true on success on false on allocation failure. In either + case, *LIST is re-initialized and can be reused. A NULL pointer is + stored in *RESULT if LIST refers to an empty list. On success, the + pointer in *RESULT is heap-allocated and must be deallocated using + free. */ +#if 0 +static bool + DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list, + DYNARRAY_FINAL_TYPE *result); +#endif +#else /* !defined DYNARRAY_FINAL_TYPE */ +/* Transfer the dynamic array to a heap-allocated array and return a + pointer to it. The pointer is NULL if memory allocation fails, or + if the array is empty, so this function should be used only for + arrays which are known not be empty (usually because they always + have a sentinel at the end). If LENGTHP is not NULL, the array + length is written to *LENGTHP. *LIST is re-initialized and can be + reused. */ +#if 0 +static DYNARRAY_ELEMENT * + DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list, + size_t *lengthp); +#endif +#endif + +/* A minimal example which provides a growing list of integers can be + defined like this: + + struct int_array + { + // Pointer to result array followed by its length, + // as required by DYNARRAY_FINAL_TYPE. + int *array; + size_t length; + }; + + #define DYNARRAY_STRUCT dynarray_int + #define DYNARRAY_ELEMENT int + #define DYNARRAY_PREFIX dynarray_int_ + #define DYNARRAY_FINAL_TYPE struct int_array + #include + + To create a three-element array with elements 1, 2, 3, use this + code: + + struct dynarray_int dyn; + dynarray_int_init (&dyn); + for (int i = 1; i <= 3; ++i) + { + int *place = dynarray_int_emplace (&dyn); + assert (place != NULL); + *place = i; + } + struct int_array result; + bool ok = dynarray_int_finalize (&dyn, &result); + assert (ok); + assert (result.length == 3); + assert (result.array[0] == 1); + assert (result.array[1] == 2); + assert (result.array[2] == 3); + free (result.array); + + If the elements contain resources which must be freed, define + DYNARRAY_ELEMENT_FREE appropriately, like this: + + struct str_array + { + char **array; + size_t length; + }; + + #define DYNARRAY_STRUCT dynarray_str + #define DYNARRAY_ELEMENT char * + #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) + #define DYNARRAY_PREFIX dynarray_str_ + #define DYNARRAY_FINAL_TYPE struct str_array + #include + */ + + +/* The implementation is imported from glibc. */ + +/* Avoid possible conflicts with symbols exported by the GNU libc. */ +#define __libc_dynarray_at_failure gl_dynarray_at_failure +#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge +#define __libc_dynarray_finalize gl_dynarray_finalize +#define __libc_dynarray_resize_clear gl_dynarray_resize_clear +#define __libc_dynarray_resize gl_dynarray_resize + +#if defined DYNARRAY_STRUCT || defined DYNARRAY_ELEMENT || defined DYNARRAY_PREFIX + +# ifndef _GL_LIKELY +/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ +# define _GL_LIKELY(cond) __builtin_expect ((cond), 1) +# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0) +# endif + +/* Define auxiliary structs and declare auxiliary functions, common to all + instantiations of dynarray. */ +# include + +/* Define the instantiation, specified through + DYNARRAY_STRUCT + DYNARRAY_ELEMENT + DYNARRAY_PREFIX + etc. */ +# include + +#else + +/* This file is being included from one of the malloc/dynarray_*.c files. */ +# include + +#endif + +#endif /* _GL_DYNARRAY_H */ diff --git a/cross/lib/eloop-threshold.h b/cross/lib/eloop-threshold.h new file mode 100644 index 00000000000..510f261795d --- /dev/null +++ b/cross/lib/eloop-threshold.h @@ -0,0 +1,83 @@ +/* Threshold at which to diagnose ELOOP. Generic version. + Copyright (C) 2012-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _ELOOP_THRESHOLD_H +#define _ELOOP_THRESHOLD_H 1 + +#include +#ifdef _LIBC +# include +# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) +#else +# include +# include "minmax.h" +# define __sysconf sysconf +# if (!defined SYMLOOP_MAX \ + && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX)) +# define SYMLOOP_MAX 8 +# endif +#endif + +/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic + links that can be reliably traversed in the resolution of a + pathname in the absence of a loop." This makes it a minimum that + we should certainly accept. But it leaves open the possibility + that more might sometimes work--just not "reliably". + + For example, Linux implements a complex policy whereby there is a + small limit on the number of direct symlink traversals (a symlink + to a symlink to a symlink), but larger limit on the total number of + symlink traversals overall. Hence the SYMLOOP_MAX number should be + the small one, but the limit library functions enforce on users + should be the larger one. + + So, we use the larger of the reported SYMLOOP_MAX (if any) and our + own constant MIN_ELOOP_THRESHOLD, below. This constant should be + large enough that it never rules out a file name and directory tree + that the underlying system (i.e. calls to 'open' et al) would + resolve successfully. It should be small enough that actual loops + are detected without a huge number of iterations. */ + +#ifndef MIN_ELOOP_THRESHOLD +# define MIN_ELOOP_THRESHOLD 40 +#endif + +/* Return the maximum number of symlink traversals to permit + before diagnosing ELOOP. */ +static inline unsigned int _GL_ATTRIBUTE_CONST +__eloop_threshold (void) +{ +#ifdef SYMLOOP_MAX + const int symloop_max = SYMLOOP_MAX; +#else + /* The function is marked 'const' even though we use memory and + call a function, because sysconf is required to return the + same value in every call and so it must always be safe to + call __eloop_threshold exactly once and reuse the value. */ + static long int sysconf_symloop_max; + if (sysconf_symloop_max == 0) + sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX); + const unsigned int symloop_max = (sysconf_symloop_max <= 0 + ? _POSIX_SYMLOOP_MAX + : sysconf_symloop_max); +#endif + + return MAX (symloop_max, MIN_ELOOP_THRESHOLD); +} + +#endif /* eloop-threshold.h */ diff --git a/cross/lib/errno.in.h b/cross/lib/errno.in.h new file mode 100644 index 00000000000..3dda9c260e6 --- /dev/null +++ b/cross/lib/errno.in.h @@ -0,0 +1,279 @@ +/* A POSIX-like . + + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_ERRNO_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_ERRNO_H@ + +#ifndef _@GUARD_PREFIX@_ERRNO_H +#define _@GUARD_PREFIX@_ERRNO_H + + +/* On native Windows platforms, many macros are not defined. */ +# if defined _WIN32 && ! defined __CYGWIN__ + +/* These are the same values as defined by MSVC 10, for interoperability. */ + +# ifndef ENOMSG +# define ENOMSG 122 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 111 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 121 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 134 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 104 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 129 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 117 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 105 +# define GNULIB_defined_ECANCELED 1 +# endif + +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# define GNULIB_defined_EOWNERDEAD 1 +# endif + +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# define EALREADY 103 +# define ENOTSOCK 128 +# define EDESTADDRREQ 109 +# define EMSGSIZE 115 +# define EPROTOTYPE 136 +# define ENOPROTOOPT 123 +# define EPROTONOSUPPORT 135 +# define EOPNOTSUPP 130 +# define EAFNOSUPPORT 102 +# define EADDRINUSE 100 +# define EADDRNOTAVAIL 101 +# define ENETDOWN 116 +# define ENETUNREACH 118 +# define ECONNRESET 108 +# define ENOBUFS 119 +# define EISCONN 113 +# define ENOTCONN 126 +# define ETIMEDOUT 138 +# define ECONNREFUSED 107 +# define ELOOP 114 +# define EHOSTUNREACH 110 +# define EWOULDBLOCK 140 +# define GNULIB_defined_ESOCK 1 +# endif + +# ifndef ETXTBSY +# define ETXTBSY 139 +# define ENODATA 120 /* not required by POSIX */ +# define ENOSR 124 /* not required by POSIX */ +# define ENOSTR 125 /* not required by POSIX */ +# define ETIME 137 /* not required by POSIX */ +# define EOTHER 131 /* not required by POSIX */ +# define GNULIB_defined_ESTREAMS 1 +# endif + +/* These are intentionally the same values as the WSA* error numbers, defined + in . */ +# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */ +# define EPFNOSUPPORT 10046 /* not required by POSIX */ +# define ESHUTDOWN 10058 /* not required by POSIX */ +# define ETOOMANYREFS 10059 /* not required by POSIX */ +# define EHOSTDOWN 10064 /* not required by POSIX */ +# define EPROCLIM 10067 /* not required by POSIX */ +# define EUSERS 10068 /* not required by POSIX */ +# define EDQUOT 10069 +# define ESTALE 10070 +# define EREMOTE 10071 /* not required by POSIX */ +# define GNULIB_defined_EWINSOCK 1 + +# endif + + +/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros + EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */ +# if @EMULTIHOP_HIDDEN@ +# define EMULTIHOP @EMULTIHOP_VALUE@ +# define GNULIB_defined_EMULTIHOP 1 +# endif +# if @ENOLINK_HIDDEN@ +# define ENOLINK @ENOLINK_VALUE@ +# define GNULIB_defined_ENOLINK 1 +# endif +# if @EOVERFLOW_HIDDEN@ +# define EOVERFLOW @EOVERFLOW_VALUE@ +# define GNULIB_defined_EOVERFLOW 1 +# endif + + +/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, + EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. + Likewise, on NonStop Kernel, EDQUOT is not defined. + Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, + HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. + + Note: When one of these systems defines some of these macros some day, + binaries will have to be recompiled so that they recognizes the new + errno values from the system. */ + +# ifndef ENOMSG +# define ENOMSG 2000 +# define GNULIB_defined_ENOMSG 1 +# endif + +# ifndef EIDRM +# define EIDRM 2001 +# define GNULIB_defined_EIDRM 1 +# endif + +# ifndef ENOLINK +# define ENOLINK 2002 +# define GNULIB_defined_ENOLINK 1 +# endif + +# ifndef EPROTO +# define EPROTO 2003 +# define GNULIB_defined_EPROTO 1 +# endif + +# ifndef EMULTIHOP +# define EMULTIHOP 2004 +# define GNULIB_defined_EMULTIHOP 1 +# endif + +# ifndef EBADMSG +# define EBADMSG 2005 +# define GNULIB_defined_EBADMSG 1 +# endif + +# ifndef EOVERFLOW +# define EOVERFLOW 2006 +# define GNULIB_defined_EOVERFLOW 1 +# endif + +# ifndef ENOTSUP +# define ENOTSUP 2007 +# define GNULIB_defined_ENOTSUP 1 +# endif + +# ifndef ENETRESET +# define ENETRESET 2011 +# define GNULIB_defined_ENETRESET 1 +# endif + +# ifndef ECONNABORTED +# define ECONNABORTED 2012 +# define GNULIB_defined_ECONNABORTED 1 +# endif + +# ifndef ESTALE +# define ESTALE 2009 +# define GNULIB_defined_ESTALE 1 +# endif + +# ifndef EDQUOT +# define EDQUOT 2010 +# define GNULIB_defined_EDQUOT 1 +# endif + +# ifndef ECANCELED +# define ECANCELED 2008 +# define GNULIB_defined_ECANCELED 1 +# endif + +/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not + defined. */ + +# ifndef EOWNERDEAD +# if defined __sun + /* Use the same values as defined for Solaris >= 8, for + interoperability. */ +# define EOWNERDEAD 58 +# define ENOTRECOVERABLE 59 +# elif defined _WIN32 && ! defined __CYGWIN__ + /* We have a conflict here: pthreads-win32 defines these values + differently than MSVC 10. It's hairy to decide which one to use. */ +# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS + /* Use the same values as defined by pthreads-win32, for + interoperability. */ +# define EOWNERDEAD 43 +# define ENOTRECOVERABLE 44 +# else + /* Use the same values as defined by MSVC 10, for + interoperability. */ +# define EOWNERDEAD 133 +# define ENOTRECOVERABLE 127 +# endif +# else +# define EOWNERDEAD 2013 +# define ENOTRECOVERABLE 2014 +# endif +# define GNULIB_defined_EOWNERDEAD 1 +# define GNULIB_defined_ENOTRECOVERABLE 1 +# endif + +# ifndef EILSEQ +# define EILSEQ 2015 +# define GNULIB_defined_EILSEQ 1 +# endif + +#endif /* _@GUARD_PREFIX@_ERRNO_H */ +#endif /* _@GUARD_PREFIX@_ERRNO_H */ diff --git a/cross/lib/euidaccess.c b/cross/lib/euidaccess.c new file mode 100644 index 00000000000..c2ecbeff52a --- /dev/null +++ b/cross/lib/euidaccess.c @@ -0,0 +1,226 @@ +/* euidaccess -- check if effective user id can access file + + Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2023 Free + Software Foundation, Inc. + + This file is part of the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by David MacKenzie and Torbjorn Granlund. + Adapted for GNU C library by Roland McGrath. */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include +#include +#if defined _WIN32 && ! defined __CYGWIN__ +# include +#else +# include "root-uid.h" +#endif + +#if HAVE_LIBGEN_H +# include +#endif + +#include +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#if defined EACCES && !defined EACCESS +# define EACCESS EACCES +#endif + +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + + +#ifdef _LIBC + +# define access __access +# define getuid __getuid +# define getgid __getgid +# define geteuid __geteuid +# define getegid __getegid +# define group_member __group_member +# define euidaccess __euidaccess +# undef stat +# define stat stat64 + +#endif + +/* Return 0 if the user has permission of type MODE on FILE; + otherwise, return -1 and set 'errno'. + Like access, except that it uses the effective user and group + id's instead of the real ones, and it does not always check for read-only + file system, text busy, etc. */ + +int +euidaccess (const char *file, int mode) +{ +#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */ + return faccessat (AT_FDCWD, file, mode, AT_EACCESS); +#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */ + return access (file, mode | EFF_ONLY_OK); +#elif defined ACC_SELF /* AIX */ + return accessx (file, mode, ACC_SELF); +#elif HAVE_EACCESS /* FreeBSD */ + return eaccess (file, mode); +#elif defined _WIN32 && ! defined __CYGWIN__ /* mingw */ + return _access (file, mode); +#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, BeOS */ + + uid_t uid = getuid (); + gid_t gid = getgid (); + uid_t euid = geteuid (); + gid_t egid = getegid (); + struct stat stats; + +# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS + + /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to + return the correct result even if this would make it + nonreentrant. Define this only if your entire application is + safe even if the uid or gid might temporarily change. If your + application uses signal handlers or threads it is probably not + safe. */ + + if (mode == F_OK) + { + int result = stat (file, &stats); + return result != 0 && errno == EOVERFLOW ? 0 : result; + } + else + { + int result; + int saved_errno; + + if (uid != euid) + setreuid (euid, uid); + if (gid != egid) + setregid (egid, gid); + + result = access (file, mode); + saved_errno = errno; + + /* Restore them. */ + if (uid != euid) + setreuid (uid, euid); + if (gid != egid) + setregid (gid, egid); + + errno = saved_errno; + return result; + } + +# else + + /* The following code assumes the traditional Unix model, and is not + correct on systems that have ACLs or the like. However, it's + better than nothing, and it is reentrant. */ + + unsigned int granted; + if (uid == euid && gid == egid) + /* If we are not set-uid or set-gid, access does the same. */ + return access (file, mode); + + if (stat (file, &stats) == -1) + return mode == F_OK && errno == EOVERFLOW ? 0 : -1; + + /* The super-user can read and write any file, and execute any file + that anyone can execute. */ + if (euid == ROOT_UID + && ((mode & X_OK) == 0 + || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) + return 0; + + /* Convert the mode to traditional form, clearing any bogus bits. */ + if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0) + mode &= 7; + else + mode = ((mode & R_OK ? 4 : 0) + + (mode & W_OK ? 2 : 0) + + (mode & X_OK ? 1 : 0)); + + if (mode == 0) + return 0; /* The file exists. */ + + /* Convert the file's permission bits to traditional form. */ + if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6) + && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3) + && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0)) + granted = stats.st_mode; + else + granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0) + + (stats.st_mode & S_IWUSR ? 2 << 6 : 0) + + (stats.st_mode & S_IXUSR ? 1 << 6 : 0) + + (stats.st_mode & S_IRGRP ? 4 << 3 : 0) + + (stats.st_mode & S_IWGRP ? 2 << 3 : 0) + + (stats.st_mode & S_IXGRP ? 1 << 3 : 0) + + (stats.st_mode & S_IROTH ? 4 << 0 : 0) + + (stats.st_mode & S_IWOTH ? 2 << 0 : 0) + + (stats.st_mode & S_IXOTH ? 1 << 0 : 0)); + + if (euid == stats.st_uid) + granted >>= 6; + else if (egid == stats.st_gid || group_member (stats.st_gid)) + granted >>= 3; + + if ((mode & ~granted) == 0) + return 0; + __set_errno (EACCESS); + return -1; + +# endif +#endif +} +#undef euidaccess +#ifdef weak_alias +weak_alias (__euidaccess, euidaccess) +#endif + +#ifdef TEST +# include +# include +# include + +int +main (int argc, char **argv) +{ + char *file; + int mode; + int err; + + if (argc < 3) + abort (); + file = argv[1]; + mode = atoi (argv[2]); + + err = euidaccess (file, mode); + printf ("%d\n", err); + if (err != 0) + error (0, errno, "%s", file); + exit (0); +} +#endif diff --git a/cross/lib/execinfo.c b/cross/lib/execinfo.c new file mode 100644 index 00000000000..2048d00f5fb --- /dev/null +++ b/cross/lib/execinfo.c @@ -0,0 +1,21 @@ +/* Information about executables. + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define _GL_EXECINFO_INLINE _GL_EXTERN_INLINE +#include "execinfo.h" diff --git a/cross/lib/execinfo.in.h b/cross/lib/execinfo.in.h new file mode 100644 index 00000000000..ff9293b6327 --- /dev/null +++ b/cross/lib/execinfo.in.h @@ -0,0 +1,57 @@ +/* Information about executables. + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This program 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 program is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_EXECINFO_H +#define _GL_EXECINFO_H + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_EXECINFO_INLINE +# define _GL_EXECINFO_INLINE _GL_INLINE +#endif + +_GL_EXECINFO_INLINE int +backtrace (void **buffer, int size) +{ + (void) buffer; + (void) size; + return 0; +} + +_GL_EXECINFO_INLINE char ** +backtrace_symbols (void *const *buffer, int size) +{ + (void) buffer; + (void) size; + return 0; +} + +_GL_EXECINFO_INLINE void +backtrace_symbols_fd (void *const *buffer, int size, int fd) +{ + (void) buffer; + (void) size; + (void) fd; +} + +_GL_INLINE_HEADER_END + +#endif diff --git a/cross/lib/explicit_bzero.c b/cross/lib/explicit_bzero.c new file mode 100644 index 00000000000..c33cab9e6d5 --- /dev/null +++ b/cross/lib/explicit_bzero.c @@ -0,0 +1,74 @@ +/* Erasure of sensitive data, generic implementation. + Copyright (C) 2016-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +/* An assembler implementation of explicit_bzero can be created as an + assembler alias of an optimized bzero implementation. + Architecture-specific implementations also need to define + __explicit_bzero_chk. */ + +#if !_LIBC +# include +#endif + +/* memset_s need this define */ +#if HAVE_MEMSET_S +# define __STDC_WANT_LIB_EXT1__ 1 +#endif + +#include + +#if defined _WIN32 && !defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#if _LIBC +/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero + redirects to that. */ +# undef explicit_bzero +#endif + +/* Set LEN bytes of S to 0. The compiler will not delete a call to + this function, even if S is dead after the call. */ +void +explicit_bzero (void *s, size_t len) +{ +#if defined _WIN32 && !defined __CYGWIN__ + (void) SecureZeroMemory (s, len); +#elif HAVE_EXPLICIT_MEMSET + explicit_memset (s, '\0', len); +#elif HAVE_MEMSET_S + (void) memset_s (s, len, '\0', len); +#elif defined __GNUC__ && !defined __clang__ + memset (s, '\0', len); + /* Compiler barrier. */ + asm volatile ("" ::: "memory"); +#elif defined __clang__ + memset (s, '\0', len); + /* Compiler barrier. */ + /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the + whole thing is dead and eliminates it. Use 'g' to work around this + problem. See . */ + __asm__ volatile ("" : : "g"(s) : "memory"); +#else + /* Invoke memset through a volatile function pointer. This defeats compiler + optimizations. */ + void * (* const volatile volatile_memset) (void *, int, size_t) = memset; + (void) volatile_memset (s, '\0', len); +#endif +} diff --git a/cross/lib/faccessat.c b/cross/lib/faccessat.c new file mode 100644 index 00000000000..ac8977cfd65 --- /dev/null +++ b/cross/lib/faccessat.c @@ -0,0 +1,94 @@ +/* Check the access rights of a file relative to an open directory. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Eric Blake */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_faccessat doesn't recurse to + rpl_faccessat. */ +#define _GL_INCLUDING_UNISTD_H +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include +#undef _GL_INCLUDING_UNISTD_H + +#if HAVE_FACCESSAT +static int +orig_faccessat (int fd, char const *name, int mode, int flag) +{ + return faccessat (fd, name, mode, flag); +} +#endif + +/* Write "unistd.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +#include "unistd.h" + +#ifndef HAVE_ACCESS +/* Mingw lacks access, but it also lacks real vs. effective ids, so + the gnulib euidaccess module is good enough. */ +# undef access +# define access euidaccess +#endif + +#if HAVE_FACCESSAT + +int +rpl_faccessat (int fd, char const *file, int mode, int flag) +{ + int result = orig_faccessat (fd, file, mode, flag); + + if (result == 0 && file[strlen (file) - 1] == '/') + { + struct stat st; + result = fstatat (fd, file, &st, 0); + if (result == 0 && !S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } + + return result; +} + +#else /* !HAVE_FACCESSAT */ + +/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory + open on descriptor FD. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, then + (access|euidaccess)/restore_cwd. If either the save_cwd or the + restore_cwd fails, then give a diagnostic and exit nonzero. + Note that this implementation only supports AT_EACCESS, although some + native versions also support AT_SYMLINK_NOFOLLOW. */ + +# define AT_FUNC_NAME faccessat +# define AT_FUNC_F1 euidaccess +# define AT_FUNC_F2 access +# define AT_FUNC_USE_F1_COND AT_EACCESS +# define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag +# define AT_FUNC_POST_FILE_ARGS , mode +# include "at-func.c" + +#endif diff --git a/cross/lib/fchmodat.c b/cross/lib/fchmodat.c new file mode 100644 index 00000000000..a7b70a2af2c --- /dev/null +++ b/cross/lib/fchmodat.c @@ -0,0 +1,142 @@ +/* Change the protections of file relative to an open directory. + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Jim Meyering and Paul Eggert */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fchmodat doesn't recurse to + rpl_fchmodat. */ +#define __need_system_sys_stat_h +#include + +/* Specification. */ +#include +#undef __need_system_sys_stat_h + +#if HAVE_FCHMODAT +static int +orig_fchmodat (int dir, char const *file, mode_t mode, int flags) +{ + return fchmodat (dir, file, mode, flags); +} +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __osf__ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +# include "sys/stat.h" +#else +# include +#endif + +#include + +/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory + open on descriptor FD. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, + then (chmod|lchmod)/restore_cwd. If either the save_cwd or the + restore_cwd fails, then give a diagnostic and exit nonzero. + Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW + on a system without lchmod support causes this function to fail. */ + +#if HAVE_FCHMODAT +int +fchmodat (int dir, char const *file, mode_t mode, int flags) +{ +# if HAVE_NEARLY_WORKING_FCHMODAT + /* Correct the trailing slash handling. */ + size_t len = strlen (file); + if (len && file[len - 1] == '/') + { + struct stat st; + if (fstatat (dir, file, &st, flags & AT_SYMLINK_NOFOLLOW) < 0) + return -1; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } +# endif + +# if NEED_FCHMODAT_NONSYMLINK_FIX + if (flags == AT_SYMLINK_NOFOLLOW) + { +# if HAVE_READLINKAT + char readlink_buf[1]; + +# ifdef O_PATH + /* Open a file descriptor with O_NOFOLLOW, to make sure we don't + follow symbolic links, if /proc is mounted. O_PATH is used to + avoid a failure if the file is not readable. + Cf. */ + int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) + return fd; + + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) + { + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; + } + else + err = errno == ENOENT ? -1 : errno; + + close (fd); + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; +# endif + + /* O_PATH + /proc is not supported. */ + + if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf)) + { + errno = EOPNOTSUPP; + return -1; + } +# endif + + /* Fall back on orig_fchmodat with no flags, despite a possible race. */ + flags = 0; + } +# endif + + return orig_fchmodat (dir, file, mode, flags); +} +#else +# define AT_FUNC_NAME fchmodat +# define AT_FUNC_F1 lchmod +# define AT_FUNC_F2 chmod +# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW +# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag +# define AT_FUNC_POST_FILE_ARGS , mode +# include "at-func.c" +#endif diff --git a/cross/lib/fcntl.c b/cross/lib/fcntl.c new file mode 100644 index 00000000000..e220800845b --- /dev/null +++ b/cross/lib/fcntl.c @@ -0,0 +1,629 @@ +/* Provide file descriptor control. + + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Eric Blake . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#ifdef __KLIBC__ +# define INCL_DOS +# include +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include +# endif + +/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ +# define OPEN_MAX_MAX 0x10000 + +/* Duplicate OLDFD into the first available slot of at least NEWFD, + which must be positive, with FLAGS determining whether the duplicate + will be inheritable. */ +static int +dupfd (int oldfd, int newfd, int flags) +{ + /* Mingw has no way to create an arbitrary fd. Iterate until all + file descriptors less than newfd are filled up. */ + HANDLE curr_process = GetCurrentProcess (); + HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); + unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; + unsigned int fds_to_close_bound = 0; + int result; + BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; + int mode; + + if (newfd < 0 || getdtablesize () <= newfd) + { + errno = EINVAL; + return -1; + } + if (old_handle == INVALID_HANDLE_VALUE + || (mode = _setmode (oldfd, O_BINARY)) == -1) + { + /* oldfd is not open, or is an unassigned standard file + descriptor. */ + errno = EBADF; + return -1; + } + _setmode (oldfd, mode); + flags |= mode; + + for (;;) + { + HANDLE new_handle; + int duplicated_fd; + unsigned int index; + + if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ + old_handle, /* SourceHandle */ + curr_process, /* TargetProcessHandle */ + (PHANDLE) &new_handle, /* TargetHandle */ + (DWORD) 0, /* DesiredAccess */ + inherit, /* InheritHandle */ + DUPLICATE_SAME_ACCESS)) /* Options */ + { + switch (GetLastError ()) + { + case ERROR_TOO_MANY_OPEN_FILES: + errno = EMFILE; + break; + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_TARGET_HANDLE: + case ERROR_DIRECT_ACCESS_HANDLE: + errno = EBADF; + break; + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_ACCESS: + errno = EINVAL; + break; + default: + errno = EACCES; + break; + } + result = -1; + break; + } + duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags); + if (duplicated_fd < 0) + { + CloseHandle (new_handle); + result = -1; + break; + } + if (newfd <= duplicated_fd) + { + result = duplicated_fd; + break; + } + + /* Set the bit duplicated_fd in fds_to_close[]. */ + index = (unsigned int) duplicated_fd / CHAR_BIT; + if (fds_to_close_bound <= index) + { + if (sizeof fds_to_close <= index) + /* Need to increase OPEN_MAX_MAX. */ + abort (); + memset (fds_to_close + fds_to_close_bound, '\0', + index + 1 - fds_to_close_bound); + fds_to_close_bound = index + 1; + } + fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT); + } + + /* Close the previous fds that turned out to be too small. */ + { + int saved_errno = errno; + unsigned int duplicated_fd; + + for (duplicated_fd = 0; + duplicated_fd < fds_to_close_bound * CHAR_BIT; + duplicated_fd++) + if ((fds_to_close[duplicated_fd / CHAR_BIT] + >> (duplicated_fd % CHAR_BIT)) + & 1) + close (duplicated_fd); + + errno = saved_errno; + } + +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (oldfd, result); +# endif + return result; +} +#endif /* W32 */ + +/* Forward declarations, because we '#undef fcntl' in the middle of this + compilation unit. */ +/* Our implementation of fcntl (fd, F_DUPFD, target). */ +static int rpl_fcntl_DUPFD (int fd, int target); +/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */ +static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target); +#ifdef __KLIBC__ +/* Adds support for fcntl on directories. */ +static int klibc_fcntl (int fd, int action, /* arg */...); +#endif + + +/* Perform the specified ACTION on the file descriptor FD, possibly + using the argument ARG further described below. This replacement + handles the following actions, and forwards all others on to the + native fcntl. An unrecognized ACTION returns -1 with errno set to + EINVAL. + + F_DUPFD - duplicate FD, with int ARG being the minimum target fd. + If successful, return the duplicate, which will be inheritable; + otherwise return -1 and set errno. + + F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum + target fd. If successful, return the duplicate, which will not be + inheritable; otherwise return -1 and set errno. + + F_GETFD - ARG need not be present. If successful, return a + non-negative value containing the descriptor flags of FD (only + FD_CLOEXEC is portable, but other flags may be present); otherwise + return -1 and set errno. */ + +int +fcntl (int fd, int action, /* arg */...) +#undef fcntl +#ifdef __KLIBC__ +# define fcntl klibc_fcntl +#endif +{ + va_list arg; + int result = -1; + va_start (arg, action); + switch (action) + { + case F_DUPFD: + { + int target = va_arg (arg, int); + result = rpl_fcntl_DUPFD (fd, target); + break; + } + + case F_DUPFD_CLOEXEC: + { + int target = va_arg (arg, int); + result = rpl_fcntl_DUPFD_CLOEXEC (fd, target); + break; + } + +#if !HAVE_FCNTL + case F_GETFD: + { +# if defined _WIN32 && ! defined __CYGWIN__ + HANDLE handle = (HANDLE) _get_osfhandle (fd); + DWORD flags; + if (handle == INVALID_HANDLE_VALUE + || GetHandleInformation (handle, &flags) == 0) + errno = EBADF; + else + result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; +# else /* !W32 */ + /* Use dup2 to reject invalid file descriptors. No way to + access this information, so punt. */ + if (0 <= dup2 (fd, fd)) + result = 0; +# endif /* !W32 */ + break; + } /* F_GETFD */ +#endif /* !HAVE_FCNTL */ + + /* Implementing F_SETFD on mingw is not trivial - there is no + API for changing the O_NOINHERIT bit on an fd, and merely + changing the HANDLE_FLAG_INHERIT bit on the underlying handle + can lead to odd state. It may be possible by duplicating the + handle, using _open_osfhandle with the right flags, then + using dup2 to move the duplicate onto the original, but that + is not supported for now. */ + + default: + { +#if HAVE_FCNTL + switch (action) + { + #ifdef F_BARRIERFSYNC /* macOS */ + case F_BARRIERFSYNC: + #endif + #ifdef F_CHKCLEAN /* macOS */ + case F_CHKCLEAN: + #endif + #ifdef F_CLOSEM /* NetBSD, HP-UX */ + case F_CLOSEM: + #endif + #ifdef F_FLUSH_DATA /* macOS */ + case F_FLUSH_DATA: + #endif + #ifdef F_FREEZE_FS /* macOS */ + case F_FREEZE_FS: + #endif + #ifdef F_FULLFSYNC /* macOS */ + case F_FULLFSYNC: + #endif + #ifdef F_GETCONFINED /* macOS */ + case F_GETCONFINED: + #endif + #ifdef F_GETDEFAULTPROTLEVEL /* macOS */ + case F_GETDEFAULTPROTLEVEL: + #endif + #ifdef F_GETFD /* POSIX */ + case F_GETFD: + #endif + #ifdef F_GETFL /* POSIX */ + case F_GETFL: + #endif + #ifdef F_GETLEASE /* Linux */ + case F_GETLEASE: + #endif + #ifdef F_GETNOSIGPIPE /* macOS */ + case F_GETNOSIGPIPE: + #endif + #ifdef F_GETOWN /* POSIX */ + case F_GETOWN: + #endif + #ifdef F_GETPIPE_SZ /* Linux */ + case F_GETPIPE_SZ: + #endif + #ifdef F_GETPROTECTIONCLASS /* macOS */ + case F_GETPROTECTIONCLASS: + #endif + #ifdef F_GETPROTECTIONLEVEL /* macOS */ + case F_GETPROTECTIONLEVEL: + #endif + #ifdef F_GET_SEALS /* Linux */ + case F_GET_SEALS: + #endif + #ifdef F_GETSIG /* Linux */ + case F_GETSIG: + #endif + #ifdef F_MAXFD /* NetBSD */ + case F_MAXFD: + #endif + #ifdef F_RECYCLE /* macOS */ + case F_RECYCLE: + #endif + #ifdef F_SETFIFOENH /* HP-UX */ + case F_SETFIFOENH: + #endif + #ifdef F_THAW_FS /* macOS */ + case F_THAW_FS: + #endif + /* These actions take no argument. */ + result = fcntl (fd, action); + break; + + #ifdef F_ADD_SEALS /* Linux */ + case F_ADD_SEALS: + #endif + #ifdef F_BADFD /* Solaris */ + case F_BADFD: + #endif + #ifdef F_CHECK_OPENEVT /* macOS */ + case F_CHECK_OPENEVT: + #endif + #ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */ + case F_DUP2FD: + #endif + #ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */ + case F_DUP2FD_CLOEXEC: + #endif + #ifdef F_DUP2FD_CLOFORK /* Solaris */ + case F_DUP2FD_CLOFORK: + #endif + #ifdef F_DUPFD /* POSIX */ + case F_DUPFD: + #endif + #ifdef F_DUPFD_CLOEXEC /* POSIX */ + case F_DUPFD_CLOEXEC: + #endif + #ifdef F_DUPFD_CLOFORK /* Solaris */ + case F_DUPFD_CLOFORK: + #endif + #ifdef F_GETXFL /* Solaris */ + case F_GETXFL: + #endif + #ifdef F_GLOBAL_NOCACHE /* macOS */ + case F_GLOBAL_NOCACHE: + #endif + #ifdef F_MAKECOMPRESSED /* macOS */ + case F_MAKECOMPRESSED: + #endif + #ifdef F_MOVEDATAEXTENTS /* macOS */ + case F_MOVEDATAEXTENTS: + #endif + #ifdef F_NOCACHE /* macOS */ + case F_NOCACHE: + #endif + #ifdef F_NODIRECT /* macOS */ + case F_NODIRECT: + #endif + #ifdef F_NOTIFY /* Linux */ + case F_NOTIFY: + #endif + #ifdef F_OPLKACK /* IRIX */ + case F_OPLKACK: + #endif + #ifdef F_OPLKREG /* IRIX */ + case F_OPLKREG: + #endif + #ifdef F_RDAHEAD /* macOS */ + case F_RDAHEAD: + #endif + #ifdef F_SETBACKINGSTORE /* macOS */ + case F_SETBACKINGSTORE: + #endif + #ifdef F_SETCONFINED /* macOS */ + case F_SETCONFINED: + #endif + #ifdef F_SETFD /* POSIX */ + case F_SETFD: + #endif + #ifdef F_SETFL /* POSIX */ + case F_SETFL: + #endif + #ifdef F_SETLEASE /* Linux */ + case F_SETLEASE: + #endif + #ifdef F_SETNOSIGPIPE /* macOS */ + case F_SETNOSIGPIPE: + #endif + #ifdef F_SETOWN /* POSIX */ + case F_SETOWN: + #endif + #ifdef F_SETPIPE_SZ /* Linux */ + case F_SETPIPE_SZ: + #endif + #ifdef F_SETPROTECTIONCLASS /* macOS */ + case F_SETPROTECTIONCLASS: + #endif + #ifdef F_SETSIG /* Linux */ + case F_SETSIG: + #endif + #ifdef F_SINGLE_WRITER /* macOS */ + case F_SINGLE_WRITER: + #endif + /* These actions take an 'int' argument. */ + { + int x = va_arg (arg, int); + result = fcntl (fd, action, x); + } + break; + + default: + /* Other actions take a pointer argument. */ + { + void *p = va_arg (arg, void *); + result = fcntl (fd, action, p); + } + break; + } +#else + errno = EINVAL; +#endif + break; + } + } + va_end (arg); + return result; +} + +static int +rpl_fcntl_DUPFD (int fd, int target) +{ + int result; +#if !HAVE_FCNTL + result = dupfd (fd, target, 0); +#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR + /* Detect invalid target; needed for cygwin 1.5.x. */ + if (target < 0 || getdtablesize () <= target) + { + result = -1; + errno = EINVAL; + } + else + { + /* Haiku alpha 2 loses fd flags on original. */ + int flags = fcntl (fd, F_GETFD); + if (flags < 0) + result = -1; + else + { + result = fcntl (fd, F_DUPFD, target); + if (0 <= result && fcntl (fd, F_SETFD, flags) == -1) + { + int saved_errno = errno; + close (result); + result = -1; + errno = saved_errno; + } +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + } +#else + result = fcntl (fd, F_DUPFD, target); +#endif + return result; +} + +static int +rpl_fcntl_DUPFD_CLOEXEC (int fd, int target) +{ + int result; +#if !HAVE_FCNTL + result = dupfd (fd, target, O_CLOEXEC); +#else /* HAVE_FCNTL */ +# if defined __NetBSD__ || defined __HAIKU__ + /* On NetBSD 9.0, the system fcntl (fd, F_DUPFD_CLOEXEC, target) + has only the same effect as fcntl (fd, F_DUPFD, target). */ + /* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets + the FD_CLOEXEC flag on fd, not on target. Therefore avoid the + system fcntl in this case. */ +# define have_dupfd_cloexec -1 +# else + /* Try the system call first, if the headers claim it exists + (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we + may be running with a glibc that has the macro but with an + older kernel that does not support it. Cache the + information on whether the system call really works, but + avoid caching failure if the corresponding F_DUPFD fails + for any reason. 0 = unknown, 1 = yes, -1 = no. */ + static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0; + if (0 <= have_dupfd_cloexec) + { + result = fcntl (fd, F_DUPFD_CLOEXEC, target); + if (0 <= result || errno != EINVAL) + { + have_dupfd_cloexec = 1; +# if REPLACE_FCHDIR + if (0 <= result) + result = _gl_register_dup (fd, result); +# endif + } + else + { + result = rpl_fcntl_DUPFD (fd, target); + if (result >= 0) + have_dupfd_cloexec = -1; + } + } + else +# endif + result = rpl_fcntl_DUPFD (fd, target); + if (0 <= result && have_dupfd_cloexec == -1) + { + int flags = fcntl (result, F_GETFD); + if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1) + { + int saved_errno = errno; + close (result); + errno = saved_errno; + result = -1; + } + } +#endif /* HAVE_FCNTL */ + return result; +} + +#undef fcntl + +#ifdef __KLIBC__ + +static int +klibc_fcntl (int fd, int action, /* arg */...) +{ + va_list arg_ptr; + int arg; + struct stat sbuf; + int result; + + va_start (arg_ptr, action); + arg = va_arg (arg_ptr, int); + result = fcntl (fd, action, arg); + /* EPERM for F_DUPFD, ENOTSUP for others */ + if (result == -1 && (errno == EPERM || errno == ENOTSUP) + && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) + { + ULONG ulMode; + + switch (action) + { + case F_DUPFD: + /* Find available fd */ + while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) + arg++; + + result = dup2 (fd, arg); + break; + + /* Using underlying APIs is right ? */ + case F_GETFD: + if (DosQueryFHState (fd, &ulMode)) + break; + + result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; + break; + + case F_SETFD: + if (arg & ~FD_CLOEXEC) + break; + + if (DosQueryFHState (fd, &ulMode)) + break; + + if (arg & FD_CLOEXEC) + ulMode |= OPEN_FLAGS_NOINHERIT; + else + ulMode &= ~OPEN_FLAGS_NOINHERIT; + + /* Filter supported flags. */ + ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR + | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); + + if (DosSetFHState (fd, ulMode)) + break; + + result = 0; + break; + + case F_GETFL: + result = 0; + break; + + case F_SETFL: + if (arg != 0) + break; + + result = 0; + break; + + default: + errno = EINVAL; + break; + } + } + + va_end (arg_ptr); + + return result; +} + +#endif diff --git a/cross/lib/fcntl.in.h b/cross/lib/fcntl.in.h new file mode 100644 index 00000000000..e034eaf9f5a --- /dev/null +++ b/cross/lib/fcntl.in.h @@ -0,0 +1,445 @@ +/* Like , but with non-working flags defined to 0. + + Copyright (C) 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Paul Eggert */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_fcntl_h +/* Special invocation convention. */ + +/* Needed before . + May also define off_t to a 64-bit type on native Windows. */ +#include +/* On some systems other than glibc, is a prerequisite of + . On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, includes inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include +#endif +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +/* Native Windows platforms declare open(), creat() in . */ +#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) +# include +#endif + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_FCNTL_H + +/* Needed before . + May also define off_t to a 64-bit type on native Windows. */ +#include +/* On some systems other than glibc, is a prerequisite of + . On glibc systems, we would like to avoid namespace pollution. + But on glibc systems, includes inside an + extern "C" { ... } block, which leads to errors in C++ mode with the + overridden from gnulib. These errors are known to be gone + with g++ version >= 4.3. */ +#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) +# include +#endif +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ + +/* Native Windows platforms declare open(), creat() in . */ +#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) +# include +#endif + +#ifndef _@GUARD_PREFIX@_FCNTL_H +#define _@GUARD_PREFIX@_FCNTL_H + +#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */ +# include +#endif + + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + +#if @GNULIB_CREAT@ +# if @REPLACE_CREAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef creat +# define creat rpl_creat +# endif +_GL_FUNCDECL_RPL (creat, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (creat, int, (const char *filename, mode_t mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef creat +# define creat _creat +# endif +_GL_CXXALIAS_MDA (creat, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (creat); +#elif defined GNULIB_POSIXCHECK +# undef creat +/* Assume creat is always declared. */ +_GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - " + "use gnulib module creat for portability"); +#elif @GNULIB_MDA_CREAT@ +/* On native Windows, map 'creat' to '_creat', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::creat always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef creat +# define creat _creat +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (creat, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (creat); +#endif + +#if @GNULIB_FCNTL@ +# if @REPLACE_FCNTL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fcntl +# define fcntl rpl_fcntl +# endif +_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...)); +_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...)); +# if !GNULIB_defined_rpl_fcntl +# define GNULIB_defined_rpl_fcntl 1 +# endif +# else +# if !@HAVE_FCNTL@ +_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...)); +# if !GNULIB_defined_fcntl +# define GNULIB_defined_fcntl 1 +# endif +# endif +_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...)); +# endif +_GL_CXXALIASWARN (fcntl); +#elif defined GNULIB_POSIXCHECK +# undef fcntl +# if HAVE_RAW_DECL_FCNTL +_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - " + "use gnulib module fcntl for portability"); +# endif +#endif + +#if @GNULIB_OPEN@ +# if @REPLACE_OPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef open +# define open rpl_open +# endif +_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef open +# define open _open +# endif +_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); +# else +_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); +# endif +/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a + default argument. _GL_CXXALIASWARN does not work in this case. */ +# if !defined __hpux +_GL_CXXALIASWARN (open); +# endif +#elif defined GNULIB_POSIXCHECK +# undef open +/* Assume open is always declared. */ +_GL_WARN_ON_USE (open, "open is not always POSIX compliant - " + "use gnulib module open for portability"); +#elif @GNULIB_MDA_OPEN@ +/* On native Windows, map 'open' to '_open', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::open always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef open +# define open _open +# endif +_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); +# else +_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); +# endif +# if !defined __hpux +_GL_CXXALIASWARN (open); +# endif +#endif + +#if @GNULIB_OPENAT@ +# if @REPLACE_OPENAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef openat +# define openat rpl_openat +# endif +_GL_FUNCDECL_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# else +# if !@HAVE_OPENAT@ +_GL_FUNCDECL_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (openat, int, + (int fd, char const *file, int flags, /* mode_t mode */ ...)); +# endif +_GL_CXXALIASWARN (openat); +#elif defined GNULIB_POSIXCHECK +# undef openat +# if HAVE_RAW_DECL_OPENAT +_GL_WARN_ON_USE (openat, "openat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +/* Fix up the FD_* macros, only known to be missing on mingw. */ + +#ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +#endif + +/* Fix up the supported F_* macros. Intentionally leave other F_* + macros undefined. Only known to be missing on mingw. */ + +#ifndef F_DUPFD_CLOEXEC +# define F_DUPFD_CLOEXEC 0x40000000 +/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */ +# define GNULIB_defined_F_DUPFD_CLOEXEC 1 +#else +# define GNULIB_defined_F_DUPFD_CLOEXEC 0 +#endif + +#ifndef F_DUPFD +# define F_DUPFD 1 +#endif + +#ifndef F_GETFD +# define F_GETFD 2 +#endif + +/* Fix up the O_* macros. */ + +/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT + to values outside 'int' range, so omit these misdefinitions. + But avoid namespace pollution on non-AIX systems. */ +#ifdef _AIX +# include +# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX) +# undef O_CLOEXEC +# endif +# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +# undef O_NOFOLLOW +# endif +# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX) +# undef O_TTY_INIT +# endif +#endif + +#if !defined O_DIRECT && defined O_DIRECTIO +/* Tru64 spells it 'O_DIRECTIO'. */ +# define O_DIRECT O_DIRECTIO +#endif + +#if !defined O_CLOEXEC && defined O_NOINHERIT +/* Mingw spells it 'O_NOINHERIT'. */ +# define O_CLOEXEC O_NOINHERIT +#endif + +#ifndef O_CLOEXEC +# define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */ +# define GNULIB_defined_O_CLOEXEC 1 +#else +# define GNULIB_defined_O_CLOEXEC 0 +#endif + +#ifndef O_DIRECT +# define O_DIRECT 0 +#endif + +#ifndef O_DIRECTORY +# define O_DIRECTORY 0 +#endif + +#ifndef O_DSYNC +# define O_DSYNC 0 +#endif + +#ifndef O_EXEC +# define O_EXEC O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_IGNORE_CTTY +# define O_IGNORE_CTTY 0 +#endif + +#ifndef O_NDELAY +# define O_NDELAY 0 +#endif + +#ifndef O_NOATIME +# define O_NOATIME 0 +#endif + +#ifndef O_NONBLOCK +# define O_NONBLOCK O_NDELAY +#endif + +/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero + value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY + or to 0 as fallback. */ +#if @GNULIB_NONBLOCKING@ +# if O_NONBLOCK +# define GNULIB_defined_O_NONBLOCK 0 +# else +# define GNULIB_defined_O_NONBLOCK 1 +# undef O_NONBLOCK +# define O_NONBLOCK 0x40000000 +# endif +#endif + +#ifndef O_NOCTTY +# define O_NOCTTY 0 +#endif + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#ifndef O_NOLINK +# define O_NOLINK 0 +#endif + +#ifndef O_NOLINKS +# define O_NOLINKS 0 +#endif + +#ifndef O_NOTRANS +# define O_NOTRANS 0 +#endif + +#ifndef O_RSYNC +# define O_RSYNC 0 +#endif + +#ifndef O_SEARCH +# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */ +#endif + +#ifndef O_SYNC +# define O_SYNC 0 +#endif + +#ifndef O_TTY_INIT +# define O_TTY_INIT 0 +#endif + +#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +# undef O_ACCMODE +# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) +#endif + +/* For systems that distinguish between text and binary I/O. + O_BINARY is usually declared in fcntl.h */ +#if !defined O_BINARY && defined _O_BINARY + /* For MSC-compatible compilers. */ +# define O_BINARY _O_BINARY +# define O_TEXT _O_TEXT +#endif + +#if defined __BEOS__ || defined __HAIKU__ + /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */ +# undef O_BINARY +# undef O_TEXT +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +# define O_TEXT 0 +#endif + +/* Fix up the AT_* macros. */ + +/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its + value exceeds INT_MAX, so its use as an int doesn't conform to the + C standard, and GCC and Sun C complain in some cases. If the bug + is present, undef AT_FDCWD here, so it can be redefined below. */ +#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 +# undef AT_FDCWD +#endif + +/* Use the same bit pattern as Solaris 9, but with the proper + signedness. The bit pattern is important, in case this actually is + Solaris with the above workaround. */ +#ifndef AT_FDCWD +# define AT_FDCWD (-3041965) +#endif + +/* Use the same values as Solaris 9. This shouldn't matter, but + there's no real reason to differ. */ +#ifndef AT_SYMLINK_NOFOLLOW +# define AT_SYMLINK_NOFOLLOW 4096 +#endif + +#ifndef AT_REMOVEDIR +# define AT_REMOVEDIR 1 +#endif + +/* Solaris 9 lacks these two, so just pick unique values. */ +#ifndef AT_SYMLINK_FOLLOW +# define AT_SYMLINK_FOLLOW 2 +#endif + +#ifndef AT_EACCESS +# define AT_EACCESS 4 +#endif + +/* Ignore this flag if not supported. */ +#ifndef AT_NO_AUTOMOUNT +# define AT_NO_AUTOMOUNT 0 +#endif + +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif /* _@GUARD_PREFIX@_FCNTL_H */ +#endif diff --git a/cross/lib/fdopendir.c b/cross/lib/fdopendir.c new file mode 100644 index 00000000000..aa841e3e819 --- /dev/null +++ b/cross/lib/fdopendir.c @@ -0,0 +1,249 @@ +/* provide a replacement fdopendir function + Copyright (C) 2004-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Jim Meyering */ + +#include + +#include + +#include +#include + +#if !HAVE_FDOPENDIR + +# include "openat.h" +# include "openat-priv.h" +# include "save-cwd.h" + +# if GNULIB_DIRENT_SAFER +# include "dirent--.h" +# endif + +# ifndef REPLACE_FCHDIR +# define REPLACE_FCHDIR 0 +# endif + +static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *); +static DIR *fd_clone_opendir (int, struct saved_cwd const *); + +/* Replacement for POSIX fdopendir. + + First, try to simulate it via opendir ("/proc/self/fd/..."). Failing + that, simulate it by using fchdir metadata, or by doing + save_cwd/fchdir/opendir(".")/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + + If successful, the resulting stream is based on FD in + implementations where streams are based on file descriptors and in + applications where no other thread or signal handler allocates or + frees file descriptors. In other cases, consult dirfd on the result + to find out whether FD is still being used. + + Otherwise, this function works just like POSIX fdopendir. + + W A R N I N G: + + Unlike other fd-related functions, this one places constraints on FD. + If this function returns successfully, FD is under control of the + dirent.h system, and the caller should not close or modify the state of + FD other than by the dirent.h functions. */ +# ifdef __KLIBC__ +# include + +DIR * +fdopendir (int fd) +{ + char path[_MAX_PATH]; + DIR *dirp; + + /* Get a path from fd */ + if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) + return NULL; + + dirp = opendir (path); + if (!dirp) + return NULL; + + /* Unregister fd registered by opendir() */ + _gl_unregister_dirp_fd (dirfd (dirp)); + + /* Register our fd */ + if (_gl_register_dirp_fd (fd, dirp)) + { + int saved_errno = errno; + + closedir (dirp); + + errno = saved_errno; + + dirp = NULL; + } + + return dirp; +} +# else +DIR * +fdopendir (int fd) +{ + DIR *dir = fdopendir_with_dup (fd, -1, NULL); + + if (! REPLACE_FCHDIR && ! dir) + { + int saved_errno = errno; + if (EXPECTED_ERRNO (saved_errno)) + { + struct saved_cwd cwd; + if (save_cwd (&cwd) != 0) + openat_save_fail (errno); + dir = fdopendir_with_dup (fd, -1, &cwd); + saved_errno = errno; + free_cwd (&cwd); + errno = saved_errno; + } + } + + return dir; +} +# endif + +/* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known + to be a dup of FD which is less than FD - 1 and which will be + closed by the caller and not otherwise used by the caller. This + function makes sure that FD is closed and all file descriptors less + than FD are open, and then calls fd_clone_opendir on a dup of FD. + That way, barring race conditions, fd_clone_opendir returns a + stream whose file descriptor is FD. + + If REPLACE_FCHDIR or CWD is null, use opendir ("/proc/self/fd/...", + falling back on fchdir metadata. Otherwise, CWD is a saved version + of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ +static DIR * +fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd) +{ + int dupfd = dup (fd); + if (dupfd < 0 && errno == EMFILE) + dupfd = older_dupfd; + if (dupfd < 0) + return NULL; + else + { + DIR *dir; + int saved_errno; + if (dupfd < fd - 1 && dupfd != older_dupfd) + { + dir = fdopendir_with_dup (fd, dupfd, cwd); + saved_errno = errno; + } + else + { + close (fd); + dir = fd_clone_opendir (dupfd, cwd); + saved_errno = errno; + if (! dir) + { + int fd1 = dup (dupfd); + if (fd1 != fd) + openat_save_fail (fd1 < 0 ? errno : EBADF); + } + } + + if (dupfd != older_dupfd) + close (dupfd); + errno = saved_errno; + return dir; + } +} + +/* Like fdopendir, except the result controls a clone of FD. It is + the caller's responsibility both to close FD and (if the result is + not null) to closedir the result. */ +static DIR * +fd_clone_opendir (int fd, struct saved_cwd const *cwd) +{ + if (REPLACE_FCHDIR || ! cwd) + { + DIR *dir = NULL; + int saved_errno = EOPNOTSUPP; + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) + { + dir = opendir (proc_file); + saved_errno = errno; + if (proc_file != buf) + free (proc_file); + } +# if REPLACE_FCHDIR + if (! dir && EXPECTED_ERRNO (saved_errno)) + { + char const *name = _gl_directory_name (fd); + DIR *dp = name ? opendir (name) : NULL; + + /* The caller has done an elaborate dance to arrange for opendir to + consume just the right file descriptor. If dirfd returns -1, + though, we're on a system like mingw where opendir does not + consume a file descriptor. Consume it via 'dup' instead. */ + if (dp && dirfd (dp) < 0) + dup (fd); + + return dp; + } +# endif + errno = saved_errno; + return dir; + } + else + { + if (fchdir (fd) != 0) + return NULL; + else + { + DIR *dir = opendir ("."); + int saved_errno = errno; + if (restore_cwd (cwd) != 0) + openat_restore_fail (errno); + errno = saved_errno; + return dir; + } + } +} + +#else /* HAVE_FDOPENDIR */ + +# include +# include + +# undef fdopendir + +/* Like fdopendir, but work around GNU/Hurd bug by validating FD. */ + +DIR * +rpl_fdopendir (int fd) +{ + struct stat st; + if (fstat (fd, &st)) + return NULL; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return NULL; + } + return fdopendir (fd); +} + +#endif /* HAVE_FDOPENDIR */ diff --git a/cross/lib/file-has-acl.c b/cross/lib/file-has-acl.c new file mode 100644 index 00000000000..b31a2ea2523 --- /dev/null +++ b/cross/lib/file-has-acl.c @@ -0,0 +1,621 @@ +/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +/* Without this pragma, gcc 4.7.0 20120126 may suggest that the + file_has_acl function might be candidate for attribute 'const' */ +#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif + +#include + +#include "acl.h" + +#include "acl-internal.h" + +#if USE_ACL && GETXATTR_WITH_POSIX_ACLS +# include +# include +# include +# include +# ifndef XATTR_NAME_NFSV4_ACL +# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" +# endif + +enum { + /* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */ + ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001, + ACE4_IDENTIFIER_GROUP = 0x00000040 +}; + +/* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial. + -1 upon failure to determine it. Possibly change errno. Assume that + the ACL is valid, except avoid undefined behavior even if invalid. + + See . The NFSv4 acls are + defined in Internet RFC 7530 and as such, every NFSv4 server + supporting ACLs should support NFSv4 ACLs (they differ from from + POSIX draft ACLs). The ACLs can be obtained via the + nfsv4-acl-tools, e.g., the nfs4_getfacl command. Gnulib provides + only basic support of NFSv4 ACLs, i.e., recognize trivial vs + nontrivial ACLs. */ + +static int +acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) +{ + enum { BYTES_PER_NETWORK_UINT = 4}; + + /* Grab the number of aces in the acl. */ + nbytes -= BYTES_PER_NETWORK_UINT; + if (nbytes < 0) + return -1; + uint32_t num_aces = ntohl (*xattr++); + if (6 < num_aces) + return 1; + int ace_found = 0; + + for (int ace_n = 0; ace_n < num_aces; ace_n++) + { + /* Get the acl type and flag. Skip the mask; it's too risky to + test it and it does not seem to be needed. Get the wholen. */ + nbytes -= 4 * BYTES_PER_NETWORK_UINT; + if (nbytes < 0) + return -1; + uint32_t type = ntohl (xattr[0]); + uint32_t flag = ntohl (xattr[1]); + uint32_t wholen = ntohl (xattr[3]); + xattr += 4; + int whowords = (wholen / BYTES_PER_NETWORK_UINT + + (wholen % BYTES_PER_NETWORK_UINT != 0)); + int64_t wholen4 = whowords; + wholen4 *= BYTES_PER_NETWORK_UINT; + + /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or + ACE4_ACCESS_DENIED_ACE_TYPE. */ + if (ACE4_ACCESS_DENIED_ACE_TYPE < type) + return 1; + + /* RFC 7530 says FLAG should be 0, but be generous to NetApp and + also accept the group flag. */ + if (flag & ~ACE4_IDENTIFIER_GROUP) + return 1; + + /* Get the who string. Check NBYTES - WHOLEN4 before storing + into NBYTES, to avoid truncation on conversion. */ + if (nbytes - wholen4 < 0) + return -1; + nbytes -= wholen4; + + /* For a trivial ACL, max 6 (typically 3) ACEs, 3 allow, 3 deny. + Check that there is at most one ACE of each TYPE and WHO. */ + int who2 + = (wholen == 6 && memcmp (xattr, "OWNER@", 6) == 0 ? 0 + : wholen == 6 && memcmp (xattr, "GROUP@", 6) == 0 ? 2 + : wholen == 9 && memcmp (xattr, "EVERYONE@", 9) == 0 ? 4 + : -1); + if (who2 < 0) + return 1; + int ace_found_bit = 1 << (who2 | type); + if (ace_found & ace_found_bit) + return 1; + ace_found |= ace_found_bit; + + xattr += whowords; + } + + return 0; +} +#endif + +/* Return 1 if NAME has a nontrivial access control list, + 0 if ACLs are not supported, or if NAME has no or only a base ACL, + and -1 (setting errno) on error. Note callers can determine + if ACLs are not supported as errno is set in that case also. + SB must be set to the stat buffer of NAME, + obtained through stat() or lstat(). */ + +int +file_has_acl (char const *name, struct stat const *sb) +{ +#if USE_ACL + if (! S_ISLNK (sb->st_mode)) + { + +# if GETXATTR_WITH_POSIX_ACLS + + ssize_t ret; + int initial_errno = errno; + + ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0); + if (ret < 0 && errno == ENODATA) + ret = 0; + else if (ret > 0) + return 1; + + if (ret == 0 && S_ISDIR (sb->st_mode)) + { + ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0); + if (ret < 0 && errno == ENODATA) + ret = 0; + else if (ret > 0) + return 1; + } + + if (ret < 0) + { + /* Check for NFSv4 ACLs. The max length of a trivial + ACL is 6 words for owner, 6 for group, 7 for everyone, + all times 2 because there are both allow and deny ACEs. + There are 6 words for owner because of type, flag, mask, + wholen, "OWNER@"+pad and similarly for group; everyone is + another word to hold "EVERYONE@". */ + uint32_t xattr[2 * (6 + 6 + 7)]; + + ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, sizeof xattr); + if (ret < 0) + switch (errno) + { + case ENODATA: return 0; + case ERANGE : return 1; /* ACL must be nontrivial. */ + } + else + { + /* It looks like a trivial ACL, but investigate further. */ + ret = acl_nfs4_nontrivial (xattr, ret); + if (ret < 0) + { + errno = EINVAL; + return ret; + } + errno = initial_errno; + } + } + if (ret < 0) + return - acl_errno_valid (errno); + return ret; + +# elif HAVE_ACL_GET_FILE + + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + int ret; + + if (HAVE_ACL_EXTENDED_FILE) /* Linux */ + { + /* On Linux, acl_extended_file is an optimized function: It only + makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for + ACL_TYPE_DEFAULT. */ + ret = acl_extended_file (name); + } + else /* FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ + { +# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. There is no point in making + these two useless calls. The real ACL is retrieved through + acl_get_file (name, ACL_TYPE_EXTENDED). */ + acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (acl) + { + ret = acl_extended_nontrivial (acl); + acl_free (acl); + } + else + ret = -1; +# else /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ + acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (acl) + { + int saved_errno; + + ret = acl_access_nontrivial (acl); + saved_errno = errno; + acl_free (acl); + errno = saved_errno; +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always + returns NULL with errno not set. There is no point in + making this call. */ +# else /* FreeBSD, IRIX, Cygwin >= 2.5 */ + /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory + either both succeed or both fail; it depends on the + file system. Therefore there is no point in making the second + call if the first one already failed. */ + if (ret == 0 && S_ISDIR (sb->st_mode)) + { + acl = acl_get_file (name, ACL_TYPE_DEFAULT); + if (acl) + { +# ifdef __CYGWIN__ /* Cygwin >= 2.5 */ + ret = acl_access_nontrivial (acl); + saved_errno = errno; + acl_free (acl); + errno = saved_errno; +# else + ret = (0 < acl_entries (acl)); + acl_free (acl); +# endif + } + else + ret = -1; + } +# endif + } + else + ret = -1; +# endif + } + if (ret < 0) + return - acl_errno_valid (errno); + return ret; + +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ + +# if defined ACL_NO_TRIVIAL + + /* Solaris 10 (newer version), which has additional API declared in + (acl_t) and implemented in libsec (acl_set, acl_trivial, + acl_fromtext, ...). */ + return acl_trivial (name); + +# else /* Solaris, Cygwin, general case */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t)) + }; + aclent_t buf[alloc_init]; + size_t alloc = alloc_init; + aclent_t *entries = buf; + aclent_t *malloced = NULL; + int count; + + for (;;) + { + count = acl (name, GETACL, alloc, entries); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = + (aclent_t *) malloc (alloc * sizeof (aclent_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + if (count < 0) + { + if (errno == ENOSYS || errno == ENOTSUP) + ; + else + { + free (malloced); + return -1; + } + } + else if (count == 0) + ; + else + { + /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin + returns only 3 entries for files with no ACL. But this is safe: + If there are more than 4 entries, there cannot be only the + "user::", "group::", "other:", and "mask:" entries. */ + if (count > 4) + { + free (malloced); + return 1; + } + + if (acl_nontrivial (count, entries)) + { + free (malloced); + return 1; + } + } + free (malloced); + } + +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). */ + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) + }; + ace_t buf[alloc_init]; + size_t alloc = alloc_init; + ace_t *entries = buf; + ace_t *malloced = NULL; + int count; + + for (;;) + { + count = acl (name, ACE_GETACL, alloc, entries); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + if (count < 0) + { + if (errno == ENOSYS || errno == EINVAL) + ; + else + { + free (malloced); + return -1; + } + } + else if (count == 0) + ; + else + { + /* In the old (original Solaris 10) convention: + If there are more than 3 entries, there cannot be only the + ACE_OWNER, ACE_GROUP, ACE_OTHER entries. + In the newer Solaris 10 and Solaris 11 convention: + If there are more than 6 entries, there cannot be only the + ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with + NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with + NEW_ACE_ACCESS_DENIED_ACE_TYPE. */ + if (count > 6) + { + free (malloced); + return 1; + } + + if (acl_ace_nontrivial (count, entries)) + { + free (malloced); + return 1; + } + } + free (malloced); + } +# endif + + return 0; +# endif + +# elif HAVE_GETACL /* HP-UX */ + + { + struct acl_entry entries[NACLENTRIES]; + int count; + + count = getacl (name, NACLENTRIES, entries); + + if (count < 0) + { + /* ENOSYS is seen on newer HP-UX versions. + EOPNOTSUPP is typically seen on NFS mounts. + ENOTSUP was seen on Quantum StorNext file systems (cvfs). */ + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 3 entries, there cannot be only the + (uid,%), (%,gid), (%,%) entries. */ + if (count > 3) + return 1; + + { + struct stat statbuf; + + if (stat (name, &statbuf) == -1 && errno != EOVERFLOW) + return -1; + + return acl_nontrivial (count, entries); + } + } + } + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + + { + struct acl entries[NACLVENTRIES]; + int count; + + count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries); + + if (count < 0) + { + /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23. + EINVAL is seen on NFS in HP-UX 11.31. */ + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLVENTRIES) + /* If NACLVENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 4 entries, there cannot be only the + four base ACL entries. */ + if (count > 4) + return 1; + + return aclv_nontrivial (count, entries); + } + } + +# endif + +# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ + + acl_type_t type; + char aclbuf[1024]; + void *acl = aclbuf; + size_t aclsize = sizeof (aclbuf); + mode_t mode; + + for (;;) + { + /* The docs say that type being 0 is equivalent to ACL_ANY, but it + is not true, in AIX 5.3. */ + type.u64 = ACL_ANY; + if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0) + break; + if (errno == ENOSYS) + return 0; + if (errno != ENOSPC) + { + if (acl != aclbuf) + free (acl); + return -1; + } + aclsize = 2 * aclsize; + if (acl != aclbuf) + free (acl); + acl = malloc (aclsize); + if (acl == NULL) + { + errno = ENOMEM; + return -1; + } + } + + if (type.u64 == ACL_AIXC) + { + int result = acl_nontrivial ((struct acl *) acl); + if (acl != aclbuf) + free (acl); + return result; + } + else if (type.u64 == ACL_NFS4) + { + int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl); + if (acl != aclbuf) + free (acl); + return result; + } + else + { + /* A newer type of ACL has been introduced in the system. + We should better support it. */ + if (acl != aclbuf) + free (acl); + errno = EINVAL; + return -1; + } + +# elif HAVE_STATACL /* older AIX */ + + union { struct acl a; char room[4096]; } u; + + if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0) + return -1; + + return acl_nontrivial (&u.a); + +# elif HAVE_ACLSORT /* NonStop Kernel */ + + { + struct acl entries[NACLENTRIES]; + int count; + + count = acl ((char *) name, ACL_GET, NACLENTRIES, entries); + + if (count < 0) + { + if (errno == ENOSYS || errno == ENOTSUP) + ; + else + return -1; + } + else if (count == 0) + return 0; + else /* count > 0 */ + { + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 4 entries, there cannot be only the + four base ACL entries. */ + if (count > 4) + return 1; + + return acl_nontrivial (count, entries); + } + } + +# endif + } +#endif + + return 0; +} diff --git a/cross/lib/filemode.c b/cross/lib/filemode.c new file mode 100644 index 00000000000..318d287f27d --- /dev/null +++ b/cross/lib/filemode.c @@ -0,0 +1,166 @@ +/* filemode.c -- make a string describing file modes + + Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2023 Free + Software Foundation, Inc. + + This program is free software: you can 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 . */ + +#include + +#include "filemode.h" + +#if ! HAVE_DECL_STRMODE + +/* Return a character indicating the type of file described by + file mode BITS: + '-' regular file + 'b' block special file + 'c' character special file + 'C' high performance ("contiguous data") file + 'd' directory + 'D' door + 'l' symbolic link + 'm' multiplexed file (7th edition Unix; obsolete) + 'n' network special file (HP-UX) + 'p' fifo (named pipe) + 'P' port + 's' socket + 'w' whiteout (4.4BSD) + '?' some other file type */ + +static char +ftypelet (mode_t bits) +{ + /* These are the most common, so test for them first. */ + if (S_ISREG (bits)) + return '-'; + if (S_ISDIR (bits)) + return 'd'; + + /* Other letters standardized by POSIX 1003.1-2004. */ + if (S_ISBLK (bits)) + return 'b'; + if (S_ISCHR (bits)) + return 'c'; + if (S_ISLNK (bits)) + return 'l'; + if (S_ISFIFO (bits)) + return 'p'; + + /* Other file types (though not letters) standardized by POSIX. */ + if (S_ISSOCK (bits)) + return 's'; + + /* Nonstandard file types. */ + if (S_ISCTG (bits)) + return 'C'; + if (S_ISDOOR (bits)) + return 'D'; + if (S_ISMPB (bits) || S_ISMPC (bits) || S_ISMPX (bits)) + return 'm'; + if (S_ISNWK (bits)) + return 'n'; + if (S_ISPORT (bits)) + return 'P'; + if (S_ISWHT (bits)) + return 'w'; + + return '?'; +} + +/* Like filemodestring, but rely only on MODE. */ + +void +strmode (mode_t mode, char *str) +{ + str[0] = ftypelet (mode); + str[1] = mode & S_IRUSR ? 'r' : '-'; + str[2] = mode & S_IWUSR ? 'w' : '-'; + str[3] = (mode & S_ISUID + ? (mode & S_IXUSR ? 's' : 'S') + : (mode & S_IXUSR ? 'x' : '-')); + str[4] = mode & S_IRGRP ? 'r' : '-'; + str[5] = mode & S_IWGRP ? 'w' : '-'; + str[6] = (mode & S_ISGID + ? (mode & S_IXGRP ? 's' : 'S') + : (mode & S_IXGRP ? 'x' : '-')); + str[7] = mode & S_IROTH ? 'r' : '-'; + str[8] = mode & S_IWOTH ? 'w' : '-'; + str[9] = (mode & S_ISVTX + ? (mode & S_IXOTH ? 't' : 'T') + : (mode & S_IXOTH ? 'x' : '-')); + str[10] = ' '; + str[11] = '\0'; +} + +#endif /* ! HAVE_DECL_STRMODE */ + +/* filemodestring - fill in string STR with an ls-style ASCII + representation of the st_mode field of file stats block STATP. + 12 characters are stored in STR. + The characters stored in STR are: + + 0 File type, as in ftypelet above, except that other letters are used + for files whose type cannot be determined solely from st_mode: + + 'F' semaphore + 'Q' message queue + 'S' shared memory object + 'T' typed memory object + + 1 'r' if the owner may read, '-' otherwise. + + 2 'w' if the owner may write, '-' otherwise. + + 3 'x' if the owner may execute, 's' if the file is + set-user-id, '-' otherwise. + 'S' if the file is set-user-id, but the execute + bit isn't set. + + 4 'r' if group members may read, '-' otherwise. + + 5 'w' if group members may write, '-' otherwise. + + 6 'x' if group members may execute, 's' if the file is + set-group-id, '-' otherwise. + 'S' if it is set-group-id but not executable. + + 7 'r' if any user may read, '-' otherwise. + + 8 'w' if any user may write, '-' otherwise. + + 9 'x' if any user may execute, 't' if the file is "sticky" + (will be retained in swap space after execution), '-' + otherwise. + 'T' if the file is sticky but not executable. + + 10 ' ' for compatibility with 4.4BSD strmode, + since this interface does not support ACLs. + + 11 '\0'. */ + +void +filemodestring (struct stat const *statp, char *str) +{ + strmode (statp->st_mode, str); + + if (S_TYPEISSEM (statp)) + str[0] = 'F'; + else if (S_TYPEISMQ (statp)) + str[0] = 'Q'; + else if (S_TYPEISSHM (statp)) + str[0] = 'S'; + else if (S_TYPEISTMO (statp)) + str[0] = 'T'; +} diff --git a/cross/lib/filemode.h b/cross/lib/filemode.h new file mode 100644 index 00000000000..15a8dcc3760 --- /dev/null +++ b/cross/lib/filemode.h @@ -0,0 +1,44 @@ +/* Make a string describing file modes. + + Copyright (C) 1998-1999, 2003, 2006, 2009-2023 Free Software Foundation, + Inc. + + This program is free software: you can 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 . */ + +#ifndef FILEMODE_H_ + +# include +# include + +/* Get the declaration of strmode. */ +# if HAVE_DECL_STRMODE +# include /* Mac OS X, FreeBSD, OpenBSD */ +# include /* NetBSD */ +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +# if !HAVE_DECL_STRMODE +extern void strmode (mode_t mode, char *str); +# endif + +extern void filemodestring (struct stat const *statp, char *str); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/cross/lib/filename.h b/cross/lib/filename.h new file mode 100644 index 00000000000..a2400a9dfe3 --- /dev/null +++ b/cross/lib/filename.h @@ -0,0 +1,112 @@ +/* Basic filename support macros. + Copyright (C) 2001-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +/* From Paul Eggert and Jim Meyering. */ + +#ifndef _FILENAME_H +#define _FILENAME_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Filename support. + ISSLASH(C) tests whether C is a directory separator + character. + HAS_DEVICE(Filename) tests whether Filename contains a device + specification. + FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification + at the beginning of Filename, + index of the part consisting of + alternating components and slashes. + FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + 1 when a non-empty device specification + can be followed by an empty or relative + part, + 0 when a non-empty device specification + must be followed by a slash, + 0 when device specification don't exist. + IS_ABSOLUTE_FILE_NAME(Filename) + tests whether Filename is independent of + any notion of "current directory". + IS_RELATIVE_FILE_NAME(Filename) + tests whether Filename may be concatenated + to a directory filename. + Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a + relative file name! + IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device + or directory specification. + */ +#if defined _WIN32 || defined __CYGWIN__ \ + || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') + /* Internal macro: Tests whether a character is a drive letter. */ +# define _IS_DRIVE_LETTER(C) \ + (((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z')) + /* Help the compiler optimizing it. This assumes ASCII. */ +# undef _IS_DRIVE_LETTER +# define _IS_DRIVE_LETTER(C) \ + (((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a') +# define HAS_DEVICE(Filename) \ + (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':') +# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0) +# ifdef __CYGWIN__ +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +# else + /* On native Windows, OS/2, DOS, the system has the notion of a + "current directory" on each drive. */ +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1 +# endif +# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define IS_ABSOLUTE_FILE_NAME(Filename) \ + ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)]) +# else +# define IS_ABSOLUTE_FILE_NAME(Filename) \ + (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)) +# endif +# define IS_RELATIVE_FILE_NAME(Filename) \ + (! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))) +# define IS_FILE_NAME_WITH_DIR(Filename) \ + (strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \ + || HAS_DEVICE (Filename)) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define HAS_DEVICE(Filename) ((void) (Filename), 0) +# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0) +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0]) +# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0])) +# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL) +#endif + +/* Deprecated macros. For backward compatibility with old users of the + 'filename' module. */ +#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME +#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR + + +#ifdef __cplusplus +} +#endif + +#endif /* _FILENAME_H */ diff --git a/cross/lib/filevercmp.c b/cross/lib/filevercmp.c new file mode 100644 index 00000000000..78e1faff536 --- /dev/null +++ b/cross/lib/filevercmp.c @@ -0,0 +1,188 @@ +/* Compare file names containing version numbers. + + Copyright (C) 1995 Ian Jackson + Copyright (C) 2001 Anthony Towns + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#include +#include "filevercmp.h" + +#include +#include +#include + +/* Return the length of a prefix of S that corresponds to the suffix + defined by this extended regular expression in the C locale: + (\.[A-Za-z~][A-Za-z0-9~]*)*$ + Use the longest suffix matching this regular expression, + except do not use all of S as a suffix if S is nonempty. + If *LEN is -1, S is a string; set *LEN to S's length. + Otherwise, *LEN should be nonnegative, S is a char array, + and *LEN does not change. */ +static idx_t +file_prefixlen (char const *s, ptrdiff_t *len) +{ + size_t n = *len; /* SIZE_MAX if N == -1. */ + idx_t prefixlen = 0; + + for (idx_t i = 0; ; ) + { + if (*len < 0 ? !s[i] : i == n) + { + *len = i; + return prefixlen; + } + + i++; + prefixlen = i; + while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) + || s[i + 1] == '~')) + for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) + continue; + } +} + +/* Return a version sort comparison value for S's byte at position POS. + S has length LEN. If POS == LEN, sort before all non-'~' bytes. */ + +static int +order (char const *s, idx_t pos, idx_t len) +{ + if (pos == len) + return -1; + + unsigned char c = s[pos]; + if (c_isdigit (c)) + return 0; + else if (c_isalpha (c)) + return c; + else if (c == '~') + return -2; + else + { + static_assert (UCHAR_MAX <= (INT_MAX - 1 - 2) / 2); + return c + UCHAR_MAX + 1; + } +} + +/* slightly modified verrevcmp function from dpkg + S1, S2 - compared char array + S1_LEN, S2_LEN - length of arrays to be scanned + + This implements the algorithm for comparison of version strings + specified by Debian and now widely adopted. The detailed + specification can be found in the Debian Policy Manual in the + section on the 'Version' control field. This version of the code + implements that from s5.6.12 of Debian Policy v3.8.0.1 + https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */ +static int _GL_ATTRIBUTE_PURE +verrevcmp (const char *s1, idx_t s1_len, const char *s2, idx_t s2_len) +{ + idx_t s1_pos = 0; + idx_t s2_pos = 0; + while (s1_pos < s1_len || s2_pos < s2_len) + { + int first_diff = 0; + while ((s1_pos < s1_len && !c_isdigit (s1[s1_pos])) + || (s2_pos < s2_len && !c_isdigit (s2[s2_pos]))) + { + int s1_c = order (s1, s1_pos, s1_len); + int s2_c = order (s2, s2_pos, s2_len); + if (s1_c != s2_c) + return s1_c - s2_c; + s1_pos++; + s2_pos++; + } + while (s1_pos < s1_len && s1[s1_pos] == '0') + s1_pos++; + while (s2_pos < s2_len && s2[s2_pos] == '0') + s2_pos++; + while (s1_pos < s1_len && s2_pos < s2_len + && c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos])) + { + if (!first_diff) + first_diff = s1[s1_pos] - s2[s2_pos]; + s1_pos++; + s2_pos++; + } + if (s1_pos < s1_len && c_isdigit (s1[s1_pos])) + return 1; + if (s2_pos < s2_len && c_isdigit (s2[s2_pos])) + return -1; + if (first_diff) + return first_diff; + } + return 0; +} + +/* Compare version strings S1 and S2. + See filevercmp.h for function description. */ +int +filevercmp (const char *s1, const char *s2) +{ + return filenvercmp (s1, -1, s2, -1); +} + +/* Compare versions A (of length ALEN) and B (of length BLEN). + See filevercmp.h for function description. */ +int +filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen) +{ + /* Special case for empty versions. */ + bool aempty = alen < 0 ? !a[0] : !alen; + bool bempty = blen < 0 ? !b[0] : !blen; + if (aempty) + return -!bempty; + if (bempty) + return 1; + + /* Special cases for leading ".": "." sorts first, then "..", then + other names with leading ".", then other names. */ + if (a[0] == '.') + { + if (b[0] != '.') + return -1; + + bool adot = alen < 0 ? !a[1] : alen == 1; + bool bdot = blen < 0 ? !b[1] : blen == 1; + if (adot) + return -!bdot; + if (bdot) + return 1; + + bool adotdot = a[1] == '.' && (alen < 0 ? !a[2] : alen == 2); + bool bdotdot = b[1] == '.' && (blen < 0 ? !b[2] : blen == 2); + if (adotdot) + return -!bdotdot; + if (bdotdot) + return 1; + } + else if (b[0] == '.') + return 1; + + /* Cut file suffixes. */ + idx_t aprefixlen = file_prefixlen (a, &alen); + idx_t bprefixlen = file_prefixlen (b, &blen); + + /* If both suffixes are empty, a second pass would return the same thing. */ + bool one_pass_only = aprefixlen == alen && bprefixlen == blen; + + int result = verrevcmp (a, aprefixlen, b, bprefixlen); + + /* Return the initial result if nonzero, or if no second pass is needed. + Otherwise, restore the suffixes and try again. */ + return result || one_pass_only ? result : verrevcmp (a, alen, b, blen); +} diff --git a/cross/lib/filevercmp.h b/cross/lib/filevercmp.h new file mode 100644 index 00000000000..6b81ab32a7f --- /dev/null +++ b/cross/lib/filevercmp.h @@ -0,0 +1,78 @@ +/* Compare file names containing version numbers. + + Copyright (C) 1995 Ian Jackson + Copyright (C) 2001 Anthony Towns + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#ifndef FILEVERCMP_H +#define FILEVERCMP_H + +#include + +/* Compare strings A and B as file names containing version numbers, + and return an integer that is negative, zero, or positive depending + on whether A compares less than, equal to, or greater than B. + + Use the following version sort algorithm: + + 1. Compare the strings' maximal-length non-digit prefixes lexically. + If there is a difference return that difference. + Otherwise discard the prefixes and continue with the next step. + + 2. Compare the strings' maximal-length digit prefixes, using + numeric comparison of the numbers represented by each prefix. + (Treat an empty prefix as zero; this can happen only at string end.) + If there is a difference, return that difference. + Otherwise discard the prefixes and continue with the next step. + + 3. If both strings are empty, return 0. Otherwise continue with step 1. + + In version sort, lexical comparison is left to right, byte by byte, + using the byte's numeric value (0-255), except that: + + 1. ASCII letters sort before other bytes. + 2. A tilde sorts before anything, even an empty string. + + In addition to the version sort rules, the following strings have + special priority and sort before all other strings (listed in order): + + 1. The empty string. + 2. ".". + 3. "..". + 4. Strings starting with "." sort before other strings. + + Before comparing two strings where both begin with non-".", + or where both begin with "." but neither is "." or "..", + suffixes matching the C-locale extended regular expression + (\.[A-Za-z~][A-Za-z0-9~]*)*$ are removed and the strings compared + without them, using version sort without special priority; + if they do not compare equal, this comparison result is used and + the suffixes are effectively ignored. Otherwise, the entire + strings are compared using version sort. When removing a suffix + from a nonempty string, remove the maximal-length suffix such that + the remaining string is nonempty. + + This function is intended to be a replacement for strverscmp. */ +int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE; + +/* Like filevercmp, except compare the byte arrays A (of length ALEN) + and B (of length BLEN) so that A and B can contain '\0', which + sorts just before '\1'. But if ALEN is -1 treat A as a string + terminated by '\0', and similarly for BLEN. */ +int filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen) + _GL_ATTRIBUTE_PURE; + +#endif /* FILEVERCMP_H */ diff --git a/cross/lib/fingerprint.c b/cross/lib/fingerprint.c new file mode 100644 index 00000000000..d83de2245e8 --- /dev/null +++ b/cross/lib/fingerprint.c @@ -0,0 +1,66 @@ +/* Placeholder fingerprint for Emacs + +Copyright 2019-2023 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can 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. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + +#include "fingerprint.h" + +/* This random fingerprint was generated by the shell command: + + shuf -i 0-255 -n 32 -r | awk '{printf " 0x%.02X,\n", $0}' + + In the final Emacs executable, this random fingerprint is replaced + by a fingerprint of the temporary Emacs executable that was built + along the way. */ + +volatile unsigned char fingerprint[] = + { + 0xDE, + 0x86, + 0xBB, + 0x99, + 0xFF, + 0xF5, + 0x46, + 0x9A, + 0x9E, + 0x3F, + 0x9F, + 0x5D, + 0x9A, + 0xDF, + 0xF0, + 0x91, + 0xBD, + 0xCD, + 0xC1, + 0xE8, + 0x0C, + 0x16, + 0x1E, + 0xAF, + 0xB8, + 0x6C, + 0xE2, + 0x2B, + 0xB1, + 0x24, + 0xCE, + 0xB0, + }; diff --git a/cross/lib/fingerprint.h b/cross/lib/fingerprint.h new file mode 100644 index 00000000000..0bb099ceeee --- /dev/null +++ b/cross/lib/fingerprint.h @@ -0,0 +1,28 @@ +/* Header file for the Emacs build fingerprint. + +Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can 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. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#ifndef EMACS_FINGERPRINT_H +#define EMACS_FINGERPRINT_H + +/* We generate fingerprint.c and fingerprint.o from all the sources in + Emacs. This way, we have a unique value that we can use to pair + data files (like a dump file) with a specific build of Emacs. */ +extern volatile unsigned char fingerprint[32]; + +#endif diff --git a/cross/lib/flexmember.h b/cross/lib/flexmember.h new file mode 100644 index 00000000000..a6cc876a6d5 --- /dev/null +++ b/cross/lib/flexmember.h @@ -0,0 +1,60 @@ +/* Sizes of structs with flexible array members. + + Copyright 2016-2023 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . + + Written by Paul Eggert. */ + +#include + +/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. + On older platforms without _Alignof, use a pessimistic bound that is + safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. + On newer platforms, use _Alignof to get a tighter bound. */ + +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) +#else +# define FLEXALIGNOF(type) _Alignof (type) +#endif + +/* Yield a properly aligned upper bound on the size of a struct of + type TYPE with a flexible array member named MEMBER that is + followed by N bytes of other data. The result is suitable as an + argument to malloc. For example: + + struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; }; + struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char))); + + FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N), + since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is + it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size + that causes malloc to yield a pointer that is not properly aligned + for TYPE; for example, if sizeof (int) == alignof (int) == 4, + malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent + to malloc (7) and might yield a pointer that is not a multiple of 4 + (which means the pointer is not properly aligned for struct s), + whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is + equivalent to malloc (8) and must yield a pointer that is a + multiple of 4. + + Yield a value less than N if and only if arithmetic overflow occurs. */ + +#define FLEXSIZEOF(type, member, n) \ + ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ + & ~ (FLEXALIGNOF (type) - 1)) diff --git a/cross/lib/fpending.c b/cross/lib/fpending.c new file mode 100644 index 00000000000..e57155e586e --- /dev/null +++ b/cross/lib/fpending.c @@ -0,0 +1,63 @@ +/* fpending.c -- return the number of pending output bytes on a stream + Copyright (C) 2000, 2004, 2006-2007, 2009-2023 Free Software Foundation, + Inc. + + This program is free software: you can 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 . */ + +/* Written by Jim Meyering. */ + +#include + +/* Specification. */ +#include "fpending.h" + +#include "stdio-impl.h" + +/* This file is not used on systems that already have the __fpending function, + namely glibc >= 2.2, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.34, + Android API >= 23. */ + +/* Return the number of pending (aka buffered, unflushed) + bytes on the stream, FP, that is open for writing. */ +size_t +__fpending (FILE *fp) +{ + /* Most systems provide FILE as a struct and the necessary bitmask in + , because they need it for implementing getc() and putc() as + fast macros. */ +#if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 + /* GNU libc, BeOS, Haiku, Linux libc5 */ + return fp->_IO_write_ptr - fp->_IO_write_base; +#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__ + /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */ + return fp_->_p - fp_->_bf._base; +#elif defined __EMX__ /* emx+gcc */ + return fp->_ptr - fp->_buffer; +#elif defined __minix /* Minix */ + return fp_->_ptr - fp_->_buf; +#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */ + return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0); +#elif defined __UCLIBC__ /* uClibc */ + return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0); +#elif defined __QNX__ /* QNX */ + return (fp->_Mode & 0x2000 /*_MWRITE*/ ? fp->_Next - fp->_Buf : 0); +#elif defined __MINT__ /* Atari FreeMiNT */ + return fp->__bufp - fp->__buffer; +#elif defined EPLAN9 /* Plan9 */ + return fp->wp - fp->buf; +#else +# error "Please port gnulib fpending.c to your platform!" + return 1; +#endif +} diff --git a/cross/lib/fpending.h b/cross/lib/fpending.h new file mode 100644 index 00000000000..5e860db6810 --- /dev/null +++ b/cross/lib/fpending.h @@ -0,0 +1,29 @@ +/* Declare __fpending. + + Copyright (C) 2000, 2003, 2005-2006, 2009-2023 Free Software Foundation, + Inc. + + This program is free software: you can 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 . + + Written by Jim Meyering. */ + +#include +#include +#if HAVE_STDIO_EXT_H +# include +#endif + +#if !HAVE_DECL___FPENDING +size_t __fpending (FILE *) _GL_ATTRIBUTE_PURE; +#endif diff --git a/cross/lib/free.c b/cross/lib/free.c new file mode 100644 index 00000000000..372a6b0fecf --- /dev/null +++ b/cross/lib/free.c @@ -0,0 +1,53 @@ +/* Make free() preserve errno. + + Copyright (C) 2003, 2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Paul Eggert */ + +#include + +/* Specification. */ +#include + +/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */ +#if !HAVE_FREE_POSIX + +# include + +void +rpl_free (void *p) +# undef free +{ +# if defined __GNUC__ && !defined __clang__ + /* An invalid GCC optimization + + would optimize away the assignments in the code below, when link-time + optimization (LTO) is enabled. Make the code more complicated, so that + GCC does not grok how to optimize it. */ + int err[2]; + err[0] = errno; + err[1] = errno; + errno = 0; + free (p); + errno = err[errno == 0]; +# else + int err = errno; + free (p); + errno = err; +# endif +} + +#endif diff --git a/cross/lib/fstatat.c b/cross/lib/fstatat.c new file mode 100644 index 00000000000..372965ef5f6 --- /dev/null +++ b/cross/lib/fstatat.c @@ -0,0 +1,148 @@ +/* Work around an fstatat bug on Solaris 9. + + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert and Jim Meyering. */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_fstatat doesn't recurse to + rpl_fstatat. */ +#define __need_system_sys_stat_h +#include + +/* Get the original definition of fstatat. It might be defined as a macro. */ +#include +#include +#undef __need_system_sys_stat_h + +#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG +static int +orig_fstatat (int fd, char const *filename, struct stat *buf, int flags) +{ + return fstatat (fd, filename, buf, flags); +} +#endif + +#ifdef __osf__ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +# include "sys/stat.h" +#else +# include +#endif + +#include "stat-time.h" + +#include +#include +#include +#include + +#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG + +# ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK +# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0 +# endif + +static int +normal_fstatat (int fd, char const *file, struct stat *st, int flag) +{ + return stat_time_normalize (orig_fstatat (fd, file, st, flag), st); +} + +/* fstatat should always follow symbolic links that end in /, but on + Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. + Likewise, trailing slash on a non-directory should be an error. + These are the same problems that lstat.c and stat.c address, so + solve it in a similar way. + + AIX 7.1 fstatat (AT_FDCWD, ..., 0) always fails, which is a bug. + Work around this bug if FSTATAT_AT_FDCWD_0_BROKEN is nonzero. */ + +int +rpl_fstatat (int fd, char const *file, struct stat *st, int flag) +{ + int result = normal_fstatat (fd, file, st, flag); + size_t len; + + if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0) + return result; + len = strlen (file); + if (flag & AT_SYMLINK_NOFOLLOW) + { + /* Fix lstat behavior. */ + if (file[len - 1] != '/' || S_ISDIR (st->st_mode)) + return 0; + if (!S_ISLNK (st->st_mode)) + { + errno = ENOTDIR; + return -1; + } + result = normal_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); + } + /* Fix stat behavior. */ + if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/') + { + errno = ENOTDIR; + return -1; + } + return result; +} + +#else /* ! (HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG) */ + +/* On mingw, the gnulib defines 'stat' as a function-like + macro; but using it in AT_FUNC_F2 causes compilation failure + because the preprocessor sees a use of a macro that requires two + arguments but is only given one. Hence, we need an inline + forwarder to get past the preprocessor. */ +static int +stat_func (char const *name, struct stat *st) +{ + return stat (name, st); +} + +/* Likewise, if there is no native 'lstat', then the gnulib + defined it as stat, which also needs adjustment. */ +# if !HAVE_LSTAT +# undef lstat +# define lstat stat_func +# endif + +/* Replacement for Solaris' function by the same name. + + First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). + Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. + Otherwise, this function works just like Solaris' fstatat. */ + +# define AT_FUNC_NAME fstatat +# define AT_FUNC_F1 lstat +# define AT_FUNC_F2 stat_func +# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW +# define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag +# define AT_FUNC_POST_FILE_ARGS , st +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_F2 +# undef AT_FUNC_USE_F1_COND +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS + +#endif /* !HAVE_FSTATAT */ diff --git a/cross/lib/fsusage.c b/cross/lib/fsusage.c new file mode 100644 index 00000000000..f6f4b1c35fd --- /dev/null +++ b/cross/lib/fsusage.c @@ -0,0 +1,233 @@ +/* fsusage.c -- return space usage of mounted file systems + + Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2023 Free Software + Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#include + +#include "fsusage.h" + +#include +#include + +#if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */ +# include +#else +/* Don't include backward-compatibility files unless they're needed. + Eventually we'd like to remove all this cruft. */ +# include +# include +# include +#if HAVE_SYS_PARAM_H +# include +#endif +#if HAVE_SYS_MOUNT_H +# include +#endif +#if HAVE_SYS_VFS_H +# include +#endif +# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ +# include +# endif +# if HAVE_SYS_STATFS_H +# include +# endif +#endif + +/* Many space usage primitives use all 1 bits to denote a value that is + not applicable or unknown. Propagate this information by returning + a uintmax_t value that is all 1 bits if X is all 1 bits, even if X + is unsigned and narrower than uintmax_t. */ +#define PROPAGATE_ALL_ONES(x) \ + ((sizeof (x) < sizeof (uintmax_t) \ + && (~ (x) == (sizeof (x) < sizeof (int) \ + ? - (1 << (sizeof (x) * CHAR_BIT)) \ + : 0))) \ + ? UINTMAX_MAX : (uintmax_t) (x)) + +/* Extract the top bit of X as an uintmax_t value. */ +#define EXTRACT_TOP_BIT(x) ((x) \ + & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) + +/* If a value is negative, many space usage primitives store it into an + integer variable by assignment, even if the variable's type is unsigned. + So, if a space usage variable X's top bit is set, convert X to the + uintmax_t value V such that (- (uintmax_t) V) is the negative of + the original value. If X's top bit is clear, just yield X. + Use PROPAGATE_TOP_BIT if the original value might be negative; + otherwise, use PROPAGATE_ALL_ONES. */ +#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) + +#ifdef STAT_STATVFS +/* Return true if statvfs works. This is false for statvfs on systems + with GNU libc on Linux kernels before 2.6.36, which stats all + preceding entries in /proc/mounts; that makes df hang if even one + of the corresponding file systems is hard-mounted but not available. */ +# if ! (__linux__ && (__GLIBC__ || __UCLIBC__)) +/* The FRSIZE fallback is not required in this case. */ +# undef STAT_STATFS2_FRSIZE +static int statvfs_works (void) { return 1; } +# else +# include /* for strverscmp */ +# include +# include +# define STAT_STATFS2_BSIZE 1 + +static int +statvfs_works (void) +{ + static int statvfs_works_cache = -1; + struct utsname name; + if (statvfs_works_cache < 0) + statvfs_works_cache = (uname (&name) == 0 + && 0 <= strverscmp (name.release, "2.6.36")); + return statvfs_works_cache; +} +# endif +#endif + + +/* Fill in the fields of FSP with information about space usage for + the file system on which FILE resides. + DISK is the device on which FILE is mounted, for space-getting + methods that need to know it. + Return 0 if successful, -1 if not. When returning -1, ensure that + ERRNO is either a system error value, or zero if DISK is NULL + on a system that requires a non-NULL value. */ +int +get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) +{ +#ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */ + + if (statvfs_works ()) + { + struct statvfs vfsd; + + if (statvfs (file, &vfsd) < 0) + return -1; + + /* f_frsize isn't guaranteed to be supported. */ + fsp->fsu_blocksize = (vfsd.f_frsize + ? PROPAGATE_ALL_ONES (vfsd.f_frsize) + : PROPAGATE_ALL_ONES (vfsd.f_bsize)); + + fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree); + return 0; + } + +#endif + +#if defined STAT_STATVFS64 /* AIX */ + + struct statvfs64 fsd; + + if (statvfs64 (file, &fsd) < 0) + return -1; + + /* f_frsize isn't guaranteed to be supported. */ + fsp->fsu_blocksize = (fsd.f_frsize + ? PROPAGATE_ALL_ONES (fsd.f_frsize) + : PROPAGATE_ALL_ONES (fsd.f_bsize)); + +#elif defined STAT_STATFS3_OSF1 /* OSF/1 */ + + struct statfs fsd; + + if (statfs (file, &fsd, sizeof (struct statfs)) != 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize); + +#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \ + Mac OS X < 10.4, FreeBSD < 5.0, \ + NetBSD < 3.0, OpenBSD < 4.4 */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); + +# ifdef STATFS_TRUNCATES_BLOCK_COUNTS + + /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the + struct statfs are truncated to 2GB. These conditions detect that + truncation, presumably without botching the 4.1.1 case, in which + the values are not truncated. The correct counts are stored in + undocumented spare fields. */ + if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) + { + fsd.f_blocks = fsd.f_spare[0]; + fsd.f_bfree = fsd.f_spare[1]; + fsd.f_bavail = fsd.f_spare[2]; + } +# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ + +#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */ + + struct statfs fsd; + + if (statfs (file, &fsd) < 0) + return -1; + + fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); + +#elif defined STAT_STATFS4 /* SVR3, old Irix */ + + struct statfs fsd; + + if (statfs (file, &fsd, sizeof fsd, 0) < 0) + return -1; + + /* Empirically, the block counts on most SVR3 and SVR3-derived + systems seem to always be in terms of 512-byte blocks, + no matter what value f_bsize has. */ + fsp->fsu_blocksize = 512; + +#endif + +#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \ + || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \ + || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4) + + fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); + fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); + fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); + fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; + fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); + fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); + +#endif + + (void) disk; /* avoid argument-unused warning */ + return 0; +} diff --git a/cross/lib/fsusage.h b/cross/lib/fsusage.h new file mode 100644 index 00000000000..9630b04e001 --- /dev/null +++ b/cross/lib/fsusage.h @@ -0,0 +1,39 @@ +/* fsusage.h -- declarations for file system space usage info + + Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2023 Free Software + Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Space usage statistics for a file system. Blocks are 512-byte. */ + +#if !defined FSUSAGE_H_ +# define FSUSAGE_H_ + +# include + +struct fs_usage +{ + uintmax_t fsu_blocksize; /* Size of a block. */ + uintmax_t fsu_blocks; /* Total blocks. */ + uintmax_t fsu_bfree; /* Free blocks available to superuser. */ + uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ + bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ + uintmax_t fsu_files; /* Total file nodes. */ + uintmax_t fsu_ffree; /* Free file nodes. */ +}; + +int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp); + +#endif diff --git a/cross/lib/fsync.c b/cross/lib/fsync.c new file mode 100644 index 00000000000..51314662872 --- /dev/null +++ b/cross/lib/fsync.c @@ -0,0 +1,87 @@ +/* Emulate fsync on platforms that lack it, primarily Windows and + cross-compilers like MinGW. + + This is derived from sqlite3 sources. + https://www.sqlite.org/src/finfo?name=src/os_win.c + https://www.sqlite.org/copyright.html + + Written by Richard W.M. Jones + + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include +#include + +#if defined _WIN32 && ! defined __CYGWIN__ + +/* FlushFileBuffers */ +# define WIN32_LEAN_AND_MEAN +# include + +# include + +/* Get _get_osfhandle. */ +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include +# endif + +int +fsync (int fd) +{ + HANDLE h = (HANDLE) _get_osfhandle (fd); + DWORD err; + + if (h == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + + if (!FlushFileBuffers (h)) + { + /* Translate some Windows errors into rough approximations of Unix + * errors. MSDN is useless as usual - in this case it doesn't + * document the full range of errors. + */ + err = GetLastError (); + switch (err) + { + case ERROR_ACCESS_DENIED: + /* For a read-only handle, fsync should succeed, even though we have + no way to sync the access-time changes. */ + return 0; + + /* eg. Trying to fsync a tty. */ + case ERROR_INVALID_HANDLE: + errno = EINVAL; + break; + + default: + errno = EIO; + } + return -1; + } + + return 0; +} + +#else /* !Windows */ + +# error "This platform lacks fsync function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib." + +#endif /* !Windows */ diff --git a/cross/lib/ftoastr.c b/cross/lib/ftoastr.c new file mode 100644 index 00000000000..8740a4d86c8 --- /dev/null +++ b/cross/lib/ftoastr.c @@ -0,0 +1,151 @@ +/* floating point to accurate string + + Copyright (C) 2010-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +/* This code can misbehave on some buggy or older platforms, when + operating on arguments on floating types other than 'double', or + when given unusual combinations of options. Gnulib's + snprintf-posix module works around many of these problems. + + This code relies on sprintf, strtod, etc. operating accurately; + otherwise, the resulting strings could be inaccurate or too long. */ + +#include + +#include "ftoastr.h" + +#include +#include +#include + +#ifdef C_LOCALE +# include "c-snprintf.h" +# include "c-strtod.h" +# define PREFIX(name) c_ ## name +#else +# define PREFIX(name) name +#endif + +#if LENGTH == 3 +# define FLOAT long double +# define FLOAT_DIG LDBL_DIG +# define FLOAT_MIN LDBL_MIN +# define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND +# define FTOASTR PREFIX (ldtoastr) +# define PROMOTED_FLOAT long double +# define STRTOF PREFIX (strtold) +#elif LENGTH == 2 +# define FLOAT double +# define FLOAT_DIG DBL_DIG +# define FLOAT_MIN DBL_MIN +# define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND +# define FTOASTR PREFIX (dtoastr) +# define PROMOTED_FLOAT double +#else +# define LENGTH 1 +# define FLOAT float +# define FLOAT_DIG FLT_DIG +# define FLOAT_MIN FLT_MIN +# define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND +# define FTOASTR PREFIX (ftoastr) +# define PROMOTED_FLOAT double +# if HAVE_STRTOF +# define STRTOF strtof +# endif +#endif + +/* On pre-C99 hosts, approximate strtof with strtod. This + may generate one or two extra digits, but that's better than not + working at all. */ +#ifndef STRTOF +# define STRTOF PREFIX (strtod) +#endif + +/* On hosts where it's not known that snprintf works, use sprintf to + implement the subset needed here. Typically BUFSIZE is big enough + and there's little or no performance hit. */ +#ifdef C_LOCALE +# undef snprintf +# define snprintf c_snprintf +#elif ! GNULIB_SNPRINTF +# undef snprintf +# define snprintf ftoastr_snprintf +static int +ftoastr_snprintf (char *buf, size_t bufsize, char const *format, + int width, int prec, FLOAT x) +{ + PROMOTED_FLOAT promoted_x = x; + char width_0_buffer[LENGTH == 1 ? FLT_BUFSIZE_BOUND + : LENGTH == 2 ? DBL_BUFSIZE_BOUND + : LDBL_BUFSIZE_BOUND]; + int n = width; + if (bufsize < sizeof width_0_buffer) + { + n = sprintf (width_0_buffer, format, 0, prec, promoted_x); + if (n < 0) + return n; + if (n < width) + n = width; + } + if (n < bufsize) + n = sprintf (buf, format, width, prec, promoted_x); + return n; +} +#endif + +int +FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) +{ + /* The following method is simple but slow. + For ideas about speeding things up, please see: + + Andrysco M, Jhala R, Lerner S. Printing floating-point numbers: + a faster, always correct method. ACM SIGPLAN notices - POPL '16. + 2016;51(1):555-67 ; draft at + . */ + + PROMOTED_FLOAT promoted_x = x; + char format[sizeof "%-+ 0*.*Lg"]; + FLOAT abs_x = x < 0 ? -x : x; + int prec; + + char *p = format; + *p++ = '%'; + + /* Support flags that generate output parsable by strtof. */ + *p = '-'; p += (flags & FTOASTR_LEFT_JUSTIFY ) != 0; + *p = '+'; p += (flags & FTOASTR_ALWAYS_SIGNED ) != 0; + *p = ' '; p += (flags & FTOASTR_SPACE_POSITIVE) != 0; + *p = '0'; p += (flags & FTOASTR_ZERO_PAD ) != 0; + + *p++ = '*'; + *p++ = '.'; + *p++ = '*'; + *p = 'L'; p += 2 < LENGTH; + *p++ = flags & FTOASTR_UPPER_E ? 'G' : 'g'; + *p = '\0'; + + for (prec = abs_x < FLOAT_MIN ? 1 : FLOAT_DIG; ; prec++) + { + int n = snprintf (buf, bufsize, format, width, prec, promoted_x); + if (n < 0 + || FLOAT_PREC_BOUND <= prec + || (n < bufsize && STRTOF (buf, NULL) == x)) + return n; + } +} diff --git a/cross/lib/ftoastr.h b/cross/lib/ftoastr.h new file mode 100644 index 00000000000..1ce1b7a4bc6 --- /dev/null +++ b/cross/lib/ftoastr.h @@ -0,0 +1,152 @@ +/* floating point to accurate string + + Copyright (C) 2010-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +#ifndef _GL_FTOASTR_H +#define _GL_FTOASTR_H + +#include "intprops.h" +#include +#include + +/* Store into BUF (of size BUFSIZE) an accurate minimal-precision + string representation of a floating point number. FLAGS affect the + formatting of the number. Pad the output string with spaces as + necessary to width WIDTH bytes, in the style of printf. WIDTH must + be nonnegative. X is the floating-point number to be converted. + + Return the number of bytes stored into BUF, not counting the + terminating null. However, do not overrun BUF: if BUF is too + small, return a fairly tight (but not necessarily exact) upper + bound on the value that would have been returned if BUF had been + big enough. If SIZE is zero, BUF may be a null pointer. On error + (e.g., returned value would exceed INT_MAX), return -1 and set + errno. + + Example: + + char buf[DBL_BUFSIZE_BOUND]; + int r = dtoastr (buf, sizeof buf, 0, 0, 0.1); + + In the C locale, this sets R to 3 and stores "0.1" into BUF. */ + +int ftoastr (char *buf, size_t bufsize, int flags, int width, float x); +int dtoastr (char *buf, size_t bufsize, int flags, int width, double x); +int ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); + +/* The last two functions except that the formatting takes place in + the C locale. */ +int c_dtoastr (char *buf, size_t bufsize, int flags, int width, double x); +int c_ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); + + +/* Flag values for ftoastr etc. These can be ORed together. */ +enum + { + /* Left justify within the width; the default is right justification. */ + FTOASTR_LEFT_JUSTIFY = 1, + + /* Output "+" before positive numbers; the default outputs nothing. */ + FTOASTR_ALWAYS_SIGNED = 2, + + /* Output " " before positive numbers; ignored if + FTOASTR_ALWAYS_SIGNED is also given. */ + FTOASTR_SPACE_POSITIVE = 4, + + /* Pad with zeros instead of spaces; ignored if FTOASTR_LEFT_JUSTIFY + is also given. */ + FTOASTR_ZERO_PAD = 8, + + /* Use 'E' instead of 'e' before the exponent. */ + FTOASTR_UPPER_E = 16 + }; + + +/* _GL_FLT_PREC_BOUND is an upper bound on the precision needed to + represent a float value without losing information. Likewise for + _GL_DBL_PREC_BOUND and double, and _GL_LDBL_PREC_BOUND and long double. + These are macros, not enums, to work around a bug in IBM xlc 12.1. */ + +#if FLT_RADIX == 10 /* decimal floating point */ +# define _GL_FLT_PREC_BOUND FLT_MANT_DIG +# define _GL_DBL_PREC_BOUND DBL_MANT_DIG +# define _GL_LDBL_PREC_BOUND LDBL_MANT_DIG +#else + +/* An upper bound on the number of bits needed to represent a single + digit in a floating-point fraction. */ +# if FLT_RADIX == 2 /* IEEE 754 floating point, VAX floating point, etc. */ +# define _GL_FLOAT_DIG_BITS_BOUND 1 +# elif FLT_RADIX <= 16 /* IBM hex floating point has FLT_RADIX == 16. */ +# define _GL_FLOAT_DIG_BITS_BOUND 4 +# else /* no machine is this bad, but let's be complete */ +# define _GL_FLOAT_DIG_BITS_BOUND ((int) TYPE_WIDTH (int) - 1) +# endif + +/* An upper bound on the number of decimal digits needed to represent + a floating point number accurately, assuming a fraction contains + DIG digits. For why the "+ 1" is needed, see "Binary to Decimal + Conversion" in David Goldberg's paper "What Every Computer + Scientist Should Know About Floating-Point Arithmetic" + . */ +# define _GL_FLOAT_PREC_BOUND(dig) \ + (INT_BITS_STRLEN_BOUND ((dig) * _GL_FLOAT_DIG_BITS_BOUND) + 1) + +# define _GL_FLT_PREC_BOUND _GL_FLOAT_PREC_BOUND ( FLT_MANT_DIG) +# define _GL_DBL_PREC_BOUND _GL_FLOAT_PREC_BOUND ( DBL_MANT_DIG) +# define _GL_LDBL_PREC_BOUND _GL_FLOAT_PREC_BOUND (LDBL_MANT_DIG) +#endif + + +/* Bound on the number of bytes printed for an exponent in the range + MIN..MAX, where MIN < 0 < MAX; printf always prints a sign and at + least 2 digits. Although the maximum known exponent is 4932 for + IEEE 754 binary128, support tight bounds for exponents up to a + million, just in case. */ +#define _GL_FLOAT_EXPONENT_STRLEN_BOUND(min, max) \ + ( -100 < (min) && (max) < 100 ? 3 \ + : -1000 < (min) && (max) < 1000 ? 4 \ + : -10000 < (min) && (max) < 10000 ? 5 \ + : -100000 < (min) && (max) < 100000 ? 6 \ + : -1000000 < (min) && (max) < 1000000 ? 7 \ + : INT_STRLEN_BOUND (int) /* not a tight bound */) + +/* A reasonably tight bound on the length of a type-T floating value + formatted with ftoastr etc. Room is needed for sign, fraction + digits, decimal point, "e", and exponent. POINTLEN should be a + reasonably tight bound on the string length of the decimal + point. */ +#define _GL_FLOAT_STRLEN_BOUND_L(t, pointlen) \ + (1 + _GL_##t##_PREC_BOUND + pointlen + 1 \ + + _GL_FLOAT_EXPONENT_STRLEN_BOUND (t##_MIN_10_EXP, t##_MAX_10_EXP)) +#define FLT_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L ( FLT, pointlen) +#define DBL_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L ( DBL, pointlen) +#define LDBL_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L (LDBL, pointlen) + +/* Looser bounds that are locale-independent and are integral constant + expressions. */ +#define FLT_STRLEN_BOUND FLT_STRLEN_BOUND_L (MB_LEN_MAX) +#define DBL_STRLEN_BOUND DBL_STRLEN_BOUND_L (MB_LEN_MAX) +#define LDBL_STRLEN_BOUND LDBL_STRLEN_BOUND_L (MB_LEN_MAX) + +/* Looser, locale-independent bounds that include the trailing null byte. */ +#define FLT_BUFSIZE_BOUND ( FLT_STRLEN_BOUND + 1) +#define DBL_BUFSIZE_BOUND ( DBL_STRLEN_BOUND + 1) +#define LDBL_BUFSIZE_BOUND (LDBL_STRLEN_BOUND + 1) + +#endif /* _GL_FTOASTR_H */ diff --git a/cross/lib/futimens.c b/cross/lib/futimens.c new file mode 100644 index 00000000000..5bb30493c7e --- /dev/null +++ b/cross/lib/futimens.c @@ -0,0 +1,37 @@ +/* Set the access and modification time of an open fd. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* written by Eric Blake */ + +#include + +#include + +#include "utimens.h" + +/* Set the access and modification timestamps of FD to be + TIMESPEC[0] and TIMESPEC[1], respectively. + Fail with ENOSYS on systems without futimes (or equivalent). + If TIMESPEC is null, set the timestamps to the current time. + Return 0 on success, -1 (setting errno) on failure. */ +int +futimens (int fd, struct timespec const times[2]) +{ + /* fdutimens also works around bugs in native futimens, when running + with glibc compiled against newer headers but on a Linux kernel + older than 2.6.32. */ + return fdutimens (fd, NULL, times); +} diff --git a/cross/lib/get-permissions.c b/cross/lib/get-permissions.c new file mode 100644 index 00000000000..545ad23195b --- /dev/null +++ b/cross/lib/get-permissions.c @@ -0,0 +1,291 @@ +/* Get permissions of a file. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include +#include "acl.h" + +#include "acl-internal.h" + +/* Read the permissions of a file into CTX. If DESC is a valid file descriptor, + use file descriptor operations, else use filename based operations on NAME. + MODE is the file mode obtained from a previous stat call. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +get_permissions (const char *name, int desc, mode_t mode, + struct permission_context *ctx) +{ + memset (ctx, 0, sizeof *ctx); + ctx->mode = mode; + +#if USE_ACL && HAVE_ACL_GET_FILE + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ + + if (HAVE_ACL_GET_FD && desc != -1) + ctx->acl = acl_get_fd (desc); + else + ctx->acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (ctx->acl == NULL) + return acl_errno_valid (errno) ? -1 : 0; + + /* With POSIX ACLs, a file cannot have "no" acl; a file without + extended permissions has a "minimal" acl which is equivalent to the + file mode. */ + + if (S_ISDIR (mode)) + { + ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT); + if (ctx->default_acl == NULL) + return -1; + } + +# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */ + + /* TODO (see set_permissions). */ + +# endif + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + if (HAVE_ACL_GET_FD && desc != -1) + ctx->acl = acl_get_fd (desc); + else + ctx->acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (ctx->acl == NULL) + return acl_errno_valid (errno) ? -1 : 0; + +# endif + +#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). + There is an API + pathconf (name, _PC_ACL_ENABLED) + fpathconf (desc, _PC_ACL_ENABLED) + that allows us to determine which of the two kinds of ACLs is supported + for the given file. But some file systems may implement this call + incorrectly, so better not use it. + When fetching the source ACL, we simply fetch both ACL types. + When setting the destination ACL, we try either ACL types, assuming + that the kernel will translate the ACL from one form to the other. + (See in + the description of ENOTSUP.) */ + for (;;) + { + int ret; + + if (desc != -1) + ret = facl (desc, ACE_GETACLCNT, 0, NULL); + else + ret = acl (name, ACE_GETACLCNT, 0, NULL); + if (ret < 0) + { + if (errno == ENOSYS || errno == EINVAL) + ret = 0; + else + return -1; + } + ctx->ace_count = ret; + + if (ctx->ace_count == 0) + break; + + ctx->ace_entries = (ace_t *) malloc (ctx->ace_count * sizeof (ace_t)); + if (ctx->ace_entries == NULL) + { + errno = ENOMEM; + return -1; + } + + if (desc != -1) + ret = facl (desc, ACE_GETACL, ctx->ace_count, ctx->ace_entries); + else + ret = acl (name, ACE_GETACL, ctx->ace_count, ctx->ace_entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EINVAL) + { + free (ctx->ace_entries); + ctx->ace_entries = NULL; + ctx->ace_count = 0; + break; + } + else + return -1; + } + if (ret <= ctx->ace_count) + { + ctx->ace_count = ret; + break; + } + /* Huh? The number of ACL entries has increased since the last call. + Repeat. */ + free (ctx->ace_entries); + ctx->ace_entries = NULL; + } +# endif + + for (;;) + { + int ret; + + if (desc != -1) + ret = facl (desc, GETACLCNT, 0, NULL); + else + ret = acl (name, GETACLCNT, 0, NULL); + if (ret < 0) + { + if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) + ret = 0; + else + return -1; + } + ctx->count = ret; + + if (ctx->count == 0) + break; + + ctx->entries = (aclent_t *) malloc (ctx->count * sizeof (aclent_t)); + if (ctx->entries == NULL) + { + errno = ENOMEM; + return -1; + } + + if (desc != -1) + ret = facl (desc, GETACL, ctx->count, ctx->entries); + else + ret = acl (name, GETACL, ctx->count, ctx->entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) + { + free (ctx->entries); + ctx->entries = NULL; + ctx->count = 0; + break; + } + else + return -1; + } + if (ret <= ctx->count) + { + ctx->count = ret; + break; + } + /* Huh? The number of ACL entries has increased since the last call. + Repeat. */ + free (ctx->entries); + ctx->entries = NULL; + } + +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + + { + int ret; + + if (desc != -1) + ret = fgetacl (desc, NACLENTRIES, ctx->entries); + else + ret = getacl (name, NACLENTRIES, ctx->entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + ret = 0; + else + return -1; + } + else if (ret > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->count = ret; + +# if HAVE_ACLV_H + ret = acl ((char *) name, ACL_GET, NACLVENTRIES, ctx->aclv_entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + ret = 0; + else + return -2; + } + else if (ret > NACLVENTRIES) + /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->aclv_count = ret; +# endif + } + +#elif USE_ACL && HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ + + /* TODO (see set_permissions). */ + +#elif USE_ACL && HAVE_STATACL /* older AIX */ + + { + int ret; + if (desc != -1) + ret = fstatacl (desc, STX_NORMAL, &ctx->u.a, sizeof ctx->u); + else + ret = statacl ((char *) name, STX_NORMAL, &ctx->u.a, sizeof ctx->u); + if (ret == 0) + ctx->have_u = true; + } + +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + + { + int ret = acl ((char *) name, ACL_GET, NACLENTRIES, ctx->entries); + if (ret < 0) + return -1; + else if (ret > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->count = ret; + } + +#endif + + return 0; + +} diff --git a/cross/lib/getdelim.c b/cross/lib/getdelim.c new file mode 100644 index 00000000000..79ec3dd12a3 --- /dev/null +++ b/cross/lib/getdelim.c @@ -0,0 +1,147 @@ +/* getdelim.c --- Implementation of replacement getdelim function. + Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Ported from glibc by Simon Josefsson. */ + +/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc + optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ +#define _GL_ARG_NONNULL(params) + +#include + +#include + +#include +#include +#include +#include + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +# define getc_maybe_unlocked(fp) getc(fp) +#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED +# undef flockfile +# undef funlockfile +# define flockfile(x) ((void) 0) +# define funlockfile(x) ((void) 0) +# define getc_maybe_unlocked(fp) getc(fp) +#else +# define getc_maybe_unlocked(fp) getc_unlocked(fp) +#endif + +static void +alloc_failed (void) +{ +#if defined _WIN32 && ! defined __CYGWIN__ + /* Avoid errno problem without using the realloc module; see: + https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */ + errno = ENOMEM; +#endif +} + +/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) +{ + ssize_t result; + size_t cur_len = 0; + + if (lineptr == NULL || n == NULL || fp == NULL) + { + errno = EINVAL; + return -1; + } + + flockfile (fp); + + if (*lineptr == NULL || *n == 0) + { + char *new_lineptr; + *n = 120; + new_lineptr = (char *) realloc (*lineptr, *n); + if (new_lineptr == NULL) + { + alloc_failed (); + result = -1; + goto unlock_return; + } + *lineptr = new_lineptr; + } + + for (;;) + { + int i; + + i = getc_maybe_unlocked (fp); + if (i == EOF) + { + result = -1; + break; + } + + /* Make enough space for len+1 (for final NUL) bytes. */ + if (cur_len + 1 >= *n) + { + size_t needed_max = + SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + size_t needed = 2 * *n + 1; /* Be generous. */ + char *new_lineptr; + + if (needed_max < needed) + needed = needed_max; + if (cur_len + 1 >= needed) + { + result = -1; + errno = EOVERFLOW; + goto unlock_return; + } + + new_lineptr = (char *) realloc (*lineptr, needed); + if (new_lineptr == NULL) + { + alloc_failed (); + result = -1; + goto unlock_return; + } + + *lineptr = new_lineptr; + *n = needed; + } + + (*lineptr)[cur_len] = i; + cur_len++; + + if (i == delimiter) + break; + } + (*lineptr)[cur_len] = '\0'; + result = cur_len ? cur_len : result; + + unlock_return: + funlockfile (fp); /* doesn't set errno */ + + return result; +} diff --git a/cross/lib/getdtablesize.c b/cross/lib/getdtablesize.c new file mode 100644 index 00000000000..ac2d1753a6b --- /dev/null +++ b/cross/lib/getdtablesize.c @@ -0,0 +1,124 @@ +/* getdtablesize() function: Return maximum possible file descriptor value + 1. + Copyright (C) 2008-2023 Free Software Foundation, Inc. + Written by Bruno Haible , 2008. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#if defined _WIN32 && ! defined __CYGWIN__ + +# include + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif + +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static int +_setmaxstdio_nothrow (int newmax) +{ + int result; + + TRY_MSVC_INVAL + { + result = _setmaxstdio (newmax); + } + CATCH_MSVC_INVAL + { + result = -1; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define _setmaxstdio_nothrow _setmaxstdio +# endif + +/* Cache for the previous getdtablesize () result. Safe to cache because + Windows also lacks setrlimit. */ +static int dtablesize; + +int +getdtablesize (void) +{ + if (dtablesize == 0) + { + /* We are looking for the number N such that the valid file descriptors + are 0..N-1. It can be obtained through a loop as follows: + { + int fd; + for (fd = 3; fd < 65536; fd++) + if (dup2 (0, fd) == -1) + break; + return fd; + } + On Windows XP, the result is 2048. + The drawback of this loop is that it allocates memory for a libc + internal array that is never freed. + + The number N can also be obtained as the upper bound for + _getmaxstdio (). _getmaxstdio () returns the maximum number of open + FILE objects. The sanity check in _setmaxstdio reveals the maximum + number of file descriptors. This too allocates memory, but it is + freed when we call _setmaxstdio with the original value. */ + int orig_max_stdio = _getmaxstdio (); + unsigned int bound; + for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2) + ; + _setmaxstdio_nothrow (orig_max_stdio); + dtablesize = bound; + } + return dtablesize; +} + +#else + +# include +# include + +# ifndef RLIM_SAVED_CUR +# define RLIM_SAVED_CUR RLIM_INFINITY +# endif +# ifndef RLIM_SAVED_MAX +# define RLIM_SAVED_MAX RLIM_INFINITY +# endif + +# ifdef __CYGWIN__ + /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it + hits the compile-time constant hard limit of 3200. We might as + well just report the hard limit. */ +# define rlim_cur rlim_max +# endif + +int +getdtablesize (void) +{ + struct rlimit lim; + + if (getrlimit (RLIMIT_NOFILE, &lim) == 0 + && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX + && lim.rlim_cur != RLIM_INFINITY + && lim.rlim_cur != RLIM_SAVED_CUR + && lim.rlim_cur != RLIM_SAVED_MAX) + return lim.rlim_cur; + + return INT_MAX; +} + +#endif diff --git a/cross/lib/getgroups.c b/cross/lib/getgroups.c new file mode 100644 index 00000000000..93829d3b15e --- /dev/null +++ b/cross/lib/getgroups.c @@ -0,0 +1,125 @@ +/* provide consistent interface to getgroups for systems that don't allow N==0 + + Copyright (C) 1996, 1999, 2003, 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering */ + +#include + +#include + +#include +#include +#include + +#if !HAVE_GETGROUPS + +/* Provide a stub that fails with ENOSYS, since there is no group + information available on mingw. */ +int +getgroups (_GL_UNUSED int n, _GL_UNUSED GETGROUPS_T *groups) +{ + errno = ENOSYS; + return -1; +} + +#else /* HAVE_GETGROUPS */ + +# undef getgroups +# ifndef GETGROUPS_ZERO_BUG +# define GETGROUPS_ZERO_BUG 0 +# endif + +/* On OS X 10.6 and later, use the usual getgroups, not the one + supplied when _DARWIN_C_SOURCE is defined. _DARWIN_C_SOURCE is + normally defined, since it means "conform to POSIX, but add + non-POSIX extensions even if that violates the POSIX namespace + rules", which is what we normally want. But with getgroups there + is an inconsistency, and _DARWIN_C_SOURCE means "change getgroups() + so that it no longer works right". The BUGS section of compat(5) + says that the behavior is dubious if you compile different sections + of a program with different _DARWIN_C_SOURCE settings, so fix only + the offending symbol. */ +# ifdef __APPLE__ +int posix_getgroups (int, gid_t []) __asm ("_getgroups"); +# define getgroups posix_getgroups +# endif + +/* On at least NeXTstep 3.2, getgroups (0, NULL) always fails. + On other systems, it returns the number of supplemental + groups for the process. This function handles that special case + and lets the system-provided function handle all others. However, + it can fail with ENOMEM if memory is tight. It is unspecified + whether the effective group id is included in the list. */ + +int +rpl_getgroups (int n, gid_t *group) +{ + int n_groups; + GETGROUPS_T *gbuf; + + if (n < 0) + { + errno = EINVAL; + return -1; + } + + if (n != 0 || !GETGROUPS_ZERO_BUG) + { + int result; + if (sizeof *group == sizeof *gbuf) + return getgroups (n, (GETGROUPS_T *) group); + + if (SIZE_MAX / sizeof *gbuf <= n) + { + errno = ENOMEM; + return -1; + } + gbuf = malloc (n * sizeof *gbuf); + if (!gbuf) + return -1; + result = getgroups (n, gbuf); + if (0 <= result) + { + n = result; + while (n--) + group[n] = gbuf[n]; + } + free (gbuf); + return result; + } + + n = 20; + while (1) + { + /* No need to worry about address arithmetic overflow here, + since the ancient systems that we're running on have low + limits on the number of secondary groups. */ + gbuf = malloc (n * sizeof *gbuf); + if (!gbuf) + return -1; + n_groups = getgroups (n, gbuf); + if (n_groups == -1 ? errno != EINVAL : n_groups < n) + break; + free (gbuf); + n *= 2; + } + + free (gbuf); + return n_groups; +} + +#endif /* HAVE_GETGROUPS */ diff --git a/cross/lib/getline.c b/cross/lib/getline.c new file mode 100644 index 00000000000..85f16ab8bac --- /dev/null +++ b/cross/lib/getline.c @@ -0,0 +1,27 @@ +/* getline.c --- Implementation of replacement getline function. + Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Simon Josefsson. */ + +#include + +#include + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream) +{ + return getdelim (lineptr, n, '\n', stream); +} diff --git a/cross/lib/getloadavg.c b/cross/lib/getloadavg.c new file mode 100644 index 00000000000..59b53e79980 --- /dev/null +++ b/cross/lib/getloadavg.c @@ -0,0 +1,943 @@ +/* Get the system load averages. + + Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2023 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with gnulib. + Bugs can be reported to bug-gnulib@gnu.org. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 . */ + +/* Compile-time symbols that this file uses: + + HAVE_PSTAT_GETDYNAMIC Define this if your system has the + pstat_getdynamic function. I think it + is unique to HPUX9. The best way to get the + definition is through the AC_FUNC_GETLOADAVG + macro that comes with autoconf 2.13 or newer. + If that isn't an option, then just put + AC_CHECK_FUNCS(pstat_getdynamic) in your + configure.ac file. + HAVE_LIBPERFSTAT Define this if your system has the + perfstat_cpu_total function in libperfstat (AIX). + FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. + KERNEL_FILE Name of the kernel file to nlist. + LDAV_CVT() Scale the load average from the kernel. + Returns a double. + LDAV_SYMBOL Name of kernel symbol giving load average. + LOAD_AVE_TYPE Type of the load average array in the kernel. + Must be defined unless one of + apollo, DGUX, NeXT, or UMAX is defined; + or we have libkstat; + otherwise, no load average is available. + HAVE_NLIST_H nlist.h is available. NLIST_STRUCT defaults + to this. + NLIST_STRUCT Include nlist.h, not a.out.h. + N_NAME_POINTER The nlist n_name element is a pointer, + not an array. + HAVE_STRUCT_NLIST_N_UN_N_NAME 'n_un.n_name' is member of 'struct nlist'. + LINUX_LDAV_FILE [__linux__, __ANDROID__, __CYGWIN__]: File + containing load averages. + + Specific system predefines this file uses, aside from setting + default values if not emacs: + + apollo + BSD Real BSD, not just BSD-like. + DGUX + eunice UNIX emulator under VMS. + hpux + __MSDOS__ No-op for MSDOS. + NeXT + sgi + UMAX + UMAX4_3 + VMS + _WIN32 Native Windows (possibly also defined on Cygwin) + __linux__, __ANDROID__ Linux: assumes /proc file system mounted. + Support from Michael K. Johnson. + __CYGWIN__ Cygwin emulates linux /proc/loadavg. + __NetBSD__ NetBSD: assumes /kern file system mounted. + + In addition, to avoid nesting many #ifdefs, we internally set + LDAV_DONE to indicate that the load average has been computed. + + We also #define LDAV_PRIVILEGED if a program will require + special installation to be able to call getloadavg. */ + +#include + +/* Specification. */ +#include + +#include +#include + +# include + +# if HAVE_SYS_PARAM_H +# include +# endif + +# include "intprops.h" + +# if defined _WIN32 && ! defined __CYGWIN__ && ! defined WINDOWS32 +# define WINDOWS32 +# endif + +# ifdef NeXT +/* NeXT in the 2.{0,1,2} releases defines BSD in , which + conflicts with the definition understood in this file, that this + really is BSD. */ +# undef BSD + +/* NeXT defines FSCALE in . However, we take FSCALE being + defined to mean that the nlist method should be used, which is not true. */ +# undef FSCALE +# endif + +/* Same issues as for NeXT apply to the HURD-based GNU system. */ +# ifdef __GNU__ +# undef BSD +# undef FSCALE +# endif /* __GNU__ */ + +/* Set values that are different from the defaults, which are + set a little farther down with #ifndef. */ + + +/* Some shorthands. */ + +# if defined (HPUX) && !defined (hpux) +# define hpux +# endif + +# if defined (__hpux) && !defined (hpux) +# define hpux +# endif + +# if defined (__sun) && !defined (sun) +# define sun +# endif + +# if defined (hp300) && !defined (hpux) +# define MORE_BSD +# endif + +# if defined (__SVR4) && !defined (SVR4) +# define SVR4 +# endif + +# if (defined (sun) && defined (SVR4)) || defined (SOLARIS2) +# define SUNOS_5 +# endif + +# if defined (__osf__) && (defined (__alpha) || defined (__alpha__)) +# define OSF_ALPHA +# include +# include +# include +# include +/* Tru64 4.0D's table.h redefines sys */ +# undef sys +# endif + +# if defined (__osf__) && (defined (mips) || defined (__mips__)) +# define OSF_MIPS +# include +# endif + + +/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */ +# ifndef LOAD_AVE_TYPE + +# ifdef MORE_BSD +# define LOAD_AVE_TYPE long +# endif + +# ifdef sun +# define LOAD_AVE_TYPE long +# endif + +# ifdef sgi +# define LOAD_AVE_TYPE long +# endif + +# ifdef SVR4 +# define LOAD_AVE_TYPE long +# endif + +# ifdef OSF_ALPHA +# define LOAD_AVE_TYPE long +# endif + +# if defined _AIX && ! defined HAVE_LIBPERFSTAT +# define LOAD_AVE_TYPE long +# endif + +# endif /* No LOAD_AVE_TYPE. */ + +# ifdef OSF_ALPHA +/* defines an incorrect value for FSCALE on Alpha OSF/1, + according to ghazi@noc.rutgers.edu. */ +# undef FSCALE +# define FSCALE 1024.0 +# endif + + +# ifndef FSCALE + +/* SunOS and some others define FSCALE in sys/param.h. */ + +# ifdef MORE_BSD +# define FSCALE 2048.0 +# endif + +# if defined (MIPS) || defined (SVR4) +# define FSCALE 256 +# endif + +# if defined (sgi) +/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined + above under #ifdef MIPS. But we want the sgi value. */ +# undef FSCALE +# define FSCALE 1000.0 +# endif + +# if defined _AIX && !defined HAVE_LIBPERFSTAT +# define FSCALE 65536.0 +# endif + +# endif /* Not FSCALE. */ + +# if !defined (LDAV_CVT) && defined (FSCALE) +# define LDAV_CVT(n) (((double) (n)) / FSCALE) +# endif + +# ifndef NLIST_STRUCT +# if HAVE_NLIST_H +# define NLIST_STRUCT +# endif +# endif + +# if defined (sgi) || (defined (mips) && !defined (BSD)) +# define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31)) +# endif + + +# if !defined (KERNEL_FILE) && defined (hpux) +# define KERNEL_FILE "/hp-ux" +# endif + +# if !defined (KERNEL_FILE) && (defined (MIPS) || defined (SVR4) || defined (ISC) || defined (sgi)) +# define KERNEL_FILE "/unix" +# endif + + +# if !defined (LDAV_SYMBOL) && (defined (hpux) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (_AIX) && !defined(HAVE_LIBPERFSTAT))) +# define LDAV_SYMBOL "avenrun" +# endif + +# ifdef HAVE_UNISTD_H +# include +# endif + +/* LOAD_AVE_TYPE should only get defined if we're going to use the + nlist method. */ +# if !defined (LOAD_AVE_TYPE) && (defined (BSD) || defined (LDAV_CVT) || defined (KERNEL_FILE) || defined (LDAV_SYMBOL)) +# define LOAD_AVE_TYPE double +# endif + +# ifdef LOAD_AVE_TYPE + +# ifndef __VMS +# if !(defined __linux__ || defined __ANDROID__) +# ifndef NLIST_STRUCT +# include +# else /* NLIST_STRUCT */ +# include +# endif /* NLIST_STRUCT */ + +# ifdef SUNOS_5 +# include +# include +# endif + +# if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) +# include +# endif + +# ifndef KERNEL_FILE +# define KERNEL_FILE "/vmunix" +# endif /* KERNEL_FILE */ + +# ifndef LDAV_SYMBOL +# define LDAV_SYMBOL "_avenrun" +# endif /* LDAV_SYMBOL */ +# endif /* __linux__ || __ANDROID__ */ + +# else /* __VMS */ + +# ifndef eunice +# include +# include +# else /* eunice */ +# include +# endif /* eunice */ +# endif /* __VMS */ + +# ifndef LDAV_CVT +# define LDAV_CVT(n) ((double) (n)) +# endif /* !LDAV_CVT */ + +# endif /* LOAD_AVE_TYPE */ + +# if defined HAVE_LIBPERFSTAT +# include +# include +# include +# ifndef SBITS +# define SBITS 16 +# endif +# endif + +# if defined (__GNU__) && !defined (NeXT) +/* Note that NeXT Openstep defines __GNU__ even though it should not. */ +/* GNU system acts much like NeXT, for load average purposes, + but not exactly. */ +# define NeXT +# define host_self mach_host_self +# endif + +# ifdef NeXT +# ifdef HAVE_MACH_MACH_H +# include +# else +# include +# endif +# endif /* NeXT */ + +# ifdef sgi +# include +# endif /* sgi */ + +# ifdef UMAX +# include +# include +# include +# include + +# ifdef UMAX_43 +# include +# include +# include +# include +# include +# else /* Not UMAX_43. */ +# include +# include +# include +# include +# include +# include +# endif /* Not UMAX_43. */ +# endif /* UMAX */ + +# ifdef DGUX +# include +# endif + +# if (defined __linux__ || defined __ANDROID__ \ + || defined __CYGWIN__ || defined SUNOS_5 \ + || (defined LOAD_AVE_TYPE && ! defined __VMS)) +# include +# endif + +/* Avoid static vars inside a function since in HPUX they dump as pure. */ + +# ifdef NeXT +static processor_set_t default_set; +static bool getloadavg_initialized; +# endif /* NeXT */ + +# ifdef UMAX +static unsigned int cpus = 0; +static unsigned int samples; +# endif /* UMAX */ + +# ifdef DGUX +static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ +# endif /* DGUX */ + +# if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE) +/* File descriptor open to /dev/kmem or VMS load ave driver. */ +static int channel; +/* True if channel is valid. */ +static bool getloadavg_initialized; +/* Offset in kmem to seek to read load average, or 0 means invalid. */ +static long offset; + +# if ! defined __VMS && ! defined sgi && ! (defined __linux__ || defined __ANDROID__) +static struct nlist name_list[2]; +# endif + +# ifdef SUNOS_5 +static kvm_t *kd; +# endif /* SUNOS_5 */ + +# endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */ + +/* Put the 1 minute, 5 minute and 15 minute load averages + into the first NELEM elements of LOADAVG. + Return the number written (never more than 3, but may be less than NELEM), + or -1 (setting errno) if an error occurred. */ + +int +getloadavg (double loadavg[], int nelem) +{ + int elem = 0; /* Return value. */ + +# ifdef NO_GET_LOAD_AVG +# define LDAV_DONE + errno = ENOSYS; + elem = -1; +# endif + +# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Solaris <= 2.6 */ +/* Use libkstat because we don't have to be root. */ +# define LDAV_DONE + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *kn; + int saved_errno; + + kc = kstat_open (); + if (kc == NULL) + return -1; + ksp = kstat_lookup (kc, "unix", 0, "system_misc"); + if (ksp == NULL) + return -1; + if (kstat_read (kc, ksp, 0) == -1) + return -1; + + + kn = kstat_data_lookup (ksp, "avenrun_1min"); + if (kn == NULL) + { + /* Return -1 if no load average information is available. */ + nelem = 0; + elem = -1; + } + + if (nelem >= 1) + loadavg[elem++] = (double) kn->value.ul / FSCALE; + + if (nelem >= 2) + { + kn = kstat_data_lookup (ksp, "avenrun_5min"); + if (kn != NULL) + { + loadavg[elem++] = (double) kn->value.ul / FSCALE; + + if (nelem >= 3) + { + kn = kstat_data_lookup (ksp, "avenrun_15min"); + if (kn != NULL) + loadavg[elem++] = (double) kn->value.ul / FSCALE; + } + } + } + + saved_errno = errno; + kstat_close (kc); + errno = saved_errno; +# endif /* HAVE_LIBKSTAT */ + +# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) + /* HP-UX */ +/* Use pstat_getdynamic() because we don't have to be root. */ +# define LDAV_DONE +# undef LOAD_AVE_TYPE + + struct pst_dynamic dyn_info; + if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0) + return -1; + if (nelem > 0) + loadavg[elem++] = dyn_info.psd_avg_1_min; + if (nelem > 1) + loadavg[elem++] = dyn_info.psd_avg_5_min; + if (nelem > 2) + loadavg[elem++] = dyn_info.psd_avg_15_min; + +# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ + +# if ! defined LDAV_DONE && defined HAVE_LIBPERFSTAT /* AIX */ +# define LDAV_DONE +# undef LOAD_AVE_TYPE +/* Use perfstat_cpu_total because we don't have to be root. */ + { + perfstat_cpu_total_t cpu_stats; + int result = perfstat_cpu_total (NULL, &cpu_stats, sizeof cpu_stats, 1); + if (result == -1) + return result; + loadavg[0] = cpu_stats.loadavg[0] / (double)(1 << SBITS); + loadavg[1] = cpu_stats.loadavg[1] / (double)(1 << SBITS); + loadavg[2] = cpu_stats.loadavg[2] / (double)(1 << SBITS); + elem = 3; + } +# endif + +# if !defined (LDAV_DONE) && (defined __linux__ || defined __ANDROID__ || defined __CYGWIN__) + /* Linux without glibc, Android, Cygwin */ +# define LDAV_DONE +# undef LOAD_AVE_TYPE + +# ifndef LINUX_LDAV_FILE +# define LINUX_LDAV_FILE "/proc/loadavg" +# endif + + char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")]; + char const *ptr = ldavgbuf; + int fd, count, saved_errno; + + fd = open (LINUX_LDAV_FILE, O_RDONLY | O_CLOEXEC); + if (fd == -1) + return -1; + count = read (fd, ldavgbuf, sizeof ldavgbuf - 1); + saved_errno = errno; + (void) close (fd); + errno = saved_errno; + if (count <= 0) + return -1; + ldavgbuf[count] = '\0'; + + for (elem = 0; elem < nelem; elem++) + { + double numerator = 0; + double denominator = 1; + + while (*ptr == ' ') + ptr++; + + /* Finish if this number is missing, and report an error if all + were missing. */ + if (! ('0' <= *ptr && *ptr <= '9')) + { + if (elem == 0) + { + errno = ENOTSUP; + return -1; + } + break; + } + + while ('0' <= *ptr && *ptr <= '9') + numerator = 10 * numerator + (*ptr++ - '0'); + + if (*ptr == '.') + for (ptr++; '0' <= *ptr && *ptr <= '9'; ptr++) + numerator = 10 * numerator + (*ptr - '0'), denominator *= 10; + + loadavg[elem] = numerator / denominator; + } + + return elem; + +# endif /* __linux__ || __ANDROID__ || __CYGWIN__ */ + +# if !defined (LDAV_DONE) && defined (__NetBSD__) /* NetBSD < 0.9 */ +# define LDAV_DONE +# undef LOAD_AVE_TYPE + +# ifndef NETBSD_LDAV_FILE +# define NETBSD_LDAV_FILE "/kern/loadavg" +# endif + + unsigned long int load_ave[3], scale; + int count; + char readbuf[4 * INT_BUFSIZE_BOUND (unsigned long int) + 1]; + int fd = open (NETBSD_LDAV_FILE, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return fd; + int nread = read (fd, readbuf, sizeof readbuf - 1); + int err = errno; + close (fd); + if (nread < 0) + { + errno = err; + return -1; + } + readbuf[nread] = '\0'; + count = sscanf (readbuf, "%lu %lu %lu %lu\n", + &load_ave[0], &load_ave[1], &load_ave[2], + &scale); + if (count != 4) + { + errno = ENOTSUP; + return -1; + } + + for (elem = 0; elem < nelem; elem++) + loadavg[elem] = (double) load_ave[elem] / (double) scale; + + return elem; + +# endif /* __NetBSD__ */ + +# if !defined (LDAV_DONE) && defined (NeXT) /* NeXTStep */ +# define LDAV_DONE + /* The NeXT code was adapted from iscreen 3.2. */ + + host_t host; + struct processor_set_basic_info info; + unsigned int info_count; + + /* We only know how to get the 1-minute average for this system, + so even if the caller asks for more than 1, we only return 1. */ + + if (!getloadavg_initialized) + { + if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) + getloadavg_initialized = true; + } + + if (getloadavg_initialized) + { + info_count = PROCESSOR_SET_BASIC_INFO_COUNT; + if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, + (processor_set_info_t) &info, &info_count) + != KERN_SUCCESS) + getloadavg_initialized = false; + else + { + if (nelem > 0) + loadavg[elem++] = (double) info.load_average / LOAD_SCALE; + } + } + + if (!getloadavg_initialized) + { + errno = ENOTSUP; + return -1; + } +# endif /* NeXT */ + +# if !defined (LDAV_DONE) && defined (UMAX) +# define LDAV_DONE +/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not + have a /dev/kmem. Information about the workings of the running kernel + can be gathered with inq_stats system calls. + We only know how to get the 1-minute average for this system. */ + + struct proc_summary proc_sum_data; + struct stat_descr proc_info; + double load; + register unsigned int i, j; + + if (cpus == 0) + { + register unsigned int c, i; + struct cpu_config conf; + struct stat_descr desc; + + desc.sd_next = 0; + desc.sd_subsys = SUBSYS_CPU; + desc.sd_type = CPUTYPE_CONFIG; + desc.sd_addr = (char *) &conf; + desc.sd_size = sizeof conf; + + if (inq_stats (1, &desc)) + return -1; + + c = 0; + for (i = 0; i < conf.config_maxclass; ++i) + { + struct class_stats stats; + memset (&stats, 0, sizeof stats); + + desc.sd_type = CPUTYPE_CLASS; + desc.sd_objid = i; + desc.sd_addr = (char *) &stats; + desc.sd_size = sizeof stats; + + if (inq_stats (1, &desc)) + return -1; + + c += stats.class_numcpus; + } + cpus = c; + samples = cpus < 2 ? 3 : (2 * cpus / 3); + } + + proc_info.sd_next = 0; + proc_info.sd_subsys = SUBSYS_PROC; + proc_info.sd_type = PROCTYPE_SUMMARY; + proc_info.sd_addr = (char *) &proc_sum_data; + proc_info.sd_size = sizeof (struct proc_summary); + proc_info.sd_sizeused = 0; + + if (inq_stats (1, &proc_info) != 0) + return -1; + + load = proc_sum_data.ps_nrunnable; + j = 0; + for (i = samples - 1; i > 0; --i) + { + load += proc_sum_data.ps_nrun[j]; + if (j++ == PS_NRUNSIZE) + j = 0; + } + + if (nelem > 0) + loadavg[elem++] = load / samples / cpus; +# endif /* UMAX */ + +# if !defined (LDAV_DONE) && defined (DGUX) +# define LDAV_DONE + /* This call can return -1 for an error, but with good args + it's not supposed to fail. The first argument is for no + apparent reason of type 'long int *'. */ + dg_sys_info ((long int *) &load_info, + DG_SYS_INFO_LOAD_INFO_TYPE, + DG_SYS_INFO_LOAD_VERSION_0); + + if (nelem > 0) + loadavg[elem++] = load_info.one_minute; + if (nelem > 1) + loadavg[elem++] = load_info.five_minute; + if (nelem > 2) + loadavg[elem++] = load_info.fifteen_minute; +# endif /* DGUX */ + +# if !defined (LDAV_DONE) && defined (apollo) +# define LDAV_DONE +/* Apollo code from lisch@mentorg.com (Ray Lischner). + + This system call is not documented. The load average is obtained as + three long integers, for the load average over the past minute, + five minutes, and fifteen minutes. Each value is a scaled integer, + with 16 bits of integer part and 16 bits of fraction part. + + I'm not sure which operating system first supported this system call, + but I know that SR10.2 supports it. */ + + extern void proc1_$get_loadav (); + unsigned long load_ave[3]; + + proc1_$get_loadav (load_ave); + + if (nelem > 0) + loadavg[elem++] = load_ave[0] / 65536.0; + if (nelem > 1) + loadavg[elem++] = load_ave[1] / 65536.0; + if (nelem > 2) + loadavg[elem++] = load_ave[2] / 65536.0; +# endif /* apollo */ + +# if !defined (LDAV_DONE) && defined (OSF_MIPS) +# define LDAV_DONE + + struct tbl_loadavg load_ave; + table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); + loadavg[elem++] + = (load_ave.tl_lscale == 0 + ? load_ave.tl_avenrun.d[0] + : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale)); +# endif /* OSF_MIPS */ + +# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32)) + /* DJGPP */ +# define LDAV_DONE + + /* A faithful emulation is going to have to be saved for a rainy day. */ + for ( ; elem < nelem; elem++) + { + loadavg[elem] = 0.0; + } +# endif /* __MSDOS__ || WINDOWS32 */ + +# if !defined (LDAV_DONE) && defined (OSF_ALPHA) /* OSF/1 */ +# define LDAV_DONE + + struct tbl_loadavg load_ave; + table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); + for (elem = 0; elem < nelem; elem++) + loadavg[elem] + = (load_ave.tl_lscale == 0 + ? load_ave.tl_avenrun.d[elem] + : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale)); +# endif /* OSF_ALPHA */ + +# if ! defined LDAV_DONE && defined __VMS /* VMS */ + /* VMS specific code -- read from the Load Ave driver. */ + + LOAD_AVE_TYPE load_ave[3]; + static bool getloadavg_initialized; +# ifdef eunice + struct + { + int dsc$w_length; + char *dsc$a_pointer; + } descriptor; +# endif + + /* Ensure that there is a channel open to the load ave device. */ + if (!getloadavg_initialized) + { + /* Attempt to open the channel. */ +# ifdef eunice + descriptor.dsc$w_length = 18; + descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE"; +# else + $DESCRIPTOR (descriptor, "LAV0:"); +# endif + if (sys$assign (&descriptor, &channel, 0, 0) & 1) + getloadavg_initialized = true; + } + + /* Read the load average vector. */ + if (getloadavg_initialized + && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0, + load_ave, 12, 0, 0, 0, 0) & 1)) + { + sys$dassgn (channel); + getloadavg_initialized = false; + } + + if (!getloadavg_initialized) + { + errno = ENOTSUP; + return -1; + } +# endif /* ! defined LDAV_DONE && defined __VMS */ + +# if ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS + /* IRIX, other old systems */ + + /* UNIX-specific code -- read the average from /dev/kmem. */ + +# define LDAV_PRIVILEGED /* This code requires special installation. */ + + LOAD_AVE_TYPE load_ave[3]; + + /* Get the address of LDAV_SYMBOL. */ + if (offset == 0) + { +# ifndef sgi +# if ! defined NLIST_STRUCT || ! defined N_NAME_POINTER + strcpy (name_list[0].n_name, LDAV_SYMBOL); + strcpy (name_list[1].n_name, ""); +# else /* NLIST_STRUCT */ +# ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME + name_list[0].n_un.n_name = LDAV_SYMBOL; + name_list[1].n_un.n_name = 0; +# else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ + name_list[0].n_name = LDAV_SYMBOL; + name_list[1].n_name = 0; +# endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ +# endif /* NLIST_STRUCT */ + +# ifndef SUNOS_5 + if ( +# if !defined (_AIX) + nlist (KERNEL_FILE, name_list) +# else /* _AIX */ + knlist (name_list, 1, sizeof (name_list[0])) +# endif + >= 0) + /* Omit "&& name_list[0].n_type != 0 " -- it breaks on Sun386i. */ + { +# ifdef FIXUP_KERNEL_SYMBOL_ADDR + FIXUP_KERNEL_SYMBOL_ADDR (name_list); +# endif + offset = name_list[0].n_value; + } +# endif /* !SUNOS_5 */ +# else /* sgi */ + ptrdiff_t ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); + if (ldav_off != -1) + offset = (long int) ldav_off & 0x7fffffff; +# endif /* sgi */ + } + + /* Make sure we have /dev/kmem open. */ + if (!getloadavg_initialized) + { +# ifndef SUNOS_5 + int fd = open ("/dev/kmem", O_RDONLY | O_CLOEXEC); + if (0 <= fd) + { + channel = fd; + getloadavg_initialized = true; + } +# else /* SUNOS_5 */ + /* We pass 0 for the kernel, corefile, and swapfile names + to use the currently running kernel. */ + kd = kvm_open (0, 0, 0, O_RDONLY, 0); + if (kd != NULL) + { + /* nlist the currently running kernel. */ + kvm_nlist (kd, name_list); + offset = name_list[0].n_value; + getloadavg_initialized = true; + } +# endif /* SUNOS_5 */ + } + + /* If we can, get the load average values. */ + if (offset && getloadavg_initialized) + { + /* Try to read the load. */ +# ifndef SUNOS_5 + if (lseek (channel, offset, 0) == -1L + || read (channel, (char *) load_ave, sizeof (load_ave)) + != sizeof (load_ave)) + { + close (channel); + getloadavg_initialized = false; + } +# else /* SUNOS_5 */ + if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) + != sizeof (load_ave)) + { + kvm_close (kd); + getloadavg_initialized = false; + } +# endif /* SUNOS_5 */ + } + + if (offset == 0 || !getloadavg_initialized) + { + errno = ENOTSUP; + return -1; + } +# endif /* ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS */ + +# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */ + if (nelem > 0) + loadavg[elem++] = LDAV_CVT (load_ave[0]); + if (nelem > 1) + loadavg[elem++] = LDAV_CVT (load_ave[1]); + if (nelem > 2) + loadavg[elem++] = LDAV_CVT (load_ave[2]); + +# define LDAV_DONE +# endif /* !LDAV_DONE && LOAD_AVE_TYPE */ + +# if !defined LDAV_DONE + errno = ENOSYS; + elem = -1; +# endif + return elem; +} diff --git a/cross/lib/getopt-cdefs.in.h b/cross/lib/getopt-cdefs.in.h new file mode 100644 index 00000000000..e76c78cb212 --- /dev/null +++ b/cross/lib/getopt-cdefs.in.h @@ -0,0 +1,66 @@ +/* getopt-on-non-glibc compatibility macros. + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GETOPT_CDEFS_H +#define _GETOPT_CDEFS_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* getopt-core.h and getopt-ext.h are shared with GNU libc, and expect + a number of the internal macros supplied to GNU libc's headers by + sys/cdefs.h. Provide fallback definitions for all of them. */ +#if @HAVE_SYS_CDEFS_H@ +# include +#endif + +#ifndef __BEGIN_DECLS +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# else +# define __BEGIN_DECLS /* nothing */ +# endif +#endif +#ifndef __END_DECLS +# ifdef __cplusplus +# define __END_DECLS } +# else +# define __END_DECLS /* nothing */ +# endif +#endif + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_VERSION__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __THROW +# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#endif /* _GETOPT_CDEFS_H */ diff --git a/cross/lib/getopt-core.h b/cross/lib/getopt-core.h new file mode 100644 index 00000000000..c5dd49363f0 --- /dev/null +++ b/cross/lib/getopt-core.h @@ -0,0 +1,96 @@ +/* Declarations for getopt (basic, portable features only). + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _GETOPT_CORE_H +#define _GETOPT_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. Unlike most bits headers, it does not have + a protective #error, because the guard macro for getopt.h in + gnulib is not fixed. */ + +__BEGIN_DECLS + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message 'getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, 'optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in 'optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU 'getopt'. + + The argument '--' causes premature termination of argument + scanning, explicitly telling 'getopt' that there are no more + options. + + If OPTS begins with '-', then non-option arguments are treated as + arguments to the option '\1'. This behavior is specific to the GNU + 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in + the environment, then do not permute arguments. + + For standards compliance, the 'argv' argument has the type + char *const *, but this is inaccurate; if argument permutation is + enabled, the argv array (not the strings it points to) must be + writable. */ + +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_CORE_H */ diff --git a/cross/lib/getopt-ext.h b/cross/lib/getopt-ext.h new file mode 100644 index 00000000000..d37c29328b2 --- /dev/null +++ b/cross/lib/getopt-ext.h @@ -0,0 +1,77 @@ +/* Declarations for getopt (GNU extensions). + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _GETOPT_EXT_H +#define _GETOPT_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + Unlike most bits headers, it does not have a protective #error, + because the guard macro for getopt.h in gnulib is not fixed. */ + +__BEGIN_DECLS + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of 'struct option' terminated by an element containing a name which is + zero. + + The field 'has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field 'flag' is not NULL, it points to a variable that is set + to the value given in the field 'val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an 'int' to + a compiled-in constant, such as set a value from 'optarg', set the + option's 'flag' field to zero and its 'val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero 'flag' field, 'getopt' + returns the contents of the 'val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the 'has_arg' field of 'struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); +extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW _GL_ARG_NONNULL ((2, 3)); + +__END_DECLS + +#endif /* _GETOPT_EXT_H */ diff --git a/cross/lib/getopt-pfx-core.h b/cross/lib/getopt-pfx-core.h new file mode 100644 index 00000000000..3a2fde5ad4f --- /dev/null +++ b/cross/lib/getopt-pfx-core.h @@ -0,0 +1,66 @@ +/* getopt (basic, portable features) gnulib wrapper header. + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GETOPT_PFX_CORE_H +#define _GETOPT_PFX_CORE_H 1 + +/* This header should not be used directly; include getopt.h or + unistd.h instead. It does not have a protective #error, because + the guard macro for getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt +# undef optarg +# undef opterr +# undef optind +# undef optopt +# define getopt __GETOPT_ID (getopt) +# define optarg __GETOPT_ID (optarg) +# define opterr __GETOPT_ID (opterr) +# define optind __GETOPT_ID (optind) +# define optopt __GETOPT_ID (optopt) + +/* Work around a a problem on macOS, which declares getopt with a + trailing __DARWIN_ALIAS(getopt) that would expand to something like + __asm("_" "rpl_getopt" "$UNIX2003") were it not for the following + hack to suppress the macOS declaration . */ +# ifdef __APPLE__ +# define _GETOPT +# endif + +/* The system's getopt.h may have already included getopt-core.h to + declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that + getopt-core.h declares them with prefixes. */ +# undef _GETOPT_CORE_H +#endif + +#include + +#endif /* _GETOPT_PFX_CORE_H */ diff --git a/cross/lib/getopt-pfx-ext.h b/cross/lib/getopt-pfx-ext.h new file mode 100644 index 00000000000..8578d72530a --- /dev/null +++ b/cross/lib/getopt-pfx-ext.h @@ -0,0 +1,70 @@ +/* getopt (GNU extensions) gnulib wrapper header. + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GETOPT_PFX_EXT_H +#define _GETOPT_PFX_EXT_H 1 + +/* This header should not be used directly; include getopt.h instead. + It does not have a protective #error, because the guard macro for + getopt.h in gnulib is not fixed. */ + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. Systematically + rename identifiers so that they do not collide with the system + functions and variables. Renaming avoids problems with some + compilers and linkers. */ +#ifdef __GETOPT_PREFIX +# ifndef __GETOPT_ID +# define __GETOPT_CONCAT(x, y) x ## y +# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) +# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) +# endif +# undef getopt_long +# undef getopt_long_only +# undef option +# undef _getopt_internal +# define getopt_long __GETOPT_ID (getopt_long) +# define getopt_long_only __GETOPT_ID (getopt_long_only) +# define option __GETOPT_ID (option) +# define _getopt_internal __GETOPT_ID (getopt_internal) + +/* The system's getopt.h may have already included getopt-ext.h to + declare the unprefixed identifiers. Undef _GETOPT_EXT_H so that + getopt-ext.h declares them with prefixes. */ +# undef _GETOPT_EXT_H +#endif + +/* Standalone applications get correct prototypes for getopt_long and + getopt_long_only; they declare "char **argv". For backward + compatibility with old applications, if __GETOPT_PREFIX is not + defined, we supply GNU-libc-compatible, but incorrect, prototypes + using "char *const *argv". (GNU libc is stuck with the incorrect + prototypes, as they are baked into older versions of LSB.) */ +#ifndef __getopt_argv_const +# if defined __GETOPT_PREFIX +# define __getopt_argv_const /* empty */ +# else +# define __getopt_argv_const const +# endif +#endif + +#include + +#endif /* _GETOPT_PFX_EXT_H */ diff --git a/cross/lib/getopt.c b/cross/lib/getopt.c new file mode 100644 index 00000000000..1e2441c4afe --- /dev/null +++ b/cross/lib/getopt.c @@ -0,0 +1,811 @@ +/* Getopt for GNU. + Copyright (C) 1987-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include "getopt.h" + +#include +#include +#include +#include + +#ifdef _LIBC +/* When used as part of glibc, error printing must be done differently + for standards compliance. getopt is not a cancellation point, so + it must not call functions that are, and it is specified by an + older standard than stdio locking, so it must not refer to + functions in the "user namespace" related to stdio locking. + Finally, it must use glibc's internal message translation so that + the messages are looked up in the proper text domain. */ +# include +# define fprintf __fxprintf_nocancel +# define flockfile(fp) _IO_flockfile (fp) +# define funlockfile(fp) _IO_funlockfile (fp) +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +/* When used standalone, flockfile and funlockfile might not be + available. */ +# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \ + || (defined _WIN32 && ! defined __CYGWIN__)) +# define flockfile(fp) /* nop */ +# define funlockfile(fp) /* nop */ +# endif +/* When used standalone, do not attempt to use alloca. */ +# define __libc_use_alloca(size) 0 +# undef alloca +# define alloca(size) (abort (), (void *)0) +#endif + +/* This implementation of 'getopt' has three modes for handling + options interspersed with non-option arguments. It can stop + scanning for options at the first non-option argument encountered, + as POSIX specifies. It can continue scanning for options after the + first non-option argument, but permute 'argv' as it goes so that, + after 'getopt' is done, all the options precede all the non-option + arguments and 'optind' points to the first non-option argument. + Or, it can report non-option arguments as if they were arguments to + the option character '\x01'. + + The default behavior of 'getopt_long' is to permute the argument list. + When this implementation is used standalone, the default behavior of + 'getopt' is to stop at the first non-option argument, but when it is + used as part of GNU libc it also permutes the argument list. In both + cases, setting the environment variable POSIXLY_CORRECT to any value + disables permutation. + + If the first character of the OPTSTRING argument to 'getopt' or + 'getopt_long' is '+', both functions will stop at the first + non-option argument. If it is '-', both functions will report + non-option arguments as arguments to the option character '\x01'. */ + +#include "getopt_int.h" + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + 'first_nonopt' and 'last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Process the argument starting with d->__nextchar as a long option. + d->optind should *not* have been advanced over this argument. + + If the value returned is -1, it was not actually a long option, the + state is unchanged, and the argument should be processed as a set + of short options (this can only happen when long_only is true). + Otherwise, the option (and its argument, if any) have been consumed + and the return value is the value to return from _getopt_internal_r. */ +static int +process_long_option (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, + int print_errors, const char *prefix) +{ + char *nameend; + size_t namelen; + const struct option *p; + const struct option *pfound = NULL; + int n_options; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + namelen = nameend - d->__nextchar; + + /* First look for an exact match, counting the options as a side + effect. */ + for (p = longopts, n_options = 0; p->name; p++, n_options++) + if (!strncmp (p->name, d->__nextchar, namelen) + && namelen == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + option_index = n_options; + break; + } + + if (pfound == NULL) + { + /* Didn't find an exact match, so look for abbreviations. */ + unsigned char *ambig_set = NULL; + int ambig_malloced = 0; + int ambig_fallback = 0; + int indfound = -1; + + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, namelen)) + { + if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + { + /* Second or later nonexact match found. */ + if (!ambig_fallback) + { + if (!print_errors) + /* Don't waste effort tracking the ambig set if + we're not going to print it anyway. */ + ambig_fallback = 1; + else if (!ambig_set) + { + if (__libc_use_alloca (n_options)) + ambig_set = alloca (n_options); + else if ((ambig_set = malloc (n_options)) == NULL) + /* Fall back to simpler error message. */ + ambig_fallback = 1; + else + ambig_malloced = 1; + + if (ambig_set) + { + memset (ambig_set, 0, n_options); + ambig_set[indfound] = 1; + } + } + if (ambig_set) + ambig_set[option_index] = 1; + } + } + } + + if (ambig_set || ambig_fallback) + { + if (print_errors) + { + if (ambig_fallback) + fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"), + argv[0], prefix, d->__nextchar); + else + { + flockfile (stderr); + fprintf (stderr, + _("%s: option '%s%s' is ambiguous; possibilities:"), + argv[0], prefix, d->__nextchar); + + for (option_index = 0; option_index < n_options; option_index++) + if (ambig_set[option_index]) + fprintf (stderr, " '%s%s'", + prefix, longopts[option_index].name); + + /* This must use 'fprintf' even though it's only + printing a single character, so that it goes through + __fxprintf_nocancel when compiled as part of glibc. */ + fprintf (stderr, "\n"); + funlockfile (stderr); + } + } + if (ambig_malloced) + free (ambig_set); + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + option_index = indfound; + } + + if (pfound == NULL) + { + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short option, + then it's an error. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + fprintf (stderr, _("%s: unrecognized option '%s%s'\n"), + argv[0], prefix, d->__nextchar); + + d->__nextchar = NULL; + d->optind++; + d->optopt = 0; + return '?'; + } + + /* Otherwise interpret it as a short option. */ + return -1; + } + + /* We have found a matching long option. Consume it. */ + d->optind++; + d->__nextchar = NULL; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' doesn't allow an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + fprintf (stderr, + _("%s: option '%s%s' requires an argument\n"), + argv[0], prefix, pfound->name); + + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; +} + +/* Initialize internal data upon the first call to getopt. */ + +static const char * +_getopt_initialize (_GL_UNUSED int argc, + _GL_UNUSED char **argv, const char *optstring, + struct _getopt_data *d, int posixly_correct) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + if (d->optind == 0) + d->optind = 1; + + d->__first_nonopt = d->__last_nonopt = d->optind; + d->__nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct || !!getenv ("POSIXLY_CORRECT")) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + + d->__initialized = 1; + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If 'getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set 'opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in 'optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in 'optarg', otherwise 'optarg' is set to zero. + + If OPTSTRING starts with '-' or '+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with '--' instead of '-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of 'struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal_r (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d, int posixly_correct) +{ + int print_errors = d->opterr; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct); + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + + if (optstring[0] == ':') + print_errors = 0; + + /* Test whether ARGV[optind] points to a non-option argument. */ +#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element '--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange (argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Check whether it might be a long option. */ + if (longopts) + { + if (argv[d->optind][1] == '-') + { + /* "--foo" is always a long option. The special option + "--" was handled above. */ + d->__nextchar = argv[d->optind] + 2; + return process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "--"); + } + + /* If long_only and the ARGV-element has the form "-f", + where f is a valid short option, don't consider it an + abbreviated form of a long option that starts with f. + Otherwise there would be no way to give the -f short + option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an + abbreviation of the long option, just like "--fu", and + not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + if (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))) + { + int code; + d->__nextchar = argv[d->optind] + 1; + code = process_long_option (argc, argv, optstring, longopts, + longind, long_only, d, + print_errors, "-"); + if (code != -1) + return code; + } + } + + /* It is not a long option. Skip the initial punctuation. */ + d->__nextchar = argv[d->optind] + 1; + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + const char *temp = strchr (optstring, c); + + /* Increment 'optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':' || c == ';') + { + if (print_errors) + fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); + d->optopt = c; + return '?'; + } + + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL) + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + d->optarg = d->__nextchar; + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + d->optarg = argv[d->optind]; + + d->__nextchar = d->optarg; + d->optarg = NULL; + return process_long_option (argc, argv, optstring, longopts, longind, + 0 /* long_only */, d, print_errors, "-W "); + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + fprintf (stderr, + _("%s: option requires an argument -- '%c'\n"), + argv[0], c); + + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented 'optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, int long_only, + int posixly_correct) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data, + posixly_correct); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt. + Standalone applications just get a POSIX-compliant getopt. + POSIX and LSB both require these functions to take 'char *const *argv' + even though this is incorrect (because of the permutation). */ +#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \ + int \ + NAME (int argc, char *const *argv, const char *optstring) \ + { \ + return _getopt_internal (argc, (char **)argv, optstring, \ + 0, 0, 0, POSIXLY_CORRECT); \ + } + +#ifdef _LIBC +GETOPT_ENTRY(getopt, 0) +GETOPT_ENTRY(__posix_getopt, 1) +#else +GETOPT_ENTRY(getopt, 1) +#endif + + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of 'getopt'. */ + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/cross/lib/getopt.in.h b/cross/lib/getopt.in.h new file mode 100644 index 00000000000..0867d365f47 --- /dev/null +++ b/cross/lib/getopt.in.h @@ -0,0 +1,61 @@ +/* Declarations for getopt. + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of gnulib. + Unlike most of the getopt implementation, it is NOT shared + with the GNU C Library, which supplies a different version of + this file. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_GETOPT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* The include_next requires a split double-inclusion guard. We must + also inform the replacement unistd.h to not recursively use + ; our definitions will be present soon enough. */ +#if @HAVE_GETOPT_H@ +# define _GL_SYSTEM_GETOPT +# @INCLUDE_NEXT@ @NEXT_GETOPT_H@ +# undef _GL_SYSTEM_GETOPT +#endif + +#define _@GUARD_PREFIX@_GETOPT_H 1 + +/* Standalone applications should #define __GETOPT_PREFIX to an + identifier that prefixes the external functions and variables + defined in getopt-core.h and getopt-ext.h. When this happens, + include the headers that might declare getopt so that they will not + cause confusion if included after this file (if the system had + , we have already included it). */ +#if defined __GETOPT_PREFIX +# if !@HAVE_GETOPT_H@ +# define __need_system_stdlib_h +# include +# undef __need_system_stdlib_h +# include +# include +# endif +#endif + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +#include +#include +#include + +#endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/cross/lib/getopt1.c b/cross/lib/getopt1.c new file mode 100644 index 00000000000..49323aa8ed1 --- /dev/null +++ b/cross/lib/getopt1.c @@ -0,0 +1,159 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include "getopt.h" +#include "getopt_int.h" + +int +getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 0, 0); +} + +int +_getopt_long_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, d, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *__getopt_argv_const *argv, + const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 1, 0); +} + +int +_getopt_long_only_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, d, 0); +} + + +#ifdef TEST + +#include +#include + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static const struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case 'd': + printf ("option d with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/cross/lib/getopt_int.h b/cross/lib/getopt_int.h new file mode 100644 index 00000000000..4d9e24beebc --- /dev/null +++ b/cross/lib/getopt_int.h @@ -0,0 +1,118 @@ +/* Internal declarations for getopt. + Copyright (C) 1989-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library and is also part of gnulib. + Patches to this file should be submitted to both projects. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _GETOPT_INT_H +#define _GETOPT_INT_H 1 + +#include + +extern int _getopt_internal (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, int __posixly_correct); + + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* Describe how to deal with options that follow non-option ARGV-elements. + + REQUIRE_ORDER means don't recognize them as options; stop option + processing when the first non-option is seen. This is what POSIX + specifies should happen. + + PERMUTE means permute the contents of ARGV as we scan, so that + eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written + to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. + + The special argument '--' forces an end of option-scanning regardless + of the value of 'ordering'. In the case of RETURN_IN_ORDER, only + '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + +/* Data type for reentrant functions. */ +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + int optopt; + char *optarg; + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + int __initialized; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + /* See __ord above. */ + enum __ord __ordering; + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. 'first_nonopt' is the index in ARGV of the first + of them; 'last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +extern int _getopt_internal_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data, + int __posixly_correct); + +extern int _getopt_long_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); + +extern int _getopt_long_only_r (int ___argc, char **___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); + +#endif /* getopt_int.h */ diff --git a/cross/lib/getrandom.c b/cross/lib/getrandom.c new file mode 100644 index 00000000000..19bb3429baf --- /dev/null +++ b/cross/lib/getrandom.c @@ -0,0 +1,190 @@ +/* Obtain a series of random bytes. + + Copyright 2020-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#include + +#include +#include +#include + +#if defined _WIN32 && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# if HAVE_BCRYPT_H +# include +# else +# define NTSTATUS LONG +typedef void * BCRYPT_ALG_HANDLE; +# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 +# if HAVE_LIB_BCRYPT +extern NTSTATUS WINAPI BCryptGenRandom (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG); +# endif +# endif +# if !HAVE_LIB_BCRYPT +# include +# ifndef CRYPT_VERIFY_CONTEXT +# define CRYPT_VERIFY_CONTEXT 0xF0000000 +# endif +# endif +#endif + +#include "minmax.h" + +#if defined _WIN32 && ! defined __CYGWIN__ + +/* Don't assume that UNICODE is not defined. */ +# undef LoadLibrary +# define LoadLibrary LoadLibraryA +# undef CryptAcquireContext +# define CryptAcquireContext CryptAcquireContextA + +# if !HAVE_LIB_BCRYPT + +/* Avoid warnings from gcc -Wcast-function-type. */ +# define GetProcAddress \ + (void *) GetProcAddress + +/* BCryptGenRandom with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag works only + starting with Windows 7. */ +typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG); +static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL; +static BOOL initialized = FALSE; + +static void +initialize (void) +{ + HMODULE bcrypt = LoadLibrary ("bcrypt.dll"); + if (bcrypt != NULL) + { + BCryptGenRandomFunc = + (BCryptGenRandomFuncType) GetProcAddress (bcrypt, "BCryptGenRandom"); + } + initialized = TRUE; +} + +# else + +# define BCryptGenRandomFunc BCryptGenRandom + +# endif + +#else +/* These devices exist on all platforms except native Windows. */ + +/* Name of a device through which the kernel returns high quality random + numbers, from an entropy pool. When the pool is empty, the call blocks + until entropy sources have added enough bits of entropy. */ +# ifndef NAME_OF_RANDOM_DEVICE +# define NAME_OF_RANDOM_DEVICE "/dev/random" +# endif + +/* Name of a device through which the kernel returns random or pseudo-random + numbers. It uses an entropy pool, but, in order to avoid blocking, adds + bits generated by a pseudo-random number generator, as needed. */ +# ifndef NAME_OF_NONCE_DEVICE +# define NAME_OF_NONCE_DEVICE "/dev/urandom" +# endif + +#endif + +/* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS. + Return the number of bytes written (> 0). + Upon error, return -1 and set errno. */ +ssize_t +getrandom (void *buffer, size_t length, unsigned int flags) +#undef getrandom +{ +#if defined _WIN32 && ! defined __CYGWIN__ + /* BCryptGenRandom, defined in + + with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag + works in Windows 7 and newer. */ + static int bcrypt_not_working /* = 0 */; + if (!bcrypt_not_working) + { +# if !HAVE_LIB_BCRYPT + if (!initialized) + initialize (); +# endif + if (BCryptGenRandomFunc != NULL + && BCryptGenRandomFunc (NULL, buffer, length, + BCRYPT_USE_SYSTEM_PREFERRED_RNG) + == 0 /*STATUS_SUCCESS*/) + return length; + bcrypt_not_working = 1; + } +# if !HAVE_LIB_BCRYPT + /* CryptGenRandom, defined in + + works in older releases as well, but is now deprecated. + CryptAcquireContext, defined in + */ + { + static int crypt_initialized /* = 0 */; + static HCRYPTPROV provider; + if (!crypt_initialized) + { + if (CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFY_CONTEXT)) + crypt_initialized = 1; + else + crypt_initialized = -1; + } + if (crypt_initialized >= 0) + { + if (!CryptGenRandom (provider, length, buffer)) + { + errno = EIO; + return -1; + } + return length; + } + } +# endif + errno = ENOSYS; + return -1; +#elif HAVE_GETRANDOM + return getrandom (buffer, length, flags); +#else + static int randfd[2] = { -1, -1 }; + bool devrandom = (flags & GRND_RANDOM) != 0; + int fd = randfd[devrandom]; + + if (fd < 0) + { + static char const randdevice[][MAX (sizeof NAME_OF_NONCE_DEVICE, + sizeof NAME_OF_RANDOM_DEVICE)] + = { NAME_OF_NONCE_DEVICE, NAME_OF_RANDOM_DEVICE }; + int oflags = (O_RDONLY + O_CLOEXEC + + (flags & GRND_NONBLOCK ? O_NONBLOCK : 0)); + fd = open (randdevice[devrandom], oflags); + if (fd < 0) + { + if (errno == ENOENT || errno == ENOTDIR) + errno = ENOSYS; + return -1; + } + randfd[devrandom] = fd; + } + + return read (fd, buffer, length); +#endif +} diff --git a/cross/lib/gettext.h b/cross/lib/gettext.h new file mode 100644 index 00000000000..d0462c47e17 --- /dev/null +++ b/cross/lib/gettext.h @@ -0,0 +1,300 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option + or through "#define ENABLE NLS 0" before including this file. */ +#if defined ENABLE_NLS && ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by + the gettext() and ngettext() macros. This is an alternative to calling + textdomain(), and is useful for libraries. */ +# ifdef DEFAULT_TEXT_DOMAIN +# undef gettext +# define gettext(Msgid) \ + dgettext (DEFAULT_TEXT_DOMAIN, Msgid) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) +# endif + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Many header files from the libstdc++ coming with g++ 3.3 or newer include + , which chokes if dcgettext is defined as a macro. So include + it now, to make later inclusions of a NOP. */ +#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) +# include +# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H +# include +# endif +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# undef ngettext +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 \ + ? ((void) (Msgid2), (const char *) (Msgid1)) \ + : ((void) (Msgid1), (const char *) (Msgid2))) +# undef dngettext +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) +# undef dcngettext +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) +# undef textdomain +# define textdomain(Domainname) ((const char *) (Domainname)) +# undef bindtextdomain +# define bindtextdomain(Domainname, Dirname) \ + ((void) (Domainname), (const char *) (Dirname)) +# undef bind_textdomain_codeset +# define bind_textdomain_codeset(Domainname, Codeset) \ + ((void) (Domainname), (const char *) (Codeset)) + +#endif + +/* Prefer gnulib's setlocale override over libintl's setlocale override. */ +#ifdef GNULIB_defined_setlocale +# undef setlocale +# define setlocale rpl_setlocale +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +/* The separator between msgctxt and msgid in a .mo file. */ +#define GETTEXT_CONTEXT_GLUE "\004" + +/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a + MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be + short and rarely need to change. + The letter 'p' stands for 'particular' or 'special'. */ +#ifdef DEFAULT_TEXT_DOMAIN +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#else +# define pgettext(Msgctxt, Msgid) \ + pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#endif +#define dpgettext(Domainname, Msgctxt, Msgid) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) +#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ + pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) +#ifdef DEFAULT_TEXT_DOMAIN +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#else +# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#endif +#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ + npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) + +#if defined __GNUC__ || defined __clang__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +pgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + int category) +{ + const char *translation = dcgettext (domain, msg_ctxt_id, category); + if (translation == msg_ctxt_id) + return msgid; + else + return translation; +} + +#if defined __GNUC__ || defined __clang__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +npgettext_aux (const char *domain, + const char *msg_ctxt_id, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + const char *translation = + dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + if (translation == msg_ctxt_id || translation == msgid_plural) + return (n == 1 ? msgid : msgid_plural); + else + return translation; +} + +/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID + can be arbitrary expressions. But for string literals these macros are + less efficient than those above. */ + +#include + +/* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported. + This relates to the -Wvla and -Wvla-larger-than warnings, enabled in + the default GCC many warnings set. This allows programs to disable use + of VLAs, which may be unintended, or may be awkward to support portably, + or may have security implications due to non-deterministic stack usage. */ + +#if (!defined GNULIB_NO_VLA \ + && defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ + && !defined __STDC_NO_VLA__) +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 +#else +# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 +#endif + +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS +#include +#endif + +#define pgettext_expr(Msgctxt, Msgid) \ + dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) +#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ + dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) + +#if defined __GNUC__ || defined __clang__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcgettext (domain, msg_ctxt_id, category); + found_translation = (translation != msg_ctxt_id); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return msgid; +} + +#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) +#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ + dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) + +#if defined __GNUC__ || defined __clang__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static const char * +dcnpgettext_expr (const char *domain, + const char *msgctxt, const char *msgid, + const char *msgid_plural, unsigned long int n, + int category) +{ + size_t msgctxt_len = strlen (msgctxt) + 1; + size_t msgid_len = strlen (msgid) + 1; + const char *translation; +#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + char msg_ctxt_id[msgctxt_len + msgid_len]; +#else + char buf[1024]; + char *msg_ctxt_id = + (msgctxt_len + msgid_len <= sizeof (buf) + ? buf + : (char *) malloc (msgctxt_len + msgid_len)); + if (msg_ctxt_id != NULL) +#endif + { + int found_translation; + memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); + msg_ctxt_id[msgctxt_len - 1] = '\004'; + memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); + translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); + found_translation = !(translation == msg_ctxt_id || translation == msgid_plural); +#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS + if (msg_ctxt_id != buf) + free (msg_ctxt_id); +#endif + if (found_translation) + return translation; + } + return (n == 1 ? msgid : msgid_plural); +} + +#endif /* _LIBGETTEXT_H */ diff --git a/cross/lib/gettime.c b/cross/lib/gettime.c new file mode 100644 index 00000000000..f86cc4efbff --- /dev/null +++ b/cross/lib/gettime.c @@ -0,0 +1,51 @@ +/* gettime -- get the system clock + + Copyright (C) 2002, 2004-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#include "timespec.h" + +#include + +/* Get the system time into *TS. */ + +void +gettime (struct timespec *ts) +{ +#if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME + clock_gettime (CLOCK_REALTIME, ts); +#elif defined HAVE_TIMESPEC_GET + timespec_get (ts, TIME_UTC); +#else + struct timeval tv; + gettimeofday (&tv, NULL); + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000; +#endif +} + +/* Return the current system time as a struct timespec. */ + +struct timespec +current_timespec (void) +{ + struct timespec ts; + gettime (&ts); + return ts; +} diff --git a/cross/lib/gettimeofday.c b/cross/lib/gettimeofday.c new file mode 100644 index 00000000000..d896ec132b9 --- /dev/null +++ b/cross/lib/gettimeofday.c @@ -0,0 +1,153 @@ +/* Provide gettimeofday for systems that don't have it or for which it's broken. + + Copyright (C) 2001-2003, 2005-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering */ + +#include + +/* Specification. */ +#include + +#include + +#if defined _WIN32 && ! defined __CYGWIN__ +# define WINDOWS_NATIVE +# include +#endif + +#ifdef WINDOWS_NATIVE + +/* Don't assume that UNICODE is not defined. */ +# undef LoadLibrary +# define LoadLibrary LoadLibraryA + +# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8) + +/* Avoid warnings from gcc -Wcast-function-type. */ +# define GetProcAddress \ + (void *) GetProcAddress + +/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ +typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); +static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL; +static BOOL initialized = FALSE; + +static void +initialize (void) +{ + HMODULE kernel32 = LoadLibrary ("kernel32.dll"); + if (kernel32 != NULL) + { + GetSystemTimePreciseAsFileTimeFunc = + (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime"); + } + initialized = TRUE; +} + +# else + +# define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime + +# endif + +#endif + +/* This is a wrapper for gettimeofday. It is used only on systems + that lack this function, or whose implementation of this function + causes problems. + Work around the bug in some systems whereby gettimeofday clobbers + the static buffer that localtime uses for its return value. The + gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has + this problem. */ + +int +gettimeofday (struct timeval *restrict tv, void *restrict tz) +{ +#undef gettimeofday +#ifdef WINDOWS_NATIVE + + /* On native Windows, there are two ways to get the current time: + GetSystemTimeAsFileTime + + or + GetSystemTimePreciseAsFileTime + . + GetSystemTimeAsFileTime produces values that jump by increments of + 15.627 milliseconds (!) on average. + Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2 + microseconds. + More discussion on this topic: + . */ + FILETIME current_time; + +# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8) + if (!initialized) + initialize (); +# endif + if (GetSystemTimePreciseAsFileTimeFunc != NULL) + GetSystemTimePreciseAsFileTimeFunc (¤t_time); + else + GetSystemTimeAsFileTime (¤t_time); + + /* Convert from FILETIME to 'struct timeval'. */ + /* FILETIME: */ + ULONGLONG since_1601 = + ((ULONGLONG) current_time.dwHighDateTime << 32) + | (ULONGLONG) current_time.dwLowDateTime; + /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap + years, in total 134774 days. */ + ULONGLONG since_1970 = + since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000; + ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10; + tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000; + tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000; + + return 0; + +#else + +# if HAVE_GETTIMEOFDAY + +# if defined timeval /* 'struct timeval' overridden by gnulib? */ +# undef timeval + struct timeval otv; + int result = gettimeofday (&otv, (struct timezone *) tz); + if (result == 0) + { + tv->tv_sec = otv.tv_sec; + tv->tv_usec = otv.tv_usec; + } +# else + int result = gettimeofday (tv, (struct timezone *) tz); +# endif + + return result; + +# else + +# if !defined OK_TO_USE_1S_CLOCK +# error "Only 1-second nominal clock resolution found. Is that intended?" \ + "If so, compile with the -DOK_TO_USE_1S_CLOCK option." +# endif + tv->tv_sec = time (NULL); + tv->tv_usec = 0; + + return 0; + +# endif +#endif +} diff --git a/cross/lib/group-member.c b/cross/lib/group-member.c new file mode 100644 index 00000000000..96a09f94a8f --- /dev/null +++ b/cross/lib/group-member.c @@ -0,0 +1,114 @@ +/* group-member.c -- determine whether group id is in calling user's group list + + Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +/* Most processes have no more than this many groups, and for these + processes we can avoid using malloc. */ +enum { GROUPBUF_SIZE = 100 }; + +struct group_info + { + gid_t *group; + gid_t groupbuf[GROUPBUF_SIZE]; + }; + +static void +free_group_info (struct group_info const *g) +{ + if (g->group != g->groupbuf) + free (g->group); +} + +static int +get_group_info (struct group_info *gi) +{ + int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf); + gi->group = gi->groupbuf; + + if (n_groups < 0) + { + int n_group_slots = getgroups (0, NULL); + size_t nbytes; + if (! ckd_mul (&nbytes, n_group_slots, sizeof *gi->group)) + { + gi->group = malloc (nbytes); + if (gi->group) + n_groups = getgroups (n_group_slots, gi->group); + } + } + + /* In case of error, the user loses. */ + return n_groups; +} + +/* Return non-zero if GID is one that we have in our groups list. + Note that the groups list is not guaranteed to contain the current + or effective group ID, so they should generally be checked + separately. */ + +int +group_member (gid_t gid) +{ + int i; + int found; + struct group_info gi; + int n_groups = get_group_info (&gi); + + /* Search through the list looking for GID. */ + found = 0; + for (i = 0; i < n_groups; i++) + { + if (gid == gi.group[i]) + { + found = 1; + break; + } + } + + free_group_info (&gi); + + return found; +} + +#ifdef TEST + +int +main (int argc, char **argv) +{ + int i; + + for (i = 1; i < argc; i++) + { + gid_t gid; + + gid = atoi (argv[i]); + printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no"); + } + exit (0); +} + +#endif /* TEST */ diff --git a/cross/lib/idx.h b/cross/lib/idx.h new file mode 100644 index 00000000000..23020b7ec0c --- /dev/null +++ b/cross/lib/idx.h @@ -0,0 +1,134 @@ +/* A type for indices and sizes. + Copyright (C) 2020-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _IDX_H +#define _IDX_H + +/* Get ptrdiff_t. */ +#include + +/* Get PTRDIFF_MAX. */ +#include + +/* The type 'idx_t' holds an (array) index or an (object) size. + Its implementation promotes to a signed integer type, + which can hold the values + 0..2^63-1 (on 64-bit platforms) or + 0..2^31-1 (on 32-bit platforms). + + Why a signed integer type? + + * Security: Signed types can be checked for overflow via + '-fsanitize=undefined', but unsigned types cannot. + + * Comparisons without surprises: ISO C99 § 6.3.1.8 specifies a few + surprising results for comparisons, such as + + (int) -3 < (unsigned long) 7 => false + (int) -3 < (unsigned int) 7 => false + and on 32-bit machines: + (long) -3 < (unsigned int) 7 => false + + This is surprising because the natural comparison order is by + value in the realm of infinite-precision signed integers (ℤ). + + The best way to get rid of such surprises is to use signed types + for numerical integer values, and use unsigned types only for + bit masks and enums. + + Why not use 'size_t' directly? + + * Because 'size_t' is an unsigned type, and a signed type is better. + See above. + + Why not use 'ssize_t'? + + * 'ptrdiff_t' is more portable; it is standardized by ISO C + whereas 'ssize_t' is standardized only by POSIX. + + * 'ssize_t' is not required to be as wide as 'size_t', and some + now-obsolete POSIX platforms had 'size_t' wider than 'ssize_t'. + + * Conversely, some now-obsolete platforms had 'ptrdiff_t' wider + than 'size_t', which can be a win and conforms to POSIX. + + Won't this cause a problem with objects larger than PTRDIFF_MAX? + + * Typical modern or large platforms do not allocate such objects, + so this is not much of a problem in practice; for example, you + can safely write 'idx_t len = strlen (s);'. To port to older + small platforms where allocations larger than PTRDIFF_MAX could + in theory be a problem, you can use Gnulib's ialloc module, or + functions like ximalloc in Gnulib's xalloc module. + + Why not use 'ptrdiff_t' directly? + + * Maintainability: When reading and modifying code, it helps to know that + a certain variable cannot have negative values. For example, when you + have a loop + + int n = ...; + for (int i = 0; i < n; i++) ... + + or + + ptrdiff_t n = ...; + for (ptrdiff_t i = 0; i < n; i++) ... + + you have to ask yourself "what if n < 0?". Whereas in + + idx_t n = ...; + for (idx_t i = 0; i < n; i++) ... + + you know that this case cannot happen. + + Similarly, when a programmer writes + + idx_t = ptr2 - ptr1; + + there is an implied assertion that ptr1 and ptr2 point into the same + object and that ptr1 <= ptr2. + + * Being future-proof: In the future, range types (integers which are + constrained to a certain range of values) may be added to C compilers + or to the C standard. Several programming languages (Ada, Haskell, + Common Lisp, Pascal) already have range types. Such range types may + help producing good code and good warnings. The type 'idx_t' could + then be typedef'ed to a range type that is signed after promotion. */ + +/* In the future, idx_t could be typedef'ed to a signed range type. + The clang "extended integer types", supported in Clang 11 or newer + , + are a special case of range types. However, these types don't support binary + operators with plain integer types (e.g. expressions such as x > 1). + Therefore, they don't behave like signed types (and not like unsigned types + either). So, we cannot use them here. */ + +/* Use the signed type 'ptrdiff_t'. */ +/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same + size, but it is so on all platforms we have seen since 1990. */ +typedef ptrdiff_t idx_t; + +/* IDX_MAX is the maximum value of an idx_t. */ +#define IDX_MAX PTRDIFF_MAX + +/* So far no need has been found for an IDX_WIDTH macro. + Perhaps there should be another macro IDX_VALUE_BITS that does not + count the sign bit and is therefore one less than PTRDIFF_WIDTH. */ + +#endif /* _IDX_H */ diff --git a/cross/lib/ieee754.in.h b/cross/lib/ieee754.in.h new file mode 100644 index 00000000000..8de4c32be5e --- /dev/null +++ b/cross/lib/ieee754.in.h @@ -0,0 +1,222 @@ +/* Copyright (C) 1992-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _IEEE754_H + +#define _IEEE754_H 1 + +#ifndef _GL_GNULIB_HEADER +/* Ordinary glibc usage. */ +# include +# include +#else +/* Gnulib usage. */ +# ifndef __BEGIN_DECLS +# ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +# else +# define __BEGIN_DECLS +# define __END_DECLS +# endif +# endif +# ifndef __FLOAT_WORD_ORDER +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# ifdef WORDS_BIGENDIAN +# define __BYTE_ORDER __BIG_ENDIAN +# else +# define __BYTE_ORDER __LITTLE_ENDIAN +# endif +# define __FLOAT_WORD_ORDER __BYTE_ORDER +# endif +#endif + +__BEGIN_DECLS + +union ieee754_float + { + float f; + + /* This is the IEEE 754 single-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee_nan; + }; + +#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ + + +union ieee754_double + { + double d; + + /* This is the IEEE 754 double-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif + } ieee_nan; + }; + +#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ + + +union ieee854_long_double + { + long double d; + + /* This is the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:32; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee; + + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int one:1; + unsigned int quiet_nan:1; + unsigned int mantissa0:30; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee_nan; + }; + +#define IEEE854_LONG_DOUBLE_BIAS 0x3fff + +__END_DECLS + +#endif /* ieee754.h */ diff --git a/cross/lib/ignore-value.h b/cross/lib/ignore-value.h new file mode 100644 index 00000000000..f0b569af4a7 --- /dev/null +++ b/cross/lib/ignore-value.h @@ -0,0 +1,51 @@ +/* ignore a function return without a compiler warning. -*- coding: utf-8 -*- + + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */ + +/* Use "ignore_value" to avoid a warning when using a function declared with + gcc's warn_unused_result attribute, but for which you really do want to + ignore the result. Traditionally, people have used a "(void)" cast to + indicate that a function's return value is deliberately unused. However, + if the function is declared with __attribute__((warn_unused_result)), + gcc issues a warning even with the cast. + + Caution: most of the time, you really should heed gcc's warning, and + check the return value. However, in those exceptional cases in which + you're sure you know what you're doing, use this function. + + For the record, here's one of the ignorable warnings: + "copy.c:233: warning: ignoring return value of 'fchown', + declared with attribute warn_unused_result". */ + +#ifndef _GL_IGNORE_VALUE_H +#define _GL_IGNORE_VALUE_H + +/* Normally casting an expression to void discards its value, but GCC + versions 3.4 and newer have __attribute__ ((__warn_unused_result__)) + which may cause unwanted diagnostics in that case. Use __typeof__ + and __extension__ to work around the problem, if the workaround is + known to be needed. + The workaround is not needed with clang. */ +#if (3 < __GNUC__ + (4 <= __GNUC_MINOR__)) && !defined __clang__ +# define ignore_value(x) \ + (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) +#else +# define ignore_value(x) ((void) (x)) +#endif + +#endif diff --git a/cross/lib/intprops-internal.h b/cross/lib/intprops-internal.h new file mode 100644 index 00000000000..0467a9ca8f2 --- /dev/null +++ b/cross/lib/intprops-internal.h @@ -0,0 +1,392 @@ +/* intprops-internal.h -- properties of integer types not visible to users + + Copyright (C) 2001-2023 Free Software Foundation, Inc. + + This program 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 program is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GL_INTPROPS_INTERNAL_H +#define _GL_INTPROPS_INTERNAL_H + +#include + +/* Return a value with the common real type of E and V and the value of V. + Do not evaluate E. */ +#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) + +/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see + . */ +#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v)) + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if the real type T is signed. */ +#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) + +/* Return 1 if the real expression E, after promotion, has a + signed or floating type. Do not evaluate E. */ +#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) + + +/* Minimum and maximum values for integer types and expressions. */ + +/* The width in bits of the integer type or expression T. + Do not evaluate T. T must not be a bit-field expression. + Padding bits are not supported; this is checked at compile-time below. */ +#define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) + +/* The maximum and minimum values for the type of the expression E, + after integer promotion. E is not evaluated. */ +#define _GL_INT_MINIMUM(e) \ + (_GL_EXPR_SIGNED (e) \ + ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_CONVERT (e, 0)) +#define _GL_INT_MAXIMUM(e) \ + (_GL_EXPR_SIGNED (e) \ + ? _GL_SIGNED_INT_MAXIMUM (e) \ + : _GL_INT_NEGATE_CONVERT (e, 1)) +#define _GL_SIGNED_INT_MAXIMUM(e) \ + (((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1) + +/* Work around OpenVMS incompatibility with C99. */ +#if !defined LLONG_MAX && defined __INT64_MAX +# define LLONG_MAX __INT64_MAX +# define LLONG_MIN __INT64_MIN +#endif + +/* This include file assumes that signed types are two's complement without + padding bits; the above macros have undefined behavior otherwise. + If this is a problem for you, please let us know how to fix it for your host. + This assumption is tested by the intprops-tests module. */ + +/* Does the __typeof__ keyword work? This could be done by + 'configure', but for now it's easier to do it by hand. */ +#if (2 <= __GNUC__ \ + || (4 <= __clang_major__) \ + || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ + || (0x5110 <= __SUNPRO_C && !__STDC__)) +# define _GL_HAVE___TYPEOF__ 1 +#else +# define _GL_HAVE___TYPEOF__ 0 +#endif + +/* Return 1 if the integer type or expression T might be signed. Return 0 + if it is definitely unsigned. T must not be a bit-field expression. + This macro does not evaluate its argument, and expands to an + integer constant expression. */ +#if _GL_HAVE___TYPEOF__ +# define _GL_SIGNED_TYPE_OR_EXPR(t) _GL_TYPE_SIGNED (__typeof__ (t)) +#else +# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 +#endif + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + A should not have side effects, and A's type should be an + integer with minimum value MIN and maximum MAX. */ +#define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + ((min) < 0 ? (a) < - (max) : 0 < (a)) + +/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow + (A, B, P) work when P is non-null. */ +#ifdef __EDG__ +/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned + . */ +# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow) +/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x, + see . */ +#elif 7 <= __GNUC__ +# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1 +#else +# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 +#endif + +/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */ +#if defined __clang_major__ && __clang_major__ < 14 +/* Work around Clang bug . */ +# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0 +#else +# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW +#endif + +/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for + __builtin_sub_overflow_p and __builtin_mul_overflow_p. */ +#ifdef __EDG__ +/* In EDG-based compilers like ICC 2021.3 and earlier, + __builtin_add_overflow_p etc. are not treated as integral constant + expressions even when all arguments are. */ +# define _GL_HAS_BUILTIN_OVERFLOW_P 0 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p) +#else +# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) +#endif + +#if (!defined _GL_STDCKDINT_H && 202311 <= __STDC_VERSION__ \ + && ! (_GL_HAS_BUILTIN_ADD_OVERFLOW && _GL_HAS_BUILTIN_MUL_OVERFLOW)) +# include +#endif + +/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. + Return 1 if the result overflows. Arguments should not have side + effects and A, B and *R can be of any integer type other than char, + bool, a bit-precise integer type, or an enumeration type. */ +#if _GL_HAS_BUILTIN_ADD_OVERFLOW +# define _GL_INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r) +# define _GL_INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r) +#elif defined ckd_add && defined ckd_sub && !defined _GL_STDCKDINT_H +# define _GL_INT_ADD_WRAPV(a, b, r) ckd_add (r, + (a), + (b)) +# define _GL_INT_SUBTRACT_WRAPV(a, b, r) ckd_sub (r, + (a), + (b)) +#else +# define _GL_INT_ADD_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW) +# define _GL_INT_SUBTRACT_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW) +#endif +#if _GL_HAS_BUILTIN_MUL_OVERFLOW +# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \ + || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \ + && !defined __EDG__) +# define _GL_INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r) +# else + /* Work around GCC bug 91450. */ +# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \ + ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && _GL_EXPR_SIGNED (a) && _GL_EXPR_SIGNED (b) \ + && _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \ + ? ((void) __builtin_mul_overflow (a, b, r), 1) \ + : __builtin_mul_overflow (a, b, r)) +# endif +#elif defined ckd_mul && !defined _GL_STDCKDINT_H +# define _GL_INT_MULTIPLY_WRAPV(a, b, r) ckd_mul (r, + (a), + (b)) +#else +# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \ + _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW) +#endif + +/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 + https://llvm.org/bugs/show_bug.cgi?id=25390 + For now, assume all versions of GCC-like compilers generate bogus + warnings for _Generic. This matters only for compilers that + lack relevant builtins. */ +#if __GNUC__ || defined __clang__ +# define _GL__GENERIC_BOGUS 1 +#else +# define _GL__GENERIC_BOGUS 0 +#endif + +/* Store the low-order bits of A B into *R, where OP specifies + the operation and OVERFLOW the overflow predicate. Return 1 if the + result overflows. Arguments should not have side effects, + and A, B and *R can be of any integer type other than char, bool, a + bit-precise integer type, or an enumeration type. */ +#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS +# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ + (_Generic \ + (*(r), \ + signed char: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + signed char, SCHAR_MIN, SCHAR_MAX), \ + unsigned char: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + unsigned char, 0, UCHAR_MAX), \ + short int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + short int, SHRT_MIN, SHRT_MAX), \ + unsigned short int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + unsigned short int, 0, USHRT_MAX), \ + int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX), \ + unsigned int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + unsigned int, 0, UINT_MAX), \ + long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX), \ + unsigned long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + unsigned long int, 0, ULONG_MAX), \ + long long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX), \ + unsigned long long int: \ + _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + unsigned long long int, 0, ULLONG_MAX))) +#else +/* Store the low-order bits of A B into *R, where OP specifies + the operation and OVERFLOW the overflow predicate. If *R is + signed, its type is ST with bounds SMIN..SMAX; otherwise its type + is UT with bounds U..UMAX. ST and UT are narrower than int. + Return 1 if the result overflows. Arguments should not have side + effects, and A, B and *R can be of any integer type other than + char, bool, a bit-precise integer type, or an enumeration type. */ +# if _GL_HAVE___TYPEOF__ +# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \ + (_GL_TYPE_SIGNED (__typeof__ (*(r))) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax)) +# else +# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \ + (overflow (a, b, smin, smax) \ + ? (overflow (a, b, 0, umax) \ + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \ + : (overflow (a, b, 0, umax) \ + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0))) +# endif + +# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ + (sizeof *(r) == sizeof (signed char) \ + ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \ + signed char, SCHAR_MIN, SCHAR_MAX, \ + unsigned char, UCHAR_MAX) \ + : sizeof *(r) == sizeof (short int) \ + ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \ + short int, SHRT_MIN, SHRT_MAX, \ + unsigned short int, USHRT_MAX) \ + : sizeof *(r) == sizeof (int) \ + ? (_GL_EXPR_SIGNED (*(r)) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + int, INT_MIN, INT_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ + unsigned int, 0, UINT_MAX)) \ + : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) +# ifdef LLONG_MAX +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + (sizeof *(r) == sizeof (long int) \ + ? (_GL_EXPR_SIGNED (*(r)) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + unsigned long int, 0, ULONG_MAX)) \ + : (_GL_EXPR_SIGNED (*(r)) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + long long int, LLONG_MIN, LLONG_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ + unsigned long long int, 0, ULLONG_MAX))) +# else +# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ + (_GL_EXPR_SIGNED (*(r)) \ + ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + long int, LONG_MIN, LONG_MAX) \ + : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ + unsigned long int, 0, ULONG_MAX)) +# endif +#endif + +/* Store the low-order bits of A B into *R, where the operation + is given by OP. Use the unsigned type UT for calculation to avoid + overflow problems. *R's type is T, with extrema TMIN and TMAX. + T can be any signed integer type other than char, bool, a + bit-precise integer type, or an enumeration type. + Return 1 if the result overflows. */ +#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ + (overflow (a, b, tmin, tmax) \ + ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ + : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) + +/* Return 1 if the integer expressions A - B and -A would overflow, + respectively. Arguments should not have side effects, + and can be any signed integer type other than char, bool, a + bit-precise integer type, or an enumeration type. + These macros are tuned for their last input argument being a constant. */ + +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define _GL_INT_NEGATE_OVERFLOW(a) \ + __builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0) +#else +# define _GL_INT_NEGATE_OVERFLOW(a) \ + _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) +#endif + +/* Return the low-order bits of A B, where the operation is given + by OP. Use the unsigned type UT for calculation to avoid undefined + behavior on signed integer overflow, and convert the result to type T. + UT is at least as wide as T and is no narrower than unsigned int, + T is two's complement, and there is no padding or trap representations. + Assume that converting UT to T yields the low-order bits, as is + done in all known two's-complement C compilers. E.g., see: + https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html + + According to the C standard, converting UT to T yields an + implementation-defined result or signal for values outside T's + range. However, code that works around this theoretical problem + runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: + https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html + As the compiler bug is real, don't try to work around the + theoretical problem. */ + +#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ + ((t) ((ut) (a) op (ut) (b))) + +/* Return true if the numeric values A + B, A - B, A * B fall outside + the range TMIN..TMAX. Arguments should not have side effects + and can be any integer type other than char, bool, + a bit-precise integer type, or an enumeration type. + TMIN should be signed and nonpositive. + TMAX should be positive, and should be signed unless TMIN is zero. */ +#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \ + ((b) < 0 \ + ? (((tmin) \ + ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \ + && (a) < (tmin) - (b)) \ + : (a) <= -1 - (b)) \ + || ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \ + : (a) < 0 \ + ? (((tmin) \ + ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \ + && (b) < (tmin) - (a)) \ + : (b) <= -1 - (a)) \ + || ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \ + && (tmax) < (a) + (b))) \ + : (tmax) < (b) || (tmax) - (b) < (a)) +#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \ + (((a) < 0) == ((b) < 0) \ + ? ((a) < (b) \ + ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \ + : (tmax) < (a) - (b)) \ + : (a) < 0 \ + ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \ + || (a) - (tmin) < (b)) \ + : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ + && _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \ + && (tmax) <= -1 - (b)) \ + || (tmax) + (b) < (a))) +#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ + ? (a) < (tmax) / (b) \ + : ((_GL_INT_NEGATE_OVERFLOW (b) \ + ? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \ + : (tmax) / -(b)) \ + <= -1 - (a))) \ + : _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \ + ? (_GL_EXPR_SIGNED (a) \ + ? 0 < (a) + (tmin) \ + : 0 < (a) && -1 - (tmin) < (a) - 1) \ + : (tmin) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \ + ? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \ + : (tmin) / (a) < (b)) \ + : (tmax) / (b) < (a))) + +#endif /* _GL_INTPROPS_INTERNAL_H */ diff --git a/cross/lib/intprops.h b/cross/lib/intprops.h new file mode 100644 index 00000000000..44b5e60fb9a --- /dev/null +++ b/cross/lib/intprops.h @@ -0,0 +1,335 @@ +/* intprops.h -- properties of integer types + + Copyright (C) 2001-2023 Free Software Foundation, Inc. + + This program 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 program is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GL_INTPROPS_H +#define _GL_INTPROPS_H + +#include "intprops-internal.h" + +/* The extra casts in the following macros work around compiler bugs, + e.g., in Cray C 5.0.3.0. */ + +/* True if the arithmetic type T is an integer type. bool counts as + an integer. */ +#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) + +/* True if the real type T is signed. */ +#define TYPE_SIGNED(t) _GL_TYPE_SIGNED (t) + +/* Return 1 if the real expression E, after promotion, has a + signed or floating type. Do not evaluate E. */ +#define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e) + + +/* Minimum and maximum values for integer types and expressions. */ + +/* The width in bits of the integer type or expression T. + Do not evaluate T. T must not be a bit-field expression. + Padding bits are not supported; this is checked at compile-time below. */ +#define TYPE_WIDTH(t) _GL_TYPE_WIDTH (t) + +/* The maximum and minimum values for the integer type T. */ +#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) +#define TYPE_MAXIMUM(t) \ + ((t) (! TYPE_SIGNED (t) \ + ? (t) -1 \ + : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) + +/* Bound on length of the string representing an unsigned integer + value representable in B bits. log10 (2.0) < 146/485. The + smallest value of B where this bound is not tight is 2621. */ +#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) + +/* Bound on length of the string representing an integer type or expression T. + T must not be a bit-field expression. + + Subtract 1 for the sign bit if T is signed, and then add 1 more for + a minus sign if needed. + + Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is + unsigned, this macro may overestimate the true bound by one byte when + applied to unsigned types of size 2, 4, 16, ... bytes. */ +#define INT_STRLEN_BOUND(t) \ + (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \ + + _GL_SIGNED_TYPE_OR_EXPR (t)) + +/* Bound on buffer size needed to represent an integer type or expression T, + including the terminating null. T must not be a bit-field expression. */ +#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) + + +/* Range overflow checks. + + The INT__RANGE_OVERFLOW macros return 1 if the corresponding C + operators overflow arithmetically when given the same arguments. + These macros do not rely on undefined or implementation-defined behavior. + Although their implementations are simple and straightforward, + they are harder to use and may be less efficient than the + INT__WRAPV, INT__OK, and INT__OVERFLOW macros described below. + + Example usage: + + long int i = ...; + long int j = ...; + if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) + printf ("multiply would overflow"); + else + printf ("product is %ld", i * j); + + Restrictions on *_RANGE_OVERFLOW macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, + so the arguments should not have side effects. The arithmetic + arguments (including the MIN and MAX arguments) must be of the same + integer type after the usual arithmetic conversions, and the type + must have minimum value MIN and maximum MAX. Unsigned types should + use a zero MIN of the proper type. + + Because all arguments are subject to integer promotions, these + macros typically do not work on types narrower than 'int'. + + These macros are tuned for constant MIN and MAX. For commutative + operations such as A + B, they are also tuned for constant B. */ + +/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (a) < (min) - (b) \ + : (max) - (b) < (a)) + +/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? (max) + (b) < (a) \ + : (a) < (min) + (b)) + +/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. + See above for restrictions. */ +#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ + _GL_INT_NEGATE_RANGE_OVERFLOW (a, min, max) + +/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Avoid && and || as they tickle + bugs in Sun C 5.11 2010/08/13 and other compilers; see + . */ +#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ + ((b) < 0 \ + ? ((a) < 0 \ + ? (a) < (max) / (b) \ + : (b) == -1 \ + ? 0 \ + : (min) / (b) < (a)) \ + : (b) == 0 \ + ? 0 \ + : ((a) < 0 \ + ? (a) < (min) / (b) \ + : (max) / (b) < (a))) + +/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. */ +#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ + ((min) < 0 && (b) == -1 && (a) < - (max)) + +/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Do not check for division by zero. + Mathematically, % should never overflow, but on x86-like hosts + INT_MIN % -1 traps, and the C standard permits this, so treat this + as an overflow too. */ +#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ + INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) + +/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. + See above for restrictions. Here, MIN and MAX are for A only, and B need + not be of the same type as the other arguments. The C standard says that + behavior is undefined for shifts unless 0 <= B < wordwidth, and that when + A is negative then A << B has undefined behavior and A >> B has + implementation-defined behavior, but do not check these other + restrictions. */ +#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ + ((a) < 0 \ + ? (a) < (min) >> (b) \ + : (max) >> (b) < (a)) + +/* The _GL*_OVERFLOW macros have the same restrictions as the + *_RANGE_OVERFLOW macros, except that they do not assume that operands + (e.g., A and B) have the same type as MIN and MAX. Instead, they assume + that the result (e.g., A + B) has that type. */ +#if _GL_HAS_BUILTIN_OVERFLOW_P +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) +#else +# define _GL_ADD_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? (b) <= (a) + (b) \ + : (b) < 0 ? (a) <= (a) + (b) \ + : (a) + (b) < (b)) +# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ + : (a) < 0 ? 1 \ + : (b) < 0 ? (a) - (b) <= (a) \ + : (a) < (b)) +# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ + (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ + || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) +#endif +#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (b) <= (a) + (b) - 1 \ + : (b) < 0 && (a) + (b) <= (a)) +#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ + ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ + : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ + : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) + +/* Return a nonzero value if A is a mathematical multiple of B, where + A is unsigned, B is negative, and MAX is the maximum value of A's + type. A's type must be the same as (A % B)'s type. Normally (A % + -B == 0) suffices, but things get tricky if -B would overflow. */ +#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ + (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ + ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ + ? (a) \ + : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ + : (a) % - (b)) \ + == 0) + +/* Check for integer overflow, and report low order bits of answer. + + The INT__OVERFLOW macros return 1 if the corresponding C operators + might not yield numerically correct answers due to arithmetic overflow. + The INT__WRAPV macros compute the low-order bits of the sum, + difference, and product of two C integers, and return 1 if these + low-order bits are not numerically correct. + These macros work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + Example usage, assuming A and B are long int: + + if (INT_MULTIPLY_OVERFLOW (a, b)) + printf ("result would overflow\n"); + else + printf ("result is %ld (no overflow)\n", a * b); + + Example usage with WRAPV flavor: + + long int result; + bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); + printf ("result is %ld (%s)\n", result, + overflow ? "after overflow" : "no overflow"); + + Restrictions on these macros: + + These macros do not check for all possible numerical problems or + undefined or unspecified behavior: they do not check for division + by zero, for bad shift counts, or for shifting negative numbers. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + The WRAPV macros are not constant expressions. They support only + +, binary -, and *. + + Because the WRAPV macros convert the result, they report overflow + in different circumstances than the OVERFLOW macros do. For + example, in the typical case with 16-bit 'short' and 32-bit 'int', + if A, B and *R are all of type 'short' then INT_ADD_OVERFLOW (A, B) + returns false because the addition cannot overflow after A and B + are converted to 'int', whereas INT_ADD_WRAPV (A, B, R) returns + true or false depending on whether the sum fits into 'short'. + + These macros are tuned for their last input argument being a constant. + + A, B, and *R should be integers; they need not be the same type, + and they need not be all signed or all unsigned. + However, none of the integer types should be bit-precise, + and *R's type should not be char, bool, or an enumeration type. + + Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, + A % B, and A << B would overflow, respectively. */ + +#define INT_ADD_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) +#define INT_SUBTRACT_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) +#define INT_NEGATE_OVERFLOW(a) _GL_INT_NEGATE_OVERFLOW (a) +#define INT_MULTIPLY_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) +#define INT_DIVIDE_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) +#define INT_REMAINDER_OVERFLOW(a, b) \ + _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) +#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ + INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ + _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) + +/* Return 1 if the expression A B would overflow, + where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, + assuming MIN and MAX are the minimum and maximum for the result type. + Arguments should be free of side effects. */ +#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ + op_result_overflow (a, b, \ + _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \ + _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b))) + +/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. + Return 1 if the result overflows. See above for restrictions. */ +#define INT_ADD_WRAPV(a, b, r) _GL_INT_ADD_WRAPV (a, b, r) +#define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r) +#define INT_MULTIPLY_WRAPV(a, b, r) _GL_INT_MULTIPLY_WRAPV (a, b, r) + +/* The following macros compute A + B, A - B, and A * B, respectively. + If no overflow occurs, they set *R to the result and return 1; + otherwise, they return 0 and may modify *R. + + Example usage: + + long int result; + if (INT_ADD_OK (a, b, &result)) + printf ("result is %ld\n", result); + else + printf ("overflow\n"); + + A, B, and *R should be integers; they need not be the same type, + and they need not be all signed or all unsigned. + However, none of the integer types should be bit-precise, + and *R's type should not be char, bool, or an enumeration type. + + These macros work correctly on all known practical hosts, and do not rely + on undefined behavior due to signed arithmetic overflow. + + These macros are not constant expressions. + + These macros may evaluate their arguments zero or multiple times, so the + arguments should not have side effects. + + These macros are tuned for B being a constant. */ + +#define INT_ADD_OK(a, b, r) (! INT_ADD_WRAPV (a, b, r)) +#define INT_SUBTRACT_OK(a, b, r) (! INT_SUBTRACT_WRAPV (a, b, r)) +#define INT_MULTIPLY_OK(a, b, r) (! INT_MULTIPLY_WRAPV (a, b, r)) + +#endif /* _GL_INTPROPS_H */ diff --git a/cross/lib/inttypes.in.h b/cross/lib/inttypes.in.h new file mode 100644 index 00000000000..50a2bbfcda2 --- /dev/null +++ b/cross/lib/inttypes.in.h @@ -0,0 +1,1002 @@ +/* Copyright (C) 2006-2023 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Derek Price. + This file is part of gnulib. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* + * ISO C 99 for platforms that lack it. + * + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* Include the original if it exists, and if this file + has not been included yet or if this file includes gnulib stdint.h + which in turn includes this file. + The include_next requires a split double-inclusion guard. */ +#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H +# if @HAVE_INTTYPES_H@ + + /* Some pre-C++11 implementations need this. */ +# if defined __cplusplus && ! defined __STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS 1 +# endif + +# @INCLUDE_NEXT@ @NEXT_INTTYPES_H@ + +# define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H +# endif +#endif + +#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H +#define INTTYPES_H + +/* Include or the gnulib replacement. + But avoid namespace pollution on glibc systems. */ +#ifndef __GLIBC__ +# include +#endif +/* Get CHAR_BIT, INT_MAX, LONG_MAX, etc. */ +#include +/* On mingw, __USE_MINGW_ANSI_STDIO only works if is also included */ +#if defined _WIN32 && ! defined __CYGWIN__ +# include +#endif + +#if !(INT_MAX == 0x7fffffff && INT_MIN + INT_MAX == -1) +# error "This file assumes that 'int' is 32-bit two's complement. Please report your platform and compiler to ." +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* 7.8.1 Macros for format specifiers */ + +#if defined _TNS_R_TARGET + /* Tandem NonStop R series and compatible platforms released before + July 2005 support %Ld but not %lld. */ +# define _LONG_LONG_FORMAT_PREFIX "L" +#else +# define _LONG_LONG_FORMAT_PREFIX "ll" +#endif + +#if !defined PRId8 +# ifdef INT8_MAX +# define PRId8 "d" +# endif +#endif +#if !defined PRIi8 +# ifdef INT8_MAX +# define PRIi8 "i" +# endif +#endif +#if !defined PRIo8 +# ifdef UINT8_MAX +# define PRIo8 "o" +# endif +#endif +#if !defined PRIu8 +# ifdef UINT8_MAX +# define PRIu8 "u" +# endif +#endif +#if !defined PRIx8 +# ifdef UINT8_MAX +# define PRIx8 "x" +# endif +#endif +#if !defined PRIX8 +# ifdef UINT8_MAX +# define PRIX8 "X" +# endif +#endif +#if !defined PRId16 +# ifdef INT16_MAX +# define PRId16 "d" +# endif +#endif +#if !defined PRIi16 +# ifdef INT16_MAX +# define PRIi16 "i" +# endif +#endif +#if !defined PRIo16 +# ifdef UINT16_MAX +# define PRIo16 "o" +# endif +#endif +#if !defined PRIu16 +# ifdef UINT16_MAX +# define PRIu16 "u" +# endif +#endif +#if !defined PRIx16 +# ifdef UINT16_MAX +# define PRIx16 "x" +# endif +#endif +#if !defined PRIX16 +# ifdef UINT16_MAX +# define PRIX16 "X" +# endif +#endif +#if !defined PRId32 +# ifdef INT32_MAX +# define PRId32 "d" +# endif +#endif +#if !defined PRIi32 +# ifdef INT32_MAX +# define PRIi32 "i" +# endif +#endif +#if !defined PRIo32 +# ifdef UINT32_MAX +# define PRIo32 "o" +# endif +#endif +#if !defined PRIu32 +# ifdef UINT32_MAX +# define PRIu32 "u" +# endif +#endif +#if !defined PRIx32 +# ifdef UINT32_MAX +# define PRIx32 "x" +# endif +#endif +#if !defined PRIX32 +# ifdef UINT32_MAX +# define PRIX32 "X" +# endif +#endif +#ifdef INT64_MAX +# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@) +# define _PRI64_PREFIX "l" +# elif defined _MSC_VER || defined __MINGW32__ +# define _PRI64_PREFIX "I64" +# elif LONG_MAX >> 30 == 1 +# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX +# endif +# if !defined PRId64 +# define PRId64 _PRI64_PREFIX "d" +# endif +# if !defined PRIi64 +# define PRIi64 _PRI64_PREFIX "i" +# endif +#endif +#ifdef UINT64_MAX +# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@) +# define _PRIu64_PREFIX "l" +# elif defined _MSC_VER || defined __MINGW32__ +# define _PRIu64_PREFIX "I64" +# elif ULONG_MAX >> 31 == 1 +# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX +# endif +# if !defined PRIo64 +# define PRIo64 _PRIu64_PREFIX "o" +# endif +# if !defined PRIu64 +# define PRIu64 _PRIu64_PREFIX "u" +# endif +# if !defined PRIx64 +# define PRIx64 _PRIu64_PREFIX "x" +# endif +# if !defined PRIX64 +# define PRIX64 _PRIu64_PREFIX "X" +# endif +#endif + +#if !defined PRIdLEAST8 +# define PRIdLEAST8 "d" +#endif +#if !defined PRIiLEAST8 +# define PRIiLEAST8 "i" +#endif +#if !defined PRIoLEAST8 +# define PRIoLEAST8 "o" +#endif +#if !defined PRIuLEAST8 +# define PRIuLEAST8 "u" +#endif +#if !defined PRIxLEAST8 +# define PRIxLEAST8 "x" +#endif +#if !defined PRIXLEAST8 +# define PRIXLEAST8 "X" +#endif +#if !defined PRIdLEAST16 +# define PRIdLEAST16 "d" +#endif +#if !defined PRIiLEAST16 +# define PRIiLEAST16 "i" +#endif +#if !defined PRIoLEAST16 +# define PRIoLEAST16 "o" +#endif +#if !defined PRIuLEAST16 +# define PRIuLEAST16 "u" +#endif +#if !defined PRIxLEAST16 +# define PRIxLEAST16 "x" +#endif +#if !defined PRIXLEAST16 +# define PRIXLEAST16 "X" +#endif +#if !defined PRIdLEAST32 +# define PRIdLEAST32 "d" +#endif +#if !defined PRIiLEAST32 +# define PRIiLEAST32 "i" +#endif +#if !defined PRIoLEAST32 +# define PRIoLEAST32 "o" +#endif +#if !defined PRIuLEAST32 +# define PRIuLEAST32 "u" +#endif +#if !defined PRIxLEAST32 +# define PRIxLEAST32 "x" +#endif +#if !defined PRIXLEAST32 +# define PRIXLEAST32 "X" +#endif +#ifdef INT64_MAX +# if !defined PRIdLEAST64 +# define PRIdLEAST64 PRId64 +# endif +# if !defined PRIiLEAST64 +# define PRIiLEAST64 PRIi64 +# endif +#endif +#ifdef UINT64_MAX +# if !defined PRIoLEAST64 +# define PRIoLEAST64 PRIo64 +# endif +# if !defined PRIuLEAST64 +# define PRIuLEAST64 PRIu64 +# endif +# if !defined PRIxLEAST64 +# define PRIxLEAST64 PRIx64 +# endif +# if !defined PRIXLEAST64 +# define PRIXLEAST64 PRIX64 +# endif +#endif + +#if !defined PRIdFAST8 +# if INT_FAST8_MAX > INT32_MAX +# define PRIdFAST8 PRId64 +# else +# define PRIdFAST8 "d" +# endif +#endif +#if !defined PRIiFAST8 +# if INT_FAST8_MAX > INT32_MAX +# define PRIiFAST8 PRIi64 +# else +# define PRIiFAST8 "i" +# endif +#endif +#if !defined PRIoFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define PRIoFAST8 PRIo64 +# else +# define PRIoFAST8 "o" +# endif +#endif +#if !defined PRIuFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define PRIuFAST8 PRIu64 +# else +# define PRIuFAST8 "u" +# endif +#endif +#if !defined PRIxFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define PRIxFAST8 PRIx64 +# else +# define PRIxFAST8 "x" +# endif +#endif +#if !defined PRIXFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define PRIXFAST8 PRIX64 +# else +# define PRIXFAST8 "X" +# endif +#endif +#if !defined PRIdFAST16 +# if INT_FAST16_MAX > INT32_MAX +# define PRIdFAST16 PRId64 +# else +# define PRIdFAST16 "d" +# endif +#endif +#if !defined PRIiFAST16 +# if INT_FAST16_MAX > INT32_MAX +# define PRIiFAST16 PRIi64 +# else +# define PRIiFAST16 "i" +# endif +#endif +#if !defined PRIoFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define PRIoFAST16 PRIo64 +# else +# define PRIoFAST16 "o" +# endif +#endif +#if !defined PRIuFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define PRIuFAST16 PRIu64 +# else +# define PRIuFAST16 "u" +# endif +#endif +#if !defined PRIxFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define PRIxFAST16 PRIx64 +# else +# define PRIxFAST16 "x" +# endif +#endif +#if !defined PRIXFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define PRIXFAST16 PRIX64 +# else +# define PRIXFAST16 "X" +# endif +#endif +#if !defined PRIdFAST32 +# if INT_FAST32_MAX > INT32_MAX +# define PRIdFAST32 PRId64 +# else +# define PRIdFAST32 "d" +# endif +#endif +#if !defined PRIiFAST32 +# if INT_FAST32_MAX > INT32_MAX +# define PRIiFAST32 PRIi64 +# else +# define PRIiFAST32 "i" +# endif +#endif +#if !defined PRIoFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define PRIoFAST32 PRIo64 +# else +# define PRIoFAST32 "o" +# endif +#endif +#if !defined PRIuFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define PRIuFAST32 PRIu64 +# else +# define PRIuFAST32 "u" +# endif +#endif +#if !defined PRIxFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define PRIxFAST32 PRIx64 +# else +# define PRIxFAST32 "x" +# endif +#endif +#if !defined PRIXFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define PRIXFAST32 PRIX64 +# else +# define PRIXFAST32 "X" +# endif +#endif +#ifdef INT64_MAX +# if !defined PRIdFAST64 +# define PRIdFAST64 PRId64 +# endif +# if !defined PRIiFAST64 +# define PRIiFAST64 PRIi64 +# endif +#endif +#ifdef UINT64_MAX +# if !defined PRIoFAST64 +# define PRIoFAST64 PRIo64 +# endif +# if !defined PRIuFAST64 +# define PRIuFAST64 PRIu64 +# endif +# if !defined PRIxFAST64 +# define PRIxFAST64 PRIx64 +# endif +# if !defined PRIXFAST64 +# define PRIXFAST64 PRIX64 +# endif +#endif + +#if !defined PRIdMAX +# if @INT32_MAX_LT_INTMAX_MAX@ +# define PRIdMAX PRId64 +# else +# define PRIdMAX "ld" +# endif +#endif +#if !defined PRIiMAX +# if @INT32_MAX_LT_INTMAX_MAX@ +# define PRIiMAX PRIi64 +# else +# define PRIiMAX "li" +# endif +#endif +#if !defined PRIoMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define PRIoMAX PRIo64 +# else +# define PRIoMAX "lo" +# endif +#endif +#if !defined PRIuMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define PRIuMAX PRIu64 +# else +# define PRIuMAX "lu" +# endif +#endif +#if !defined PRIxMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define PRIxMAX PRIx64 +# else +# define PRIxMAX "lx" +# endif +#endif +#if !defined PRIXMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define PRIXMAX PRIX64 +# else +# define PRIXMAX "lX" +# endif +#endif + +#if !defined PRIdPTR +# ifdef INTPTR_MAX +# define PRIdPTR @PRIPTR_PREFIX@ "d" +# endif +#endif +#if !defined PRIiPTR +# ifdef INTPTR_MAX +# define PRIiPTR @PRIPTR_PREFIX@ "i" +# endif +#endif +#if !defined PRIoPTR +# ifdef UINTPTR_MAX +# define PRIoPTR @PRIPTR_PREFIX@ "o" +# endif +#endif +#if !defined PRIuPTR +# ifdef UINTPTR_MAX +# define PRIuPTR @PRIPTR_PREFIX@ "u" +# endif +#endif +#if !defined PRIxPTR +# ifdef UINTPTR_MAX +# define PRIxPTR @PRIPTR_PREFIX@ "x" +# endif +#endif +#if !defined PRIXPTR +# ifdef UINTPTR_MAX +# define PRIXPTR @PRIPTR_PREFIX@ "X" +# endif +#endif + +#if !defined SCNd8 +# ifdef INT8_MAX +# define SCNd8 "hhd" +# endif +#endif +#if !defined SCNi8 +# ifdef INT8_MAX +# define SCNi8 "hhi" +# endif +#endif +#if !defined SCNo8 +# ifdef UINT8_MAX +# define SCNo8 "hho" +# endif +#endif +#if !defined SCNu8 +# ifdef UINT8_MAX +# define SCNu8 "hhu" +# endif +#endif +#if !defined SCNx8 +# ifdef UINT8_MAX +# define SCNx8 "hhx" +# endif +#endif +#if !defined SCNd16 +# ifdef INT16_MAX +# define SCNd16 "hd" +# endif +#endif +#if !defined SCNi16 +# ifdef INT16_MAX +# define SCNi16 "hi" +# endif +#endif +#if !defined SCNo16 +# ifdef UINT16_MAX +# define SCNo16 "ho" +# endif +#endif +#if !defined SCNu16 +# ifdef UINT16_MAX +# define SCNu16 "hu" +# endif +#endif +#if !defined SCNx16 +# ifdef UINT16_MAX +# define SCNx16 "hx" +# endif +#endif +#if !defined SCNd32 +# ifdef INT32_MAX +# define SCNd32 "d" +# endif +#endif +#if !defined SCNi32 +# ifdef INT32_MAX +# define SCNi32 "i" +# endif +#endif +#if !defined SCNo32 +# ifdef UINT32_MAX +# define SCNo32 "o" +# endif +#endif +#if !defined SCNu32 +# ifdef UINT32_MAX +# define SCNu32 "u" +# endif +#endif +#if !defined SCNx32 +# ifdef UINT32_MAX +# define SCNx32 "x" +# endif +#endif +#ifdef INT64_MAX +# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@) +# define _SCN64_PREFIX "l" +# elif defined _MSC_VER || defined __MINGW32__ +# define _SCN64_PREFIX "I64" +# elif LONG_MAX >> 30 == 1 +# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX +# endif +# if !defined SCNd64 +# define SCNd64 _SCN64_PREFIX "d" +# endif +# if !defined SCNi64 +# define SCNi64 _SCN64_PREFIX "i" +# endif +#endif +#ifdef UINT64_MAX +# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@) +# define _SCNu64_PREFIX "l" +# elif defined _MSC_VER || defined __MINGW32__ +# define _SCNu64_PREFIX "I64" +# elif ULONG_MAX >> 31 == 1 +# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX +# endif +# if !defined SCNo64 +# define SCNo64 _SCNu64_PREFIX "o" +# endif +# if !defined SCNu64 +# define SCNu64 _SCNu64_PREFIX "u" +# endif +# if !defined SCNx64 +# define SCNx64 _SCNu64_PREFIX "x" +# endif +#endif + +#if !defined SCNdLEAST8 +# define SCNdLEAST8 "hhd" +#endif +#if !defined SCNiLEAST8 +# define SCNiLEAST8 "hhi" +#endif +#if !defined SCNoLEAST8 +# define SCNoLEAST8 "hho" +#endif +#if !defined SCNuLEAST8 +# define SCNuLEAST8 "hhu" +#endif +#if !defined SCNxLEAST8 +# define SCNxLEAST8 "hhx" +#endif +#if !defined SCNdLEAST16 +# define SCNdLEAST16 "hd" +#endif +#if !defined SCNiLEAST16 +# define SCNiLEAST16 "hi" +#endif +#if !defined SCNoLEAST16 +# define SCNoLEAST16 "ho" +#endif +#if !defined SCNuLEAST16 +# define SCNuLEAST16 "hu" +#endif +#if !defined SCNxLEAST16 +# define SCNxLEAST16 "hx" +#endif +#if !defined SCNdLEAST32 +# define SCNdLEAST32 "d" +#endif +#if !defined SCNiLEAST32 +# define SCNiLEAST32 "i" +#endif +#if !defined SCNoLEAST32 +# define SCNoLEAST32 "o" +#endif +#if !defined SCNuLEAST32 +# define SCNuLEAST32 "u" +#endif +#if !defined SCNxLEAST32 +# define SCNxLEAST32 "x" +#endif +#ifdef INT64_MAX +# if !defined SCNdLEAST64 +# define SCNdLEAST64 SCNd64 +# endif +# if !defined SCNiLEAST64 +# define SCNiLEAST64 SCNi64 +# endif +#endif +#ifdef UINT64_MAX +# if !defined SCNoLEAST64 +# define SCNoLEAST64 SCNo64 +# endif +# if !defined SCNuLEAST64 +# define SCNuLEAST64 SCNu64 +# endif +# if !defined SCNxLEAST64 +# define SCNxLEAST64 SCNx64 +# endif +#endif + +#if !defined SCNdFAST8 +# if INT_FAST8_MAX > INT32_MAX +# define SCNdFAST8 SCNd64 +# elif INT_FAST8_MAX == 0x7fff +# define SCNdFAST8 "hd" +# elif INT_FAST8_MAX == 0x7f +# define SCNdFAST8 "hhd" +# else +# define SCNdFAST8 "d" +# endif +#endif +#if !defined SCNiFAST8 +# if INT_FAST8_MAX > INT32_MAX +# define SCNiFAST8 SCNi64 +# elif INT_FAST8_MAX == 0x7fff +# define SCNiFAST8 "hi" +# elif INT_FAST8_MAX == 0x7f +# define SCNiFAST8 "hhi" +# else +# define SCNiFAST8 "i" +# endif +#endif +#if !defined SCNoFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define SCNoFAST8 SCNo64 +# elif UINT_FAST8_MAX == 0xffff +# define SCNoFAST8 "ho" +# elif UINT_FAST8_MAX == 0xff +# define SCNoFAST8 "hho" +# else +# define SCNoFAST8 "o" +# endif +#endif +#if !defined SCNuFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define SCNuFAST8 SCNu64 +# elif UINT_FAST8_MAX == 0xffff +# define SCNuFAST8 "hu" +# elif UINT_FAST8_MAX == 0xff +# define SCNuFAST8 "hhu" +# else +# define SCNuFAST8 "u" +# endif +#endif +#if !defined SCNxFAST8 +# if UINT_FAST8_MAX > UINT32_MAX +# define SCNxFAST8 SCNx64 +# elif UINT_FAST8_MAX == 0xffff +# define SCNxFAST8 "hx" +# elif UINT_FAST8_MAX == 0xff +# define SCNxFAST8 "hhx" +# else +# define SCNxFAST8 "x" +# endif +#endif +#if !defined SCNdFAST16 +# if INT_FAST16_MAX > INT32_MAX +# define SCNdFAST16 SCNd64 +# elif INT_FAST16_MAX == 0x7fff +# define SCNdFAST16 "hd" +# else +# define SCNdFAST16 "d" +# endif +#endif +#if !defined SCNiFAST16 +# if INT_FAST16_MAX > INT32_MAX +# define SCNiFAST16 SCNi64 +# elif INT_FAST16_MAX == 0x7fff +# define SCNiFAST16 "hi" +# else +# define SCNiFAST16 "i" +# endif +#endif +#if !defined SCNoFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define SCNoFAST16 SCNo64 +# elif UINT_FAST16_MAX == 0xffff +# define SCNoFAST16 "ho" +# else +# define SCNoFAST16 "o" +# endif +#endif +#if !defined SCNuFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define SCNuFAST16 SCNu64 +# elif UINT_FAST16_MAX == 0xffff +# define SCNuFAST16 "hu" +# else +# define SCNuFAST16 "u" +# endif +#endif +#if !defined SCNxFAST16 +# if UINT_FAST16_MAX > UINT32_MAX +# define SCNxFAST16 SCNx64 +# elif UINT_FAST16_MAX == 0xffff +# define SCNxFAST16 "hx" +# else +# define SCNxFAST16 "x" +# endif +#endif +#if !defined SCNdFAST32 +# if INT_FAST32_MAX > INT32_MAX +# define SCNdFAST32 SCNd64 +# else +# define SCNdFAST32 "d" +# endif +#endif +#if !defined SCNiFAST32 +# if INT_FAST32_MAX > INT32_MAX +# define SCNiFAST32 SCNi64 +# else +# define SCNiFAST32 "i" +# endif +#endif +#if !defined SCNoFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define SCNoFAST32 SCNo64 +# else +# define SCNoFAST32 "o" +# endif +#endif +#if !defined SCNuFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define SCNuFAST32 SCNu64 +# else +# define SCNuFAST32 "u" +# endif +#endif +#if !defined SCNxFAST32 +# if UINT_FAST32_MAX > UINT32_MAX +# define SCNxFAST32 SCNx64 +# else +# define SCNxFAST32 "x" +# endif +#endif +#ifdef INT64_MAX +# if !defined SCNdFAST64 +# define SCNdFAST64 SCNd64 +# endif +# if !defined SCNiFAST64 +# define SCNiFAST64 SCNi64 +# endif +#endif +#ifdef UINT64_MAX +# if !defined SCNoFAST64 +# define SCNoFAST64 SCNo64 +# endif +# if !defined SCNuFAST64 +# define SCNuFAST64 SCNu64 +# endif +# if !defined SCNxFAST64 +# define SCNxFAST64 SCNx64 +# endif +#endif + +#if !defined SCNdMAX +# if @INT32_MAX_LT_INTMAX_MAX@ +# define SCNdMAX SCNd64 +# else +# define SCNdMAX "ld" +# endif +#endif +#if !defined SCNiMAX +# if @INT32_MAX_LT_INTMAX_MAX@ +# define SCNiMAX SCNi64 +# else +# define SCNiMAX "li" +# endif +#endif +#if !defined SCNoMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define SCNoMAX SCNo64 +# else +# define SCNoMAX "lo" +# endif +#endif +#if !defined SCNuMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define SCNuMAX SCNu64 +# else +# define SCNuMAX "lu" +# endif +#endif +#if !defined SCNxMAX +# if @UINT32_MAX_LT_UINTMAX_MAX@ +# define SCNxMAX SCNx64 +# else +# define SCNxMAX "lx" +# endif +#endif + +#if !defined SCNdPTR +# ifdef INTPTR_MAX +# define SCNdPTR @PRIPTR_PREFIX@ "d" +# endif +#endif +#if !defined SCNiPTR +# ifdef INTPTR_MAX +# define SCNiPTR @PRIPTR_PREFIX@ "i" +# endif +#endif +#if !defined SCNoPTR +# ifdef UINTPTR_MAX +# define SCNoPTR @PRIPTR_PREFIX@ "o" +# endif +#endif +#if !defined SCNuPTR +# ifdef UINTPTR_MAX +# define SCNuPTR @PRIPTR_PREFIX@ "u" +# endif +#endif +#if !defined SCNxPTR +# ifdef UINTPTR_MAX +# define SCNxPTR @PRIPTR_PREFIX@ "x" +# endif +#endif + +/* 7.8.2 Functions for greatest-width integer types */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if @GNULIB_IMAXABS@ +# if !@HAVE_DECL_IMAXABS@ +extern intmax_t imaxabs (intmax_t); +# endif +#elif defined GNULIB_POSIXCHECK +# undef imaxabs +# if HAVE_RAW_DECL_IMAXABS +_GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - " + "use gnulib module imaxabs for portability"); +# endif +#endif + +#if @GNULIB_IMAXDIV@ +# if !@HAVE_IMAXDIV_T@ +# if !GNULIB_defined_imaxdiv_t +typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t; +# define GNULIB_defined_imaxdiv_t 1 +# endif +# endif +# if !@HAVE_DECL_IMAXDIV@ +extern imaxdiv_t imaxdiv (intmax_t, intmax_t); +# endif +#elif defined GNULIB_POSIXCHECK +# undef imaxdiv +# if HAVE_RAW_DECL_IMAXDIV +_GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - " + "use gnulib module imaxdiv for portability"); +# endif +#endif + +#if @GNULIB_STRTOIMAX@ +# if @REPLACE_STRTOIMAX@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strtoimax +# define strtoimax rpl_strtoimax +# endif +_GL_FUNCDECL_RPL (strtoimax, intmax_t, + (const char *restrict, char **restrict, int) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtoimax, intmax_t, + (const char *restrict, char **restrict, int)); +# else +# if !@HAVE_DECL_STRTOIMAX@ +# undef strtoimax +_GL_FUNCDECL_SYS (strtoimax, intmax_t, + (const char *restrict, char **restrict, int) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoimax, intmax_t, + (const char *restrict, char **restrict, int)); +# endif +_GL_CXXALIASWARN (strtoimax); +#elif defined GNULIB_POSIXCHECK +# undef strtoimax +# if HAVE_RAW_DECL_STRTOIMAX +_GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - " + "use gnulib module strtoimax for portability"); +# endif +#endif + +#if @GNULIB_STRTOUMAX@ +# if @REPLACE_STRTOUMAX@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strtoumax +# define strtoumax rpl_strtoumax +# endif +_GL_FUNCDECL_RPL (strtoumax, uintmax_t, + (const char *restrict, char **restrict, int) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtoumax, uintmax_t, + (const char *restrict, char **restrict, int)); +# else +# if !@HAVE_DECL_STRTOUMAX@ +# undef strtoumax +_GL_FUNCDECL_SYS (strtoumax, uintmax_t, + (const char *restrict, char **restrict, int) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoumax, uintmax_t, + (const char *restrict, char **restrict, int)); +# endif +_GL_CXXALIASWARN (strtoumax); +#elif defined GNULIB_POSIXCHECK +# undef strtoumax +# if HAVE_RAW_DECL_STRTOUMAX +_GL_WARN_ON_USE (strtoumax, "strtoumax is unportable - " + "use gnulib module strtoumax for portability"); +# endif +#endif + +/* Don't bother defining or declaring wcstoimax and wcstoumax, since + wide-character functions like this are hardly ever useful. */ + +#ifdef __cplusplus +} +#endif + +#endif /* !defined INTTYPES_H && !defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H */ diff --git a/cross/lib/lchmod.c b/cross/lib/lchmod.c new file mode 100644 index 00000000000..b2d1b8bfde1 --- /dev/null +++ b/cross/lib/lchmod.c @@ -0,0 +1,94 @@ +/* Implement lchmod on platforms where it does not work correctly. + + Copyright 2020-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Paul Eggert */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#include + +/* Work like chmod, except when FILE is a symbolic link. + In that case, on systems where permissions on symbolic links are unsupported + (such as Linux), set errno to EOPNOTSUPP and return -1. */ + +int +lchmod (char const *file, mode_t mode) +{ + char readlink_buf[1]; + +#ifdef O_PATH + /* Open a file descriptor with O_NOFOLLOW, to make sure we don't + follow symbolic links, if /proc is mounted. O_PATH is used to + avoid a failure if the file is not readable. + Cf. */ + int fd = open (file, O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) + return fd; + + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) + { + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; + } + else + err = errno == ENOENT ? -1 : errno; + + close (fd); + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; +#endif + + size_t len = strlen (file); + if (len && file[len - 1] == '/') + { + struct stat st; + if (lstat (file, &st) < 0) + return -1; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } + + /* O_PATH + /proc is not supported. */ + + if (0 <= readlink (file, readlink_buf, sizeof readlink_buf)) + { + errno = EOPNOTSUPP; + return -1; + } + + /* Fall back on chmod, despite a possible race. */ + return chmod (file, mode); +} diff --git a/cross/lib/libc-config.h b/cross/lib/libc-config.h new file mode 100644 index 00000000000..1d28e58c971 --- /dev/null +++ b/cross/lib/libc-config.h @@ -0,0 +1,202 @@ +/* System definitions for code taken from the GNU C Library + + Copyright 2017-2023 Free Software Foundation, Inc. + + This program 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 program is distributed in the hope that 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 program; if not, see + . */ + +/* Written by Paul Eggert. */ + +/* This is intended to be a good-enough substitute for glibc system + macros like those defined in , so that Gnulib code + shared with glibc can do this as the first #include: + + #ifndef _LIBC + # include + #endif + + When compiled as part of glibc this is a no-op; when compiled as + part of Gnulib this includes Gnulib's and defines macros + that glibc library code would normally assume. + + Note: This header file MUST NOT be included by public header files + of Gnulib. */ + +#include + +/* On glibc this includes and and #defines + _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 and + DragonFlyBSD 5.9 it includes which defines __nonnull. + Elsewhere it is harmless. */ +#include + +/* From glibc . */ +#ifndef __set_errno +# define __set_errno(val) (errno = (val)) +#endif + +/* From glibc . */ + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __glibc_clang_prereq +# if defined __clang_major__ && defined __clang_minor__ +# ifdef __apple_build_version__ +/* Apple for some reason renumbers __clang_major__ and __clang_minor__. + Gnulib code uses only __glibc_clang_prereq (3, 5); map it to + 6000000 <= __apple_build_version__. Support for other calls to + __glibc_clang_prereq can be added here as needed. */ +# define __glibc_clang_prereq(maj, min) \ + ((maj) == 3 && (min) == 5 ? 6000000 <= __apple_build_version__ : 0) +# else +# define __glibc_clang_prereq(maj, min) \ + ((maj) < __clang_major__ + ((min) <= __clang_minor__)) +# endif +# else +# define __glibc_clang_prereq(maj, min) 0 +# endif +#endif + +#ifndef __attribute_nonnull__ +/* either does not exist, or is too old for Gnulib. + Prepare to include , which is Gnulib's version of a + more-recent glibc . */ + +/* Define _FEATURES_H so that does not include . */ +# ifndef _FEATURES_H +# define _FEATURES_H 1 +# endif +/* Define __GNULIB_CDEFS so that does not attempt to include + nonexistent files. */ +# define __GNULIB_CDEFS +/* Undef the macros unconditionally defined by our copy of glibc + , so that they do not clash with any system-defined + versions. */ +# undef _SYS_CDEFS_H +# undef __ASMNAME +# undef __ASMNAME2 +# undef __BEGIN_DECLS +# undef __CONCAT +# undef __END_DECLS +# undef __HAVE_GENERIC_SELECTION +# undef __LDBL_COMPAT +# undef __LDBL_REDIR +# undef __LDBL_REDIR1 +# undef __LDBL_REDIR1_DECL +# undef __LDBL_REDIR1_NTH +# undef __LDBL_REDIR2_DECL +# undef __LDBL_REDIR_DECL +# undef __LDBL_REDIR_NTH +# undef __LEAF +# undef __LEAF_ATTR +# undef __NTH +# undef __NTHNL +# undef __REDIRECT +# undef __REDIRECT_LDBL +# undef __REDIRECT_NTH +# undef __REDIRECT_NTHNL +# undef __REDIRECT_NTH_LDBL +# undef __STRING +# undef __THROW +# undef __THROWNL +# undef __attr_access +# undef __attr_access_none +# undef __attr_dealloc +# undef __attr_dealloc_free +# undef __attribute__ +# undef __attribute_alloc_align__ +# undef __attribute_alloc_size__ +# undef __attribute_artificial__ +# undef __attribute_const__ +# undef __attribute_deprecated__ +# undef __attribute_deprecated_msg__ +# undef __attribute_format_arg__ +# undef __attribute_format_strfmon__ +# undef __attribute_malloc__ +# undef __attribute_maybe_unused__ +# undef __attribute_noinline__ +# undef __attribute_nonstring__ +# undef __attribute_pure__ +# undef __attribute_returns_twice__ +# undef __attribute_used__ +# undef __attribute_warn_unused_result__ +# undef __bos +# undef __bos0 +# undef __errordecl +# undef __extension__ +# undef __extern_always_inline +# undef __extern_inline +# undef __flexarr +# undef __fortified_attr_access +# undef __fortify_function +# undef __glibc_c99_flexarr_available +# undef __glibc_fortify +# undef __glibc_fortify_n +# undef __glibc_has_attribute +# undef __glibc_has_builtin +# undef __glibc_has_extension +# undef __glibc_likely +# undef __glibc_macro_warning +# undef __glibc_macro_warning1 +# undef __glibc_objsize +# undef __glibc_objsize0 +# undef __glibc_safe_len_cond +# undef __glibc_safe_or_unknown_len +# undef __glibc_unlikely +# undef __glibc_unsafe_len +# undef __glibc_unsigned_or_positive +# undef __inline +# undef __ptr_t +# undef __restrict +# undef __restrict_arr +# undef __va_arg_pack +# undef __va_arg_pack_len +# undef __warnattr +# undef __wur + +/* Include our copy of glibc . */ +# include + +/* __inline is too pessimistic for non-GCC. */ +# undef __inline +# ifndef HAVE___INLINE +# if 199901 <= __STDC_VERSION__ || defined inline +# define __inline inline +# else +# define __inline +# endif +# endif + +#endif /* defined __glibc_likely */ + + +/* A substitute for glibc , good enough for Gnulib. */ +#define attribute_hidden +#define libc_hidden_proto(name) +#define libc_hidden_def(name) +#define libc_hidden_weak(name) +#define libc_hidden_ver(local, name) +#define strong_alias(name, aliasname) +#define weak_alias(name, aliasname) + +/* A substitute for glibc , good enough for Gnulib. */ +#define SHLIB_COMPAT(lib, introduced, obsoleted) 0 +#define compat_symbol(lib, local, symbol, version) extern int dummy +#define versioned_symbol(lib, local, symbol, version) extern int dummy diff --git a/cross/lib/limits.in.h b/cross/lib/limits.in.h new file mode 100644 index 00000000000..eaeac472299 --- /dev/null +++ b/cross/lib/limits.in.h @@ -0,0 +1,131 @@ +/* A GNU-like . + + Copyright 2016-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _GL_ALREADY_INCLUDING_LIMITS_H +/* Special invocation convention: + On Haiku/x86_64, we have a sequence of nested includes + -> -> . + In this situation, LONG_MAX and INT_MAX are not yet defined, + therefore we should not attempt to define LONG_BIT. */ + +#@INCLUDE_NEXT@ @NEXT_LIMITS_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_LIMITS_H + +# define _GL_ALREADY_INCLUDING_LIMITS_H + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_LIMITS_H@ + +# undef _GL_ALREADY_INCLUDING_LIMITS_H + +#ifndef _@GUARD_PREFIX@_LIMITS_H +#define _@GUARD_PREFIX@_LIMITS_H + +#ifndef LLONG_MIN +# if defined LONG_LONG_MIN /* HP-UX 11.31 */ +# define LLONG_MIN LONG_LONG_MIN +# elif defined LONGLONG_MIN /* IRIX 6.5 */ +# define LLONG_MIN LONGLONG_MIN +# elif defined __GNUC__ +# define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL) +# endif +#endif +#ifndef LLONG_MAX +# if defined LONG_LONG_MAX /* HP-UX 11.31 */ +# define LLONG_MAX LONG_LONG_MAX +# elif defined LONGLONG_MAX /* IRIX 6.5 */ +# define LLONG_MAX LONGLONG_MAX +# elif defined __GNUC__ +# define LLONG_MAX __LONG_LONG_MAX__ +# endif +#endif +#ifndef ULLONG_MAX +# if defined ULONG_LONG_MAX /* HP-UX 11.31 */ +# define ULLONG_MAX ULONG_LONG_MAX +# elif defined ULONGLONG_MAX /* IRIX 6.5 */ +# define ULLONG_MAX ULONGLONG_MAX +# elif defined __GNUC__ +# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL) +# endif +#endif + +/* The number of usable bits in an unsigned or signed integer type + with minimum value MIN and maximum value MAX, as an int expression + suitable in #if. Cover all known practical hosts. This + implementation exploits the fact that MAX is 1 less than a power of + 2, and merely counts the number of 1 bits in MAX; "COBn" means + "count the number of 1 bits in the low-order n bits"). */ +#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max)) +#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n)) +#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n)) +#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n)) +#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n)) +#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n)) +#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1)) + +#ifndef WORD_BIT +/* Assume 'int' is 32 bits wide. */ +# define WORD_BIT 32 +#endif +#ifndef LONG_BIT +/* Assume 'long' is 32 or 64 bits wide. */ +# if LONG_MAX == INT_MAX +# define LONG_BIT 32 +# else +# define LONG_BIT 64 +# endif +#endif + +/* Macros specified by C23 and by ISO/IEC TS 18661-1:2014. */ + +#if (! defined ULLONG_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__ \ + || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__))) +# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX) +# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX) +# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX) +# define SHRT_WIDTH _GL_INTEGER_WIDTH (SHRT_MIN, SHRT_MAX) +# define USHRT_WIDTH _GL_INTEGER_WIDTH (0, USHRT_MAX) +# define INT_WIDTH _GL_INTEGER_WIDTH (INT_MIN, INT_MAX) +# define UINT_WIDTH _GL_INTEGER_WIDTH (0, UINT_MAX) +# define LONG_WIDTH _GL_INTEGER_WIDTH (LONG_MIN, LONG_MAX) +# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX) +# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX) +# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX) +#endif + +/* Macros specified by C23. */ + +#if (! defined BOOL_WIDTH \ + && (defined _GNU_SOURCE \ + || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__))) +# define BOOL_MAX 1 +# define BOOL_WIDTH 1 +#endif + +#endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif /* _@GUARD_PREFIX@_LIMITS_H */ +#endif diff --git a/cross/lib/lstat.c b/cross/lib/lstat.c new file mode 100644 index 00000000000..00a4ce2ab87 --- /dev/null +++ b/cross/lib/lstat.c @@ -0,0 +1,104 @@ +/* Work around a bug of lstat on some systems + + Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_lstat doesn't recurse to + rpl_lstat. */ +#define __need_system_sys_stat_h +#include + +#if !HAVE_LSTAT +/* On systems that lack symlinks, our replacement already + defined lstat as stat, so there is nothing further to do other than + avoid an empty file. */ +typedef int dummy; +#else /* HAVE_LSTAT */ + +/* Get the original definition of lstat. It might be defined as a macro. */ +# include +# include +# undef __need_system_sys_stat_h + +static int +orig_lstat (const char *filename, struct stat *buf) +{ + return lstat (filename, buf); +} + +/* Specification. */ +# ifdef __osf__ +/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc + eliminates this include because of the preliminary #include + above. */ +# include "sys/stat.h" +# else +# include +# endif + +# include "stat-time.h" + +# include +# include + +/* lstat works differently on Linux and Solaris systems. POSIX (see + "pathname resolution" in the glossary) requires that programs like + 'ls' take into consideration the fact that FILE has a trailing slash + when FILE is a symbolic link. On Linux and Solaris 10 systems, the + lstat function already has the desired semantics (in treating + 'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)', + but on Solaris 9 and earlier it does not. + + If FILE has a trailing slash and specifies a symbolic link, + then use stat() to get more info on the referent of FILE. + If the referent is a non-directory, then set errno to ENOTDIR + and return -1. Otherwise, return stat's result. */ + +int +rpl_lstat (const char *file, struct stat *sbuf) +{ + int result = orig_lstat (file, sbuf); + + /* This replacement file can blindly check against '/' rather than + using the ISSLASH macro, because all platforms with '\\' either + lack symlinks (mingw) or have working lstat (cygwin) and thus do + not compile this file. 0 len should have already been filtered + out above, with a failure return of ENOENT. */ + if (result == 0) + { + if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/') + result = stat_time_normalize (result, sbuf); + else + { + /* At this point, a trailing slash is permitted only on + symlink-to-dir; but it should have found information on the + directory, not the symlink. Call 'stat' to get info about the + link's referent. Our replacement stat guarantees valid results, + even if the symlink is not pointing to a directory. */ + if (!S_ISLNK (sbuf->st_mode)) + { + errno = ENOTDIR; + return -1; + } + result = stat (file, sbuf); + } + } + return result; +} + +#endif /* HAVE_LSTAT */ diff --git a/cross/lib/malloc.c b/cross/lib/malloc.c new file mode 100644 index 00000000000..3ade35cb63f --- /dev/null +++ b/cross/lib/malloc.c @@ -0,0 +1,51 @@ +/* malloc() function that is glibc compatible. + + Copyright (C) 1997-1998, 2006-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering and Bruno Haible */ + +#define _GL_USE_STDLIB_ALLOC 1 +#include + +#include + +#include + +#include "xalloc-oversized.h" + +/* Allocate an N-byte block of memory from the heap, even if N is 0. */ + +void * +rpl_malloc (size_t n) +{ + if (n == 0) + n = 1; + + if (xalloc_oversized (n, 1)) + { + errno = ENOMEM; + return NULL; + } + + void *result = malloc (n); + +#if !HAVE_MALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/cross/lib/malloc/dynarray-skeleton.c b/cross/lib/malloc/dynarray-skeleton.c new file mode 100644 index 00000000000..580c278b7c5 --- /dev/null +++ b/cross/lib/malloc/dynarray-skeleton.c @@ -0,0 +1,528 @@ +/* Type-safe arrays which grow dynamically. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +/* Pre-processor macros which act as parameters: + + DYNARRAY_STRUCT + The struct tag of dynamic array to be defined. + DYNARRAY_ELEMENT + The type name of the element type. Elements are copied + as if by memcpy, and can change address as the dynamic + array grows. + DYNARRAY_PREFIX + The prefix of the functions which are defined. + + The following parameters are optional: + + DYNARRAY_ELEMENT_FREE + DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the + contents of elements. E is of type DYNARRAY_ELEMENT *. + DYNARRAY_ELEMENT_INIT + DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new + element. E is of type DYNARRAY_ELEMENT *. + If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is + defined, new elements are automatically zero-initialized. + Otherwise, new elements have undefined contents. + DYNARRAY_INITIAL_SIZE + The size of the statically allocated array (default: + at least 2, more elements if they fit into 128 bytes). + Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, + there is no statically allocated array at, and all non-empty + arrays are heap-allocated. + DYNARRAY_FINAL_TYPE + The name of the type which holds the final array. If not + defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE + must be a struct type, with members of type DYNARRAY_ELEMENT and + size_t at the start (in this order). + + These macros are undefined after this header file has been + included. + + The following types are provided (their members are private to the + dynarray implementation): + + struct DYNARRAY_STRUCT + + The following functions are provided: + + void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *); + void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *); + bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *); + void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *); + size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *); + DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *); + DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *); + DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t); + void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT); + DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *); + bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t); + void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *); + void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *); + + The following functions are provided are provided if the + prerequisites are met: + + bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, + DYNARRAY_FINAL_TYPE *); + (if DYNARRAY_FINAL_TYPE is defined) + DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, + size_t *); + (if DYNARRAY_FINAL_TYPE is not defined) +*/ + +#include + +#include +#include +#include + +#ifndef DYNARRAY_STRUCT +# error "DYNARRAY_STRUCT must be defined" +#endif + +#ifndef DYNARRAY_ELEMENT +# error "DYNARRAY_ELEMENT must be defined" +#endif + +#ifndef DYNARRAY_PREFIX +# error "DYNARRAY_PREFIX must be defined" +#endif + +#ifdef DYNARRAY_INITIAL_SIZE +# if DYNARRAY_INITIAL_SIZE < 0 +# error "DYNARRAY_INITIAL_SIZE must be non-negative" +# endif +# if DYNARRAY_INITIAL_SIZE > 0 +# define DYNARRAY_HAVE_SCRATCH 1 +# else +# define DYNARRAY_HAVE_SCRATCH 0 +# endif +#else +/* Provide a reasonable default which limits the size of + DYNARRAY_STRUCT. */ +# define DYNARRAY_INITIAL_SIZE \ + (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT)) +# define DYNARRAY_HAVE_SCRATCH 1 +#endif + +/* Public type definitions. */ + +/* All fields of this struct are private to the implementation. */ +struct DYNARRAY_STRUCT +{ + union + { + struct dynarray_header dynarray_abstract; + struct + { + /* These fields must match struct dynarray_header. */ + size_t used; + size_t allocated; + DYNARRAY_ELEMENT *array; + } dynarray_header; + } u; + +#if DYNARRAY_HAVE_SCRATCH + /* Initial inline allocation. */ + DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE]; +#endif +}; + +/* Internal use only: Helper macros. */ + +/* Ensure macro-expansion of DYNARRAY_PREFIX. */ +#define DYNARRAY_CONCAT0(prefix, name) prefix##name +#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name) +#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name) + +/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free), + so that Gnulib does not change 'free' to 'rpl_free'. */ +#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree) + +/* Address of the scratch buffer if any. */ +#if DYNARRAY_HAVE_SCRATCH +# define DYNARRAY_SCRATCH(list) (list)->scratch +#else +# define DYNARRAY_SCRATCH(list) NULL +#endif + +/* Internal use only: Helper functions. */ + +/* Internal function. Call DYNARRAY_ELEMENT_FREE with the array + elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE + macro expansion. */ +static inline void +DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array, + size_t __dynarray_used) +{ +#ifdef DYNARRAY_ELEMENT_FREE + for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i) + DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]); +#endif /* DYNARRAY_ELEMENT_FREE */ +} + +/* Internal function. Free the non-scratch array allocation. */ +static inline void +DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list) +{ +#if DYNARRAY_HAVE_SCRATCH + if (list->u.dynarray_header.array != list->scratch) + free (list->u.dynarray_header.array); +#else + free (list->u.dynarray_header.array); +#endif +} + +/* Public functions. */ + +/* Initialize a dynamic array object. This must be called before any + use of the object. */ +__attribute_nonnull__ ((1)) +static void +DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list) +{ + list->u.dynarray_header.used = 0; + list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE; + list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); +} + +/* Deallocate the dynamic array and its elements. */ +__attribute_maybe_unused__ __attribute_nonnull__ ((1)) +static void +DYNARRAY_FREE (struct DYNARRAY_STRUCT *list) +{ + DYNARRAY_NAME (free__elements__) + (list->u.dynarray_header.array, list->u.dynarray_header.used); + DYNARRAY_NAME (free__array__) (list); + DYNARRAY_NAME (init) (list); +} + +/* Return true if the dynamic array is in an error state. */ +__attribute_nonnull__ ((1)) +static inline bool +DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list) +{ + return list->u.dynarray_header.allocated == __dynarray_error_marker (); +} + +/* Mark the dynamic array as failed. All elements are deallocated as + a side effect. */ +__attribute_nonnull__ ((1)) +static void +DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list) +{ + DYNARRAY_NAME (free__elements__) + (list->u.dynarray_header.array, list->u.dynarray_header.used); + DYNARRAY_NAME (free__array__) (list); + list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); + list->u.dynarray_header.used = 0; + list->u.dynarray_header.allocated = __dynarray_error_marker (); +} + +/* Return the number of elements which have been added to the dynamic + array. */ +__attribute_nonnull__ ((1)) +static inline size_t +DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list) +{ + return list->u.dynarray_header.used; +} + +/* Return a pointer to the array element at INDEX. Terminate the + process if INDEX is out of bounds. */ +__attribute_nonnull__ ((1)) +static inline DYNARRAY_ELEMENT * +DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index) +{ + if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list))) + __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index); + return list->u.dynarray_header.array + index; +} + +/* Return a pointer to the first array element, if any. For a + zero-length array, the pointer can be NULL even though the dynamic + array has not entered the failure state. */ +__attribute_nonnull__ ((1)) +static inline DYNARRAY_ELEMENT * +DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list) +{ + return list->u.dynarray_header.array; +} + +/* Return a pointer one element past the last array element. For a + zero-length array, the pointer can be NULL even though the dynamic + array has not entered the failure state. */ +__attribute_nonnull__ ((1)) +static inline DYNARRAY_ELEMENT * +DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list) +{ + return list->u.dynarray_header.array + list->u.dynarray_header.used; +} + +/* Internal function. Slow path for the add function below. */ +static void +DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) +{ + if (__glibc_unlikely + (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, + DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT)))) + { + DYNARRAY_NAME (mark_failed) (list); + return; + } + + /* Copy the new element and increase the array length. */ + list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; +} + +/* Add ITEM at the end of the array, enlarging it by one element. + Mark *LIST as failed if the dynamic array allocation size cannot be + increased. */ +__attribute_nonnull__ ((1)) +static inline void +DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) +{ + /* Do nothing in case of previous error. */ + if (DYNARRAY_NAME (has_failed) (list)) + return; + + /* Enlarge the array if necessary. */ + if (__glibc_unlikely (list->u.dynarray_header.used + == list->u.dynarray_header.allocated)) + { + DYNARRAY_NAME (add__) (list, item); + return; + } + + /* Copy the new element and increase the array length. */ + list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; +} + +/* Internal function. Building block for the emplace functions below. + Assumes space for one more element in *LIST. */ +static inline DYNARRAY_ELEMENT * +DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list) +{ + DYNARRAY_ELEMENT *result + = &list->u.dynarray_header.array[list->u.dynarray_header.used]; + ++list->u.dynarray_header.used; +#if defined (DYNARRAY_ELEMENT_INIT) + DYNARRAY_ELEMENT_INIT (result); +#elif defined (DYNARRAY_ELEMENT_FREE) + memset (result, 0, sizeof (*result)); +#endif + return result; +} + +/* Internal function. Slow path for the emplace function below. */ +static DYNARRAY_ELEMENT * +DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list) +{ + if (__glibc_unlikely + (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, + DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT)))) + { + DYNARRAY_NAME (mark_failed) (list); + return NULL; + } + return DYNARRAY_NAME (emplace__tail__) (list); +} + +/* Allocate a place for a new element in *LIST and return a pointer to + it. The pointer can be NULL if the dynamic array cannot be + enlarged due to a memory allocation failure. */ +__attribute_maybe_unused__ __attribute_warn_unused_result__ +__attribute_nonnull__ ((1)) +static +/* Avoid inlining with the larger initialization code. */ +#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE)) +inline +#endif +DYNARRAY_ELEMENT * +DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list) +{ + /* Do nothing in case of previous error. */ + if (DYNARRAY_NAME (has_failed) (list)) + return NULL; + + /* Enlarge the array if necessary. */ + if (__glibc_unlikely (list->u.dynarray_header.used + == list->u.dynarray_header.allocated)) + return (DYNARRAY_NAME (emplace__) (list)); + return DYNARRAY_NAME (emplace__tail__) (list); +} + +/* Change the size of *LIST to SIZE. If SIZE is larger than the + existing size, new elements are added (which can be initialized). + Otherwise, the list is truncated, and elements are freed. Return + false on memory allocation failure (and mark *LIST as failed). */ +__attribute_maybe_unused__ __attribute_nonnull__ ((1)) +static bool +DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size) +{ + if (size > list->u.dynarray_header.used) + { + bool ok; +#if defined (DYNARRAY_ELEMENT_INIT) + /* The new elements have to be initialized. */ + size_t old_size = list->u.dynarray_header.used; + ok = __libc_dynarray_resize (&list->u.dynarray_abstract, + size, DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT)); + if (ok) + for (size_t i = old_size; i < size; ++i) + { + DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]); + } +#elif defined (DYNARRAY_ELEMENT_FREE) + /* Zero initialization is needed so that the elements can be + safely freed. */ + ok = __libc_dynarray_resize_clear + (&list->u.dynarray_abstract, size, + DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT)); +#else + ok = __libc_dynarray_resize (&list->u.dynarray_abstract, + size, DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT)); +#endif + if (__glibc_unlikely (!ok)) + DYNARRAY_NAME (mark_failed) (list); + return ok; + } + else + { + /* The list has shrunk in size. Free the removed elements. */ + DYNARRAY_NAME (free__elements__) + (list->u.dynarray_header.array + size, + list->u.dynarray_header.used - size); + list->u.dynarray_header.used = size; + return true; + } +} + +/* Remove the last element of LIST if it is present. */ +__attribute_maybe_unused__ __attribute_nonnull__ ((1)) +static void +DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list) +{ + /* used > 0 implies that the array is the non-failed state. */ + if (list->u.dynarray_header.used > 0) + { + size_t new_length = list->u.dynarray_header.used - 1; +#ifdef DYNARRAY_ELEMENT_FREE + DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]); +#endif + list->u.dynarray_header.used = new_length; + } +} + +/* Remove all elements from the list. The elements are freed, but the + list itself is not. */ +__attribute_maybe_unused__ __attribute_nonnull__ ((1)) +static void +DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list) +{ + /* free__elements__ does nothing if the list is in the failed + state. */ + DYNARRAY_NAME (free__elements__) + (list->u.dynarray_header.array, list->u.dynarray_header.used); + list->u.dynarray_header.used = 0; +} + +#ifdef DYNARRAY_FINAL_TYPE +/* Transfer the dynamic array to a permanent location at *RESULT. + Returns true on success on false on allocation failure. In either + case, *LIST is re-initialized and can be reused. A NULL pointer is + stored in *RESULT if LIST refers to an empty list. On success, the + pointer in *RESULT is heap-allocated and must be deallocated using + free. */ +__attribute_maybe_unused__ __attribute_warn_unused_result__ +__attribute_nonnull__ ((1, 2)) +static bool +DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, + DYNARRAY_FINAL_TYPE *result) +{ + struct dynarray_finalize_result res; + if (__libc_dynarray_finalize (&list->u.dynarray_abstract, + DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT), &res)) + { + /* On success, the result owns all the data. */ + DYNARRAY_NAME (init) (list); + *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length }; + return true; + } + else + { + /* On error, we need to free all data. */ + DYNARRAY_FREE (list); + errno = ENOMEM; + return false; + } +} +#else /* !DYNARRAY_FINAL_TYPE */ +/* Transfer the dynamic array to a heap-allocated array and return a + pointer to it. The pointer is NULL if memory allocation fails, or + if the array is empty, so this function should be used only for + arrays which are known not be empty (usually because they always + have a sentinel at the end). If LENGTHP is not NULL, the array + length is written to *LENGTHP. *LIST is re-initialized and can be + reused. */ +__attribute_maybe_unused__ __attribute_warn_unused_result__ +__attribute_nonnull__ ((1)) +static DYNARRAY_ELEMENT * +DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp) +{ + struct dynarray_finalize_result res; + if (__libc_dynarray_finalize (&list->u.dynarray_abstract, + DYNARRAY_SCRATCH (list), + sizeof (DYNARRAY_ELEMENT), &res)) + { + /* On success, the result owns all the data. */ + DYNARRAY_NAME (init) (list); + if (lengthp != NULL) + *lengthp = res.length; + return res.array; + } + else + { + /* On error, we need to free all data. */ + DYNARRAY_FREE (list); + errno = ENOMEM; + return NULL; + } +} +#endif /* !DYNARRAY_FINAL_TYPE */ + +/* Undo macro definitions. */ + +#undef DYNARRAY_CONCAT0 +#undef DYNARRAY_CONCAT1 +#undef DYNARRAY_NAME +#undef DYNARRAY_SCRATCH +#undef DYNARRAY_HAVE_SCRATCH + +#undef DYNARRAY_STRUCT +#undef DYNARRAY_ELEMENT +#undef DYNARRAY_PREFIX +#undef DYNARRAY_ELEMENT_FREE +#undef DYNARRAY_ELEMENT_INIT +#undef DYNARRAY_INITIAL_SIZE +#undef DYNARRAY_FINAL_TYPE diff --git a/cross/lib/malloc/dynarray.h b/cross/lib/malloc/dynarray.h new file mode 100644 index 00000000000..a9a3b0859c1 --- /dev/null +++ b/cross/lib/malloc/dynarray.h @@ -0,0 +1,177 @@ +/* Type-safe arrays which grow dynamically. Shared definitions. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +/* To use the dynarray facility, you need to include + and define the parameter macros + documented in that file. + + A minimal example which provides a growing list of integers can be + defined like this: + + struct int_array + { + // Pointer to result array followed by its length, + // as required by DYNARRAY_FINAL_TYPE. + int *array; + size_t length; + }; + + #define DYNARRAY_STRUCT dynarray_int + #define DYNARRAY_ELEMENT int + #define DYNARRAY_PREFIX dynarray_int_ + #define DYNARRAY_FINAL_TYPE struct int_array + #include + + To create a three-element array with elements 1, 2, 3, use this + code: + + struct dynarray_int dyn; + dynarray_int_init (&dyn); + for (int i = 1; i <= 3; ++i) + { + int *place = dynarray_int_emplace (&dyn); + assert (place != NULL); + *place = i; + } + struct int_array result; + bool ok = dynarray_int_finalize (&dyn, &result); + assert (ok); + assert (result.length == 3); + assert (result.array[0] == 1); + assert (result.array[1] == 2); + assert (result.array[2] == 3); + free (result.array); + + If the elements contain resources which must be freed, define + DYNARRAY_ELEMENT_FREE appropriately, like this: + + struct str_array + { + char **array; + size_t length; + }; + + #define DYNARRAY_STRUCT dynarray_str + #define DYNARRAY_ELEMENT char * + #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) + #define DYNARRAY_PREFIX dynarray_str_ + #define DYNARRAY_FINAL_TYPE struct str_array + #include + + Compared to scratch buffers, dynamic arrays have the following + features: + + - They have an element type, and are not just an untyped buffer of + bytes. + + - When growing, previously stored elements are preserved. (It is + expected that scratch_buffer_grow_preserve and + scratch_buffer_set_array_size eventually go away because all + current users are moved to dynamic arrays.) + + - Scratch buffers have a more aggressive growth policy because + growing them typically means a retry of an operation (across an + NSS service module boundary), which is expensive. + + - For the same reason, scratch buffers have a much larger initial + stack allocation. */ + +#ifndef _DYNARRAY_H +#define _DYNARRAY_H + +#include +#include + +struct dynarray_header +{ + size_t used; + size_t allocated; + void *array; +}; + +/* Marker used in the allocated member to indicate that an error was + encountered. */ +static inline size_t +__dynarray_error_marker (void) +{ + return -1; +} + +/* Internal function. See the has_failed function in + dynarray-skeleton.c. */ +static inline bool +__dynarray_error (struct dynarray_header *list) +{ + return list->allocated == __dynarray_error_marker (); +} + +/* Internal function. Enlarge the dynamically allocated area of the + array to make room for one more element. SCRATCH is a pointer to + the scratch area (which is not heap-allocated and must not be + freed). ELEMENT_SIZE is the size, in bytes, of one element. + Return false on failure, true on success. */ +bool __libc_dynarray_emplace_enlarge (struct dynarray_header *, + void *scratch, size_t element_size); + +/* Internal function. Enlarge the dynamically allocated area of the + array to make room for at least SIZE elements (which must be larger + than the existing used part of the dynamic array). SCRATCH is a + pointer to the scratch area (which is not heap-allocated and must + not be freed). ELEMENT_SIZE is the size, in bytes, of one element. + Return false on failure, true on success. */ +bool __libc_dynarray_resize (struct dynarray_header *, size_t size, + void *scratch, size_t element_size); + +/* Internal function. Like __libc_dynarray_resize, but clear the new + part of the dynamic array. */ +bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size, + void *scratch, size_t element_size); + +/* Internal type. */ +struct dynarray_finalize_result +{ + void *array; + size_t length; +}; + +/* Internal function. Copy the dynamically-allocated area to an + explicitly-sized heap allocation. SCRATCH is a pointer to the + embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the + element type. On success, true is returned, and pointer and length + are written to *RESULT. On failure, false is returned. The caller + has to take care of some of the memory management; this function is + expected to be called from dynarray-skeleton.c. */ +bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch, + size_t element_size, + struct dynarray_finalize_result *result); + + +/* Internal function. Terminate the process after an index error. + SIZE is the number of elements of the dynamic array. INDEX is the + lookup index which triggered the failure. */ +_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index); + +#ifndef _ISOMAC +libc_hidden_proto (__libc_dynarray_emplace_enlarge) +libc_hidden_proto (__libc_dynarray_resize) +libc_hidden_proto (__libc_dynarray_resize_clear) +libc_hidden_proto (__libc_dynarray_finalize) +libc_hidden_proto (__libc_dynarray_at_failure) +#endif + +#endif /* _DYNARRAY_H */ diff --git a/cross/lib/malloc/dynarray_at_failure.c b/cross/lib/malloc/dynarray_at_failure.c new file mode 100644 index 00000000000..ebc9310982c --- /dev/null +++ b/cross/lib/malloc/dynarray_at_failure.c @@ -0,0 +1,40 @@ +/* Report an dynamic array index out of bounds condition. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +# include +#endif + +#include +#include + +void +__libc_dynarray_at_failure (size_t size, size_t index) +{ +#ifdef _LIBC + char buf[200]; + __snprintf (buf, sizeof (buf), "Fatal glibc error: " + "array index %zu not less than array length %zu\n", + index, size); + __libc_fatal (buf); +#else + abort (); +#endif +} +libc_hidden_def (__libc_dynarray_at_failure) diff --git a/cross/lib/malloc/dynarray_emplace_enlarge.c b/cross/lib/malloc/dynarray_emplace_enlarge.c new file mode 100644 index 00000000000..7da539316c1 --- /dev/null +++ b/cross/lib/malloc/dynarray_emplace_enlarge.c @@ -0,0 +1,77 @@ +/* Increase the size of a dynamic array in preparation of an emplace operation. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include +#include +#include + +bool +__libc_dynarray_emplace_enlarge (struct dynarray_header *list, + void *scratch, size_t element_size) +{ + size_t new_allocated; + if (list->allocated == 0) + { + /* No scratch buffer provided. Choose a reasonable default + size. */ + if (element_size < 4) + new_allocated = 16; + else if (element_size < 8) + new_allocated = 8; + else + new_allocated = 4; + } + else + /* Increase the allocated size, using an exponential growth + policy. */ + { + new_allocated = list->allocated + list->allocated / 2 + 1; + if (new_allocated <= list->allocated) + { + /* Overflow. */ + __set_errno (ENOMEM); + return false; + } + } + + size_t new_size; + if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size)) + return false; + void *new_array; + if (list->array == scratch) + { + /* The previous array was not heap-allocated. */ + new_array = malloc (new_size); + if (new_array != NULL && list->array != NULL) + memcpy (new_array, list->array, list->used * element_size); + } + else + new_array = realloc (list->array, new_size); + if (new_array == NULL) + return false; + list->array = new_array; + list->allocated = new_allocated; + return true; +} +libc_hidden_def (__libc_dynarray_emplace_enlarge) diff --git a/cross/lib/malloc/dynarray_finalize.c b/cross/lib/malloc/dynarray_finalize.c new file mode 100644 index 00000000000..673595a5fad --- /dev/null +++ b/cross/lib/malloc/dynarray_finalize.c @@ -0,0 +1,66 @@ +/* Copy the dynamically-allocated area to an explicitly-sized heap allocation. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include + +bool +__libc_dynarray_finalize (struct dynarray_header *list, + void *scratch, size_t element_size, + struct dynarray_finalize_result *result) +{ + if (__dynarray_error (list)) + /* The caller will reported the deferred error. */ + return false; + + size_t used = list->used; + + /* Empty list. */ + if (used == 0) + { + /* An empty list could still be backed by a heap-allocated + array. Free it if necessary. */ + if (list->array != scratch) + free (list->array); + *result = (struct dynarray_finalize_result) { NULL, 0 }; + return true; + } + + size_t allocation_size = used * element_size; + void *heap_array = malloc (allocation_size); + if (heap_array != NULL) + { + /* The new array takes ownership of the strings. */ + if (list->array != NULL) + memcpy (heap_array, list->array, allocation_size); + if (list->array != scratch) + free (list->array); + *result = (struct dynarray_finalize_result) + { .array = heap_array, .length = used }; + return true; + } + else + /* The caller will perform the freeing operation. */ + return false; +} +libc_hidden_def (__libc_dynarray_finalize) diff --git a/cross/lib/malloc/dynarray_resize.c b/cross/lib/malloc/dynarray_resize.c new file mode 100644 index 00000000000..7ecd4de63b9 --- /dev/null +++ b/cross/lib/malloc/dynarray_resize.c @@ -0,0 +1,68 @@ +/* Increase the size of a dynamic array. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include +#include +#include + +bool +__libc_dynarray_resize (struct dynarray_header *list, size_t size, + void *scratch, size_t element_size) +{ + /* The existing allocation provides sufficient room. */ + if (size <= list->allocated) + { + list->used = size; + return true; + } + + /* Otherwise, use size as the new allocation size. The caller is + expected to provide the final size of the array, so there is no + over-allocation here. */ + + size_t new_size_bytes; + if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes)) + { + /* Overflow. */ + __set_errno (ENOMEM); + return false; + } + void *new_array; + if (list->array == scratch) + { + /* The previous array was not heap-allocated. */ + new_array = malloc (new_size_bytes); + if (new_array != NULL && list->array != NULL) + memcpy (new_array, list->array, list->used * element_size); + } + else + new_array = realloc (list->array, new_size_bytes); + if (new_array == NULL) + return false; + list->array = new_array; + list->allocated = size; + list->used = size; + return true; +} +libc_hidden_def (__libc_dynarray_resize) diff --git a/cross/lib/malloc/dynarray_resize_clear.c b/cross/lib/malloc/dynarray_resize_clear.c new file mode 100644 index 00000000000..bb23c522a14 --- /dev/null +++ b/cross/lib/malloc/dynarray_resize_clear.c @@ -0,0 +1,39 @@ +/* Increase the size of a dynamic array and clear the new part. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include + +bool +__libc_dynarray_resize_clear (struct dynarray_header *list, size_t size, + void *scratch, size_t element_size) +{ + size_t old_size = list->used; + if (!__libc_dynarray_resize (list, size, scratch, element_size)) + return false; + /* __libc_dynarray_resize already checked for overflow. */ + char *array = list->array; + memset (array + (old_size * element_size), 0, + (size - old_size) * element_size); + return true; +} +libc_hidden_def (__libc_dynarray_resize_clear) diff --git a/cross/lib/malloc/scratch_buffer.h b/cross/lib/malloc/scratch_buffer.h new file mode 100644 index 00000000000..33fd2b29cd5 --- /dev/null +++ b/cross/lib/malloc/scratch_buffer.h @@ -0,0 +1,135 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2015-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _SCRATCH_BUFFER_H +#define _SCRATCH_BUFFER_H + +/* Scratch buffers with a default stack allocation and fallback to + heap allocation. It is expected that this function is used in this + way: + + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) + if (!scratch_buffer_grow (&tmpbuf)) + return -1; + + scratch_buffer_free (&tmpbuf); + return 0; + + The allocation functions (scratch_buffer_grow, + scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make + sure that the heap allocation, if any, is freed, so that the code + above does not have a memory leak. The buffer still remains in a + state that can be deallocated using scratch_buffer_free, so a loop + like this is valid as well: + + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) + if (!scratch_buffer_grow (&tmpbuf)) + break; + + scratch_buffer_free (&tmpbuf); + + scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed + to grow the buffer by at least 512 bytes. This means that when + using the scratch buffer as a backing store for a non-character + array whose element size, in bytes, is 512 or smaller, the scratch + buffer only has to grow once to make room for at least one more + element. +*/ + +#include +#include +#include + +/* Scratch buffer. Must be initialized with scratch_buffer_init + before its use. */ +struct scratch_buffer { + void *data; /* Pointer to the beginning of the scratch area. */ + size_t length; /* Allocated space at the data pointer, in bytes. */ + union { max_align_t __align; char __c[1024]; } __space; +}; + +/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space + and BUFFER->length reflects the available space. */ +static inline void +scratch_buffer_init (struct scratch_buffer *buffer) +{ + buffer->data = buffer->__space.__c; + buffer->length = sizeof (buffer->__space); +} + +/* Deallocates *BUFFER (if it was heap-allocated). */ +static inline void +scratch_buffer_free (struct scratch_buffer *buffer) +{ + if (buffer->data != buffer->__space.__c) + free (buffer->data); +} + +/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT + preserved. Return true on success, false on allocation failure (in + which case the old buffer is freed). On success, the new buffer is + larger than the previous size. On failure, *BUFFER is deallocated, + but remains in a free-able state, and errno is set. */ +bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer); +libc_hidden_proto (__libc_scratch_buffer_grow) + +/* Alias for __libc_scratch_buffer_grow. */ +static __always_inline bool +scratch_buffer_grow (struct scratch_buffer *buffer) +{ + return __glibc_likely (__libc_scratch_buffer_grow (buffer)); +} + +/* Like __libc_scratch_buffer_grow, but preserve the old buffer + contents on success, as a prefix of the new buffer. */ +bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer); +libc_hidden_proto (__libc_scratch_buffer_grow_preserve) + +/* Alias for __libc_scratch_buffer_grow_preserve. */ +static __always_inline bool +scratch_buffer_grow_preserve (struct scratch_buffer *buffer) +{ + return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer)); +} + +/* Grow *BUFFER so that it can store at least NELEM elements of SIZE + bytes. The buffer contents are NOT preserved. Both NELEM and SIZE + can be zero. Return true on success, false on allocation failure + (in which case the old buffer is freed, but *BUFFER remains in a + free-able state, and errno is set). It is unspecified whether this + function can reduce the array size. */ +bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, + size_t nelem, size_t size); +libc_hidden_proto (__libc_scratch_buffer_set_array_size) + +/* Alias for __libc_scratch_set_array_size. */ +static __always_inline bool +scratch_buffer_set_array_size (struct scratch_buffer *buffer, + size_t nelem, size_t size) +{ + return __glibc_likely (__libc_scratch_buffer_set_array_size + (buffer, nelem, size)); +} + +#endif /* _SCRATCH_BUFFER_H */ diff --git a/cross/lib/malloc/scratch_buffer_dupfree.c b/cross/lib/malloc/scratch_buffer_dupfree.c new file mode 100644 index 00000000000..2f60fbb54e8 --- /dev/null +++ b/cross/lib/malloc/scratch_buffer_dupfree.c @@ -0,0 +1,41 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2020-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include + +void * +__libc_scratch_buffer_dupfree (struct scratch_buffer *buffer, size_t size) +{ + void *data = buffer->data; + if (data == buffer->__space.__c) + { + void *copy = malloc (size); + return copy != NULL ? memcpy (copy, data, size) : NULL; + } + else + { + void *copy = realloc (data, size); + return copy != NULL ? copy : data; + } +} +libc_hidden_def (__libc_scratch_buffer_dupfree) diff --git a/cross/lib/malloc/scratch_buffer_grow.c b/cross/lib/malloc/scratch_buffer_grow.c new file mode 100644 index 00000000000..a5e8f2f7230 --- /dev/null +++ b/cross/lib/malloc/scratch_buffer_grow.c @@ -0,0 +1,56 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2015-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include + +bool +__libc_scratch_buffer_grow (struct scratch_buffer *buffer) +{ + void *new_ptr; + size_t new_length = buffer->length * 2; + + /* Discard old buffer. */ + scratch_buffer_free (buffer); + + /* Check for overflow. */ + if (__glibc_likely (new_length >= buffer->length)) + new_ptr = malloc (new_length); + else + { + __set_errno (ENOMEM); + new_ptr = NULL; + } + + if (__glibc_unlikely (new_ptr == NULL)) + { + /* Buffer must remain valid to free. */ + scratch_buffer_init (buffer); + return false; + } + + /* Install new heap-based buffer. */ + buffer->data = new_ptr; + buffer->length = new_length; + return true; +} +libc_hidden_def (__libc_scratch_buffer_grow) diff --git a/cross/lib/malloc/scratch_buffer_grow_preserve.c b/cross/lib/malloc/scratch_buffer_grow_preserve.c new file mode 100644 index 00000000000..c0b5d87b7e4 --- /dev/null +++ b/cross/lib/malloc/scratch_buffer_grow_preserve.c @@ -0,0 +1,67 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2015-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include + +bool +__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer) +{ + size_t new_length = 2 * buffer->length; + void *new_ptr; + + if (buffer->data == buffer->__space.__c) + { + /* Move buffer to the heap. No overflow is possible because + buffer->length describes a small buffer on the stack. */ + new_ptr = malloc (new_length); + if (new_ptr == NULL) + return false; + memcpy (new_ptr, buffer->__space.__c, buffer->length); + } + else + { + /* Buffer was already on the heap. Check for overflow. */ + if (__glibc_likely (new_length >= buffer->length)) + new_ptr = realloc (buffer->data, new_length); + else + { + __set_errno (ENOMEM); + new_ptr = NULL; + } + + if (__glibc_unlikely (new_ptr == NULL)) + { + /* Deallocate, but buffer must remain valid to free. */ + free (buffer->data); + scratch_buffer_init (buffer); + return false; + } + } + + /* Install new heap-based buffer. */ + buffer->data = new_ptr; + buffer->length = new_length; + return true; +} +libc_hidden_def (__libc_scratch_buffer_grow_preserve) diff --git a/cross/lib/malloc/scratch_buffer_set_array_size.c b/cross/lib/malloc/scratch_buffer_set_array_size.c new file mode 100644 index 00000000000..24c39350ade --- /dev/null +++ b/cross/lib/malloc/scratch_buffer_set_array_size.c @@ -0,0 +1,64 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2015-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include +#include + +bool +__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, + size_t nelem, size_t size) +{ + size_t new_length = nelem * size; + + /* Avoid overflow check if both values are small. */ + if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0 + && nelem != 0 && size != new_length / nelem) + { + /* Overflow. Discard the old buffer, but it must remain valid + to free. */ + scratch_buffer_free (buffer); + scratch_buffer_init (buffer); + __set_errno (ENOMEM); + return false; + } + + if (new_length <= buffer->length) + return true; + + /* Discard old buffer. */ + scratch_buffer_free (buffer); + + char *new_ptr = malloc (new_length); + if (new_ptr == NULL) + { + /* Buffer must remain valid to free. */ + scratch_buffer_init (buffer); + return false; + } + + /* Install new heap-based buffer. */ + buffer->data = new_ptr; + buffer->length = new_length; + return true; +} +libc_hidden_def (__libc_scratch_buffer_set_array_size) diff --git a/cross/lib/md5-stream.c b/cross/lib/md5-stream.c new file mode 100644 index 00000000000..ba76792cbbe --- /dev/null +++ b/cross/lib/md5-stream.c @@ -0,0 +1,141 @@ +/* Functions to compute MD5 message digest of files or memory blocks. + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Ulrich Drepper , 1995. */ + +#include + +/* Specification. */ +#if HAVE_OPENSSL_MD5 +# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE +#endif +#include "md5.h" + +#include + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#include "af_alg.h" + +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_stream __md5_stream +#endif + +#define BLOCKSIZE 32768 +#if BLOCKSIZE % 64 != 0 +# error "invalid BLOCKSIZE" +#endif + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (FILE *stream, void *resblock) +{ + switch (afalg_stream (stream, "md5", resblock, MD5_DIGEST_SIZE)) + { + case 0: return 0; + case -EIO: return 1; + } + + char *buffer = malloc (BLOCKSIZE + 72); + if (!buffer) + return 1; + + struct md5_ctx ctx; + md5_init_ctx (&ctx); + size_t sum; + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + while (1) + { + /* Either process a partial fread() from this loop, + or the fread() in afalg_stream may have gotten EOF. + We need to avoid a subsequent fread() as EOF may + not be sticky. For details of such systems, see: + https://sourceware.org/bugzilla/show_bug.cgi?id=1190 */ + if (feof (stream)) + goto process_partial_block; + + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + + if (sum == BLOCKSIZE) + break; + + if (n == 0) + { + /* Check for the error flag IFF N == 0, so that we don't + exit the loop after a partial read due to e.g., EAGAIN + or EWOULDBLOCK. */ + if (ferror (stream)) + { + free (buffer); + return 1; + } + goto process_partial_block; + } + } + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + +process_partial_block: + + /* Process any remaining bytes. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + free (buffer); + return 0; +} + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/md5.c b/cross/lib/md5.c new file mode 100644 index 00000000000..4a6accf28ff --- /dev/null +++ b/cross/lib/md5.c @@ -0,0 +1,394 @@ +/* Functions to compute MD5 message digest of files or memory blocks. + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Ulrich Drepper , 1995. */ + +#include + +/* Specification. */ +#if HAVE_OPENSSL_MD5 +# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE +#endif +#include "md5.h" + +#include +#include +#include + +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_buffer __md5_buffer +#endif + +#include +#ifdef WORDS_BIGENDIAN +# define SWAP(n) bswap_32 (n) +#else +# define SWAP(n) (n) +#endif + +#if ! HAVE_OPENSSL_MD5 + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (struct md5_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Copy the 4 byte value from v into the memory location pointed to by *cp, + If your architecture allows unaligned access this is equivalent to + * (uint32_t *) cp = v */ +static void +set_uint32 (char *cp, uint32_t v) +{ + memcpy (cp, &v, sizeof v); +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. */ +void * +md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) +{ + char *r = resbuf; + set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); + set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); + set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); + set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + uint32_t bytes = ctx->buflen; + size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + ctx->buffer[size - 2] = SWAP (ctx->total[0] << 3); + ctx->buffer[size - 1] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); + + memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, size * 4, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (const char *buffer, size_t len, void *resblock) +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap, + because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ + memcpy (ctx->buffer, + &((char *) ctx->buffer)[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) +# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + /* The regions in the following copy operation cannot overlap, + because left_over ≤ 64. */ + memcpy (ctx->buffer, &ctx->buffer[16], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) +{ + uint32_t correct_words[16]; + const uint32_t *words = buffer; + size_t nwords = len / sizeof (uint32_t); + const uint32_t *endp = words + nwords; + uint32_t A = ctx->A; + uint32_t B = ctx->B; + uint32_t C = ctx->C; + uint32_t D = ctx->D; + uint32_t lolen = len; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += lolen; + ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + uint32_t *cwp = correct_words; + uint32_t A_save = A; + uint32_t B_save = B; + uint32_t C_save = C; + uint32_t D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + + Here is an equivalent invocation using Perl: + + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/md5.h b/cross/lib/md5.h new file mode 100644 index 00000000000..f34e7cb8dfa --- /dev/null +++ b/cross/lib/md5.h @@ -0,0 +1,151 @@ +/* Declaration of functions and data types used for MD5 sum computing + library functions. + Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2023 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include +#include + +# if HAVE_OPENSSL_MD5 +# ifndef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ +# endif +# include +# endif + +#define MD5_DIGEST_SIZE 16 +#define MD5_BLOCK_SIZE 64 + +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#ifndef __THROW +# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#ifndef _LIBC +# define __md5_buffer md5_buffer +# define __md5_finish_ctx md5_finish_ctx +# define __md5_init_ctx md5_init_ctx +# define __md5_process_block md5_process_block +# define __md5_process_bytes md5_process_bytes +# define __md5_read_ctx md5_read_ctx +# define __md5_stream md5_stream +#endif + +# ifdef __cplusplus +extern "C" { +# endif + +# if HAVE_OPENSSL_MD5 +# define GL_OPENSSL_NAME 5 +# include "gl_openssl.h" +# else +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + uint32_t A; + uint32_t B; + uint32_t C; + uint32_t D; + + uint32_t total[2]; + uint32_t buflen; /* ≥ 0, ≤ 128 */ + uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ +}; + +/* + * The following three functions are build up the low level used in + * the functions 'md5_stream' and 'md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void __md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx) __THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void __md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx) __THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. */ +extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *restrict resbuf) + __THROW; + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. */ +extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *restrict resbuf) + __THROW; + + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *__md5_buffer (const char *buffer, size_t len, + void *restrict resblock) __THROW; + +# endif + +/* Compute MD5 message digest for bytes read from STREAM. + STREAM is an open file stream. Regular files are handled more efficiently. + The contents of STREAM from its current position to its end will be read. + The case that the last operation on STREAM was an 'ungetc' is not supported. + The resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int __md5_stream (FILE *stream, void *resblock) __THROW; + + +# ifdef __cplusplus +} +# endif + +#endif /* md5.h */ + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/memmem.c b/cross/lib/memmem.c new file mode 100644 index 00000000000..c0b48c1b25d --- /dev/null +++ b/cross/lib/memmem.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2023 Free Software + Foundation, Inc. + This file is part of the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* This particular implementation was written by Eric Blake, 2008. */ + +#ifndef _LIBC +# include +#endif + +/* Specification of memmem. */ +#include + +#define RETURN_TYPE void * +#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l)) +#include "str-two-way.h" + +/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK + if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in + HAYSTACK. */ +void * +memmem (const void *haystack_start, size_t haystack_len, + const void *needle_start, size_t needle_len) +{ + /* Abstract memory is considered to be an array of 'unsigned char' values, + not an array of 'char' values. See ISO C 99 section 6.2.6.1. */ + const unsigned char *haystack = (const unsigned char *) haystack_start; + const unsigned char *needle = (const unsigned char *) needle_start; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + /* Use optimizations in memchr when possible, to reduce the search + size of haystack using a linear algorithm with a smaller + coefficient. However, avoid memchr for long needles, since we + can often achieve sublinear performance. */ + if (needle_len < LONG_NEEDLE_THRESHOLD) + { + haystack = memchr (haystack, *needle, haystack_len); + if (!haystack || __builtin_expect (needle_len == 1, 0)) + return (void *) haystack; + haystack_len -= haystack - (const unsigned char *) haystack_start; + if (haystack_len < needle_len) + return NULL; + return two_way_short_needle (haystack, haystack_len, needle, needle_len); + } + else + return two_way_long_needle (haystack, haystack_len, needle, needle_len); +} + +#undef LONG_NEEDLE_THRESHOLD diff --git a/cross/lib/mempcpy.c b/cross/lib/mempcpy.c new file mode 100644 index 00000000000..24a3135988f --- /dev/null +++ b/cross/lib/mempcpy.c @@ -0,0 +1,33 @@ +/* Copy memory area and return pointer after last written byte. + Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* A function definition is only needed if HAVE_MEMPCPY is not defined. */ +#if !HAVE_MEMPCPY + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +void * +mempcpy (void *dest, const void *src, size_t n) +{ + return (char *) memcpy (dest, src, n) + n; +} + +#endif diff --git a/cross/lib/memrchr.c b/cross/lib/memrchr.c new file mode 100644 index 00000000000..c5b1fe8b2e3 --- /dev/null +++ b/cross/lib/memrchr.c @@ -0,0 +1,161 @@ +/* memrchr -- find the last occurrence of a byte in a memory block + + Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2023 Free Software + Foundation, Inc. + + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#if defined _LIBC +# include +#else +# include +# define reg_char char +#endif + +#include +#include + +#undef __memrchr +#ifdef _LIBC +# undef memrchr +#endif + +#ifndef weak_alias +# define __memrchr memrchr +#endif + +/* Search no more than N bytes of S for C. */ +void * +__memrchr (void const *s, int c_in, size_t n) +{ + /* On 32-bit hardware, choosing longword to be a 32-bit unsigned + long instead of a 64-bit uintmax_t tends to give better + performance. On 64-bit hardware, unsigned long is generally 64 + bits already. Change this typedef to experiment with + performance. */ + typedef unsigned long int longword; + + const unsigned char *char_ptr; + const longword *longword_ptr; + longword repeated_one; + longword repeated_c; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the last few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s + n; + n > 0 && (size_t) char_ptr % sizeof (longword) != 0; + --n) + if (*--char_ptr == c) + return (void *) char_ptr; + + longword_ptr = (const void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to any size longwords. */ + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + repeated_one = 0x01010101; + repeated_c = c | (c << 8); + repeated_c |= repeated_c << 16; + if (0xffffffffU < (longword) -1) + { + repeated_one |= repeated_one << 31 << 1; + repeated_c |= repeated_c << 31 << 1; + if (8 < sizeof (longword)) + { + size_t i; + + for (i = 64; i < sizeof (longword) * 8; i *= 2) + { + repeated_one |= repeated_one << i; + repeated_c |= repeated_c << i; + } + } + } + + /* Instead of the traditional loop which tests each byte, we will test a + longword at a time. The tricky part is testing if *any of the four* + bytes in the longword in question are equal to c. We first use an xor + with repeated_c. This reduces the task to testing whether *any of the + four* bytes in longword1 is zero. + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + So, the test whether any byte in longword1 is zero is equivalent to + testing whether tmp is nonzero. */ + + while (n >= sizeof (longword)) + { + longword longword1 = *--longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) + & (repeated_one << 7)) != 0) + { + longword_ptr++; + break; + } + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + /* At this point, we know that either n < sizeof (longword), or one of the + sizeof (longword) bytes starting at char_ptr is == c. On little-endian + machines, we could determine the first such byte without any further + memory accesses, just by looking at the tmp result from the last loop + iteration. But this does not work on big-endian machines. Choose code + that works in both cases. */ + + while (n-- > 0) + { + if (*--char_ptr == c) + return (void *) char_ptr; + } + + return NULL; +} +#ifdef weak_alias +weak_alias (__memrchr, memrchr) +#endif diff --git a/cross/lib/memset_explicit.c b/cross/lib/memset_explicit.c new file mode 100644 index 00000000000..6d21a5e8797 --- /dev/null +++ b/cross/lib/memset_explicit.c @@ -0,0 +1,55 @@ +/* Erase sensitive data from memory. + Copyright 2022-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* memset_s need this define */ +#if HAVE_MEMSET_S +# define __STDC_WANT_LIB_EXT1__ 1 +#endif + +#include + +/* Set S's bytes to C, where S has LEN bytes. The compiler will not + optimize effects away, even if S is dead after the call. */ +void * +memset_explicit (void *s, int c, size_t len) +{ +#if HAVE_EXPLICIT_MEMSET + return explicit_memset (s, c, len); +#elif HAVE_MEMSET_S + (void) memset_s (s, len, c, len); + return s; +#elif defined __GNUC__ && !defined __clang__ + memset (s, c, len); + /* Compiler barrier. */ + __asm__ volatile ("" ::: "memory"); + return s; +#elif defined __clang__ + memset (s, c, len); + /* Compiler barrier. */ + /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the + whole thing is dead and eliminates it. Use 'g' to work around this + problem. See . */ + __asm__ volatile ("" : : "g"(s) : "memory"); + return s; +#else + /* Invoke memset through a volatile function pointer. This defeats compiler + optimizations. */ + void * (* const volatile volatile_memset) (void *, int, size_t) = memset; + return volatile_memset (s, c, len); +#endif +} diff --git a/cross/lib/min-max.h b/cross/lib/min-max.h new file mode 100644 index 00000000000..997cdd191eb --- /dev/null +++ b/cross/lib/min-max.h @@ -0,0 +1,6 @@ +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +#endif diff --git a/cross/lib/mini-gmp-gnulib.c b/cross/lib/mini-gmp-gnulib.c new file mode 100644 index 00000000000..b15ce0ff754 --- /dev/null +++ b/cross/lib/mini-gmp-gnulib.c @@ -0,0 +1,48 @@ +/* Tailor mini-gmp.c for Gnulib-using applications. + + Copyright 2018-2023 Free Software Foundation, Inc. + + This file is free software. + It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+". + You can redistribute it and/or modify it under either + - the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3, or (at your + option) any later version, or + - the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) + any later version, or + - the same dual license "the GNU LGPLv3+ or the GNU GPLv2+". + + This file is distributed in the hope that 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 and the GNU General Public License + for more details. + + You should have received a copy of the GNU Lesser General Public + License and of the GNU General Public License along with this + program. If not, see . */ + +#include + +#include +#include + +#include "mini-gmp.h" + +/* Pacify GCC -Wsuggest-attribute=const, pure, malloc. */ +#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +#endif +#if 8 <= __GNUC__ +# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc" +#endif + +/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */ +#if (defined NDEBUG \ + && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__)) +# pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#include "mini-gmp.c" diff --git a/cross/lib/mini-gmp.c b/cross/lib/mini-gmp.c new file mode 100644 index 00000000000..ea037b801dc --- /dev/null +++ b/cross/lib/mini-gmp.c @@ -0,0 +1,4620 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + + Contributed to the GNU project by Niels Möller + Additional functionalities and improvements by Marco Bodrato. + +Copyright 1991-1997, 1999-2022 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP 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 General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +/* NOTE: All functions in this file which are not declared in + mini-gmp.h are internal, and are not intended to be compatible + with GMP or with future versions of mini-gmp. */ + +/* Much of the material copied from GMP files, including: gmp-impl.h, + longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c, + mpn/generic/lshift.c, mpn/generic/mul_1.c, + mpn/generic/mul_basecase.c, mpn/generic/rshift.c, + mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c, + mpn/generic/submul_1.c. */ + +#include +#include +#include +#include +#include +#include + +#include "mini-gmp.h" + +#if !defined(MINI_GMP_DONT_USE_FLOAT_H) +#include +#endif + + +/* Macros */ +#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) + +#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0) +#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)) + +#define GMP_HLIMB_BIT ((mp_limb_t) 1 << (GMP_LIMB_BITS / 2)) +#define GMP_LLIMB_MASK (GMP_HLIMB_BIT - 1) + +#define GMP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT) +#define GMP_ULONG_HIGHBIT ((unsigned long) 1 << (GMP_ULONG_BITS - 1)) + +#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1)) + +#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b))) + +#if defined(DBL_MANT_DIG) && FLT_RADIX == 2 +#define GMP_DBL_MANT_BITS DBL_MANT_DIG +#else +#define GMP_DBL_MANT_BITS (53) +#endif + +/* Return non-zero if xp,xsize and yp,ysize overlap. + If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no + overlap. If both these are false, there's an overlap. */ +#define GMP_MPN_OVERLAP_P(xp, xsize, yp, ysize) \ + ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp)) + +#define gmp_assert_nocarry(x) do { \ + mp_limb_t __cy = (x); \ + assert (__cy == 0); \ + (void) (__cy); \ + } while (0) + +#define gmp_clz(count, x) do { \ + mp_limb_t __clz_x = (x); \ + unsigned __clz_c = 0; \ + int LOCAL_SHIFT_BITS = 8; \ + if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) \ + for (; \ + (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \ + __clz_c += 8) \ + { __clz_x <<= LOCAL_SHIFT_BITS; } \ + for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \ + __clz_x <<= 1; \ + (count) = __clz_c; \ + } while (0) + +#define gmp_ctz(count, x) do { \ + mp_limb_t __ctz_x = (x); \ + unsigned __ctz_c = 0; \ + gmp_clz (__ctz_c, __ctz_x & - __ctz_x); \ + (count) = GMP_LIMB_BITS - 1 - __ctz_c; \ + } while (0) + +#define gmp_add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + mp_limb_t __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) + +#define gmp_sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + mp_limb_t __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - ((al) < (bl)); \ + (sl) = __x; \ + } while (0) + +#define gmp_umul_ppmm(w1, w0, u, v) \ + do { \ + int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; \ + if (sizeof(unsigned int) * CHAR_BIT >= 2 * GMP_LIMB_BITS) \ + { \ + unsigned int __ww = (unsigned int) (u) * (v); \ + w0 = (mp_limb_t) __ww; \ + w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \ + } \ + else if (GMP_ULONG_BITS >= 2 * GMP_LIMB_BITS) \ + { \ + unsigned long int __ww = (unsigned long int) (u) * (v); \ + w0 = (mp_limb_t) __ww; \ + w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \ + } \ + else { \ + mp_limb_t __x0, __x1, __x2, __x3; \ + unsigned __ul, __vl, __uh, __vh; \ + mp_limb_t __u = (u), __v = (v); \ + assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); \ + \ + __ul = __u & GMP_LLIMB_MASK; \ + __uh = __u >> (GMP_LIMB_BITS / 2); \ + __vl = __v & GMP_LLIMB_MASK; \ + __vh = __v >> (GMP_LIMB_BITS / 2); \ + \ + __x0 = (mp_limb_t) __ul * __vl; \ + __x1 = (mp_limb_t) __ul * __vh; \ + __x2 = (mp_limb_t) __uh * __vl; \ + __x3 = (mp_limb_t) __uh * __vh; \ + \ + __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \ + (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \ + } \ + } while (0) + +#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ + do { \ + mp_limb_t _qh, _ql, _r, _mask; \ + gmp_umul_ppmm (_qh, _ql, (nh), (di)); \ + gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \ + _r = (nl) - _qh * (d); \ + _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ + _qh += _mask; \ + _r += _mask & (d); \ + if (_r >= (d)) \ + { \ + _r -= (d); \ + _qh++; \ + } \ + \ + (r) = _r; \ + (q) = _qh; \ + } while (0) + +#define gmp_udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \ + do { \ + mp_limb_t _q0, _t1, _t0, _mask; \ + gmp_umul_ppmm ((q), _q0, (n2), (dinv)); \ + gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \ + \ + /* Compute the two most significant limbs of n - q'd */ \ + (r1) = (n1) - (d1) * (q); \ + gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \ + gmp_umul_ppmm (_t1, _t0, (d0), (q)); \ + gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \ + (q)++; \ + \ + /* Conditionally adjust q and the remainders */ \ + _mask = - (mp_limb_t) ((r1) >= _q0); \ + (q) += _mask; \ + gmp_add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \ + if ((r1) >= (d1)) \ + { \ + if ((r1) > (d1) || (r0) >= (d0)) \ + { \ + (q)++; \ + gmp_sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ + } \ + } \ + } while (0) + +/* Swap macros. */ +#define MP_LIMB_T_SWAP(x, y) \ + do { \ + mp_limb_t __mp_limb_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_limb_t_swap__tmp; \ + } while (0) +#define MP_SIZE_T_SWAP(x, y) \ + do { \ + mp_size_t __mp_size_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_size_t_swap__tmp; \ + } while (0) +#define MP_BITCNT_T_SWAP(x,y) \ + do { \ + mp_bitcnt_t __mp_bitcnt_t_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_bitcnt_t_swap__tmp; \ + } while (0) +#define MP_PTR_SWAP(x, y) \ + do { \ + mp_ptr __mp_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_ptr_swap__tmp; \ + } while (0) +#define MP_SRCPTR_SWAP(x, y) \ + do { \ + mp_srcptr __mp_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mp_srcptr_swap__tmp; \ + } while (0) + +#define MPN_PTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_PTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) +#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \ + do { \ + MP_SRCPTR_SWAP (xp, yp); \ + MP_SIZE_T_SWAP (xs, ys); \ + } while(0) + +#define MPZ_PTR_SWAP(x, y) \ + do { \ + mpz_ptr __mpz_ptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_ptr_swap__tmp; \ + } while (0) +#define MPZ_SRCPTR_SWAP(x, y) \ + do { \ + mpz_srcptr __mpz_srcptr_swap__tmp = (x); \ + (x) = (y); \ + (y) = __mpz_srcptr_swap__tmp; \ + } while (0) + +const int mp_bits_per_limb = GMP_LIMB_BITS; + + +/* Memory allocation and other helper functions. */ +static void +gmp_die (const char *msg) +{ + fprintf (stderr, "%s\n", msg); + abort(); +} + +static void * +gmp_default_alloc (size_t size) +{ + void *p; + + assert (size > 0); + + p = malloc (size); + if (!p) + gmp_die("gmp_default_alloc: Virtual memory exhausted."); + + return p; +} + +static void * +gmp_default_realloc (void *old, size_t unused_old_size, size_t new_size) +{ + void * p; + + p = realloc (old, new_size); + + if (!p) + gmp_die("gmp_default_realloc: Virtual memory exhausted."); + + return p; +} + +static void +gmp_default_free (void *p, size_t unused_size) +{ + free (p); +} + +static void * (*gmp_allocate_func) (size_t) = gmp_default_alloc; +static void * (*gmp_reallocate_func) (void *, size_t, size_t) = gmp_default_realloc; +static void (*gmp_free_func) (void *, size_t) = gmp_default_free; + +void +mp_get_memory_functions (void *(**alloc_func) (size_t), + void *(**realloc_func) (void *, size_t, size_t), + void (**free_func) (void *, size_t)) +{ + if (alloc_func) + *alloc_func = gmp_allocate_func; + + if (realloc_func) + *realloc_func = gmp_reallocate_func; + + if (free_func) + *free_func = gmp_free_func; +} + +void +mp_set_memory_functions (void *(*alloc_func) (size_t), + void *(*realloc_func) (void *, size_t, size_t), + void (*free_func) (void *, size_t)) +{ + if (!alloc_func) + alloc_func = gmp_default_alloc; + if (!realloc_func) + realloc_func = gmp_default_realloc; + if (!free_func) + free_func = gmp_default_free; + + gmp_allocate_func = alloc_func; + gmp_reallocate_func = realloc_func; + gmp_free_func = free_func; +} + +#define gmp_alloc(size) ((*gmp_allocate_func)((size))) +#define gmp_free(p, size) ((*gmp_free_func) ((p), (size))) +#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size)) + +static mp_ptr +gmp_alloc_limbs (mp_size_t size) +{ + return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t)); +} + +static mp_ptr +gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size) +{ + assert (size > 0); + return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t)); +} + +static void +gmp_free_limbs (mp_ptr old, mp_size_t size) +{ + gmp_free (old, size * sizeof (mp_limb_t)); +} + + +/* MPN interface */ + +void +mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n) +{ + mp_size_t i; + for (i = 0; i < n; i++) + d[i] = s[i]; +} + +void +mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n) +{ + while (--n >= 0) + d[n] = s[n]; +} + +int +mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + while (--n >= 0) + { + if (ap[n] != bp[n]) + return ap[n] > bp[n] ? 1 : -1; + } + return 0; +} + +static int +mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + if (an != bn) + return an < bn ? -1 : 1; + else + return mpn_cmp (ap, bp, an); +} + +static mp_size_t +mpn_normalized_size (mp_srcptr xp, mp_size_t n) +{ + while (n > 0 && xp[n-1] == 0) + --n; + return n; +} + +int +mpn_zero_p(mp_srcptr rp, mp_size_t n) +{ + return mpn_normalized_size (rp, n) == 0; +} + +void +mpn_zero (mp_ptr rp, mp_size_t n) +{ + while (--n >= 0) + rp[n] = 0; +} + +mp_limb_t +mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) +{ + mp_size_t i; + + assert (n > 0); + i = 0; + do + { + mp_limb_t r = ap[i] + b; + /* Carry out */ + b = (r < b); + rp[i] = r; + } + while (++i < n); + + return b; +} + +mp_limb_t +mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mp_size_t i; + mp_limb_t cy; + + for (i = 0, cy = 0; i < n; i++) + { + mp_limb_t a, b, r; + a = ap[i]; b = bp[i]; + r = a + cy; + cy = (r < cy); + r += b; + cy += (r < b); + rp[i] = r; + } + return cy; +} + +mp_limb_t +mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + mp_limb_t cy; + + assert (an >= bn); + + cy = mpn_add_n (rp, ap, bp, bn); + if (an > bn) + cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy); + return cy; +} + +mp_limb_t +mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) +{ + mp_size_t i; + + assert (n > 0); + + i = 0; + do + { + mp_limb_t a = ap[i]; + /* Carry out */ + mp_limb_t cy = a < b; + rp[i] = a - b; + b = cy; + } + while (++i < n); + + return b; +} + +mp_limb_t +mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mp_size_t i; + mp_limb_t cy; + + for (i = 0, cy = 0; i < n; i++) + { + mp_limb_t a, b; + a = ap[i]; b = bp[i]; + b += cy; + cy = (b < cy); + cy += (a < b); + rp[i] = a - b; + } + return cy; +} + +mp_limb_t +mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) +{ + mp_limb_t cy; + + assert (an >= bn); + + cy = mpn_sub_n (rp, ap, bp, bn); + if (an > bn) + cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy); + return cy; +} + +mp_limb_t +mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl, rl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + rl = *rp; + lpl = rl + lpl; + cl += lpl < rl; + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) +{ + mp_limb_t ul, cl, hpl, lpl, rl; + + assert (n >= 1); + + cl = 0; + do + { + ul = *up++; + gmp_umul_ppmm (hpl, lpl, ul, vl); + + lpl += cl; + cl = (lpl < cl) + hpl; + + rl = *rp; + lpl = rl - lpl; + cl += lpl > rl; + *rp++ = lpl; + } + while (--n != 0); + + return cl; +} + +mp_limb_t +mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn) +{ + assert (un >= vn); + assert (vn >= 1); + assert (!GMP_MPN_OVERLAP_P(rp, un + vn, up, un)); + assert (!GMP_MPN_OVERLAP_P(rp, un + vn, vp, vn)); + + /* We first multiply by the low order limb. This result can be + stored, not added, to rp. We also avoid a loop for zeroing this + way. */ + + rp[un] = mpn_mul_1 (rp, up, un, vp[0]); + + /* Now accumulate the product of up[] and the next higher limb from + vp[]. */ + + while (--vn >= 1) + { + rp += 1, vp += 1; + rp[un] = mpn_addmul_1 (rp, up, un, vp[0]); + } + return rp[un]; +} + +void +mpn_mul_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) +{ + mpn_mul (rp, ap, n, bp, n); +} + +void +mpn_sqr (mp_ptr rp, mp_srcptr ap, mp_size_t n) +{ + mpn_mul (rp, ap, n, ap, n); +} + +mp_limb_t +mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) +{ + mp_limb_t high_limb, low_limb; + unsigned int tnc; + mp_limb_t retval; + + assert (n >= 1); + assert (cnt >= 1); + assert (cnt < GMP_LIMB_BITS); + + up += n; + rp += n; + + tnc = GMP_LIMB_BITS - cnt; + low_limb = *--up; + retval = low_limb >> tnc; + high_limb = (low_limb << cnt); + + while (--n != 0) + { + low_limb = *--up; + *--rp = high_limb | (low_limb >> tnc); + high_limb = (low_limb << cnt); + } + *--rp = high_limb; + + return retval; +} + +mp_limb_t +mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) +{ + mp_limb_t high_limb, low_limb; + unsigned int tnc; + mp_limb_t retval; + + assert (n >= 1); + assert (cnt >= 1); + assert (cnt < GMP_LIMB_BITS); + + tnc = GMP_LIMB_BITS - cnt; + high_limb = *up++; + retval = (high_limb << tnc); + low_limb = high_limb >> cnt; + + while (--n != 0) + { + high_limb = *up++; + *rp++ = low_limb | (high_limb << tnc); + low_limb = high_limb >> cnt; + } + *rp = low_limb; + + return retval; +} + +static mp_bitcnt_t +mpn_common_scan (mp_limb_t limb, mp_size_t i, mp_srcptr up, mp_size_t un, + mp_limb_t ux) +{ + unsigned cnt; + + assert (ux == 0 || ux == GMP_LIMB_MAX); + assert (0 <= i && i <= un ); + + while (limb == 0) + { + i++; + if (i == un) + return (ux == 0 ? ~(mp_bitcnt_t) 0 : un * GMP_LIMB_BITS); + limb = ux ^ up[i]; + } + gmp_ctz (cnt, limb); + return (mp_bitcnt_t) i * GMP_LIMB_BITS + cnt; +} + +mp_bitcnt_t +mpn_scan1 (mp_srcptr ptr, mp_bitcnt_t bit) +{ + mp_size_t i; + i = bit / GMP_LIMB_BITS; + + return mpn_common_scan ( ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), + i, ptr, i, 0); +} + +mp_bitcnt_t +mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit) +{ + mp_size_t i; + i = bit / GMP_LIMB_BITS; + + return mpn_common_scan (~ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), + i, ptr, i, GMP_LIMB_MAX); +} + +void +mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n) +{ + while (--n >= 0) + *rp++ = ~ *up++; +} + +mp_limb_t +mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n) +{ + while (*up == 0) + { + *rp = 0; + if (!--n) + return 0; + ++up; ++rp; + } + *rp = - *up; + mpn_com (++rp, ++up, --n); + return 1; +} + + +/* MPN division interface. */ + +/* The 3/2 inverse is defined as + + m = floor( (B^3-1) / (B u1 + u0)) - B +*/ +mp_limb_t +mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0) +{ + mp_limb_t r, m; + + { + mp_limb_t p, ql; + unsigned ul, uh, qh; + + assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); + /* For notation, let b denote the half-limb base, so that B = b^2. + Split u1 = b uh + ul. */ + ul = u1 & GMP_LLIMB_MASK; + uh = u1 >> (GMP_LIMB_BITS / 2); + + /* Approximation of the high half of quotient. Differs from the 2/1 + inverse of the half limb uh, since we have already subtracted + u0. */ + qh = (u1 ^ GMP_LIMB_MAX) / uh; + + /* Adjust to get a half-limb 3/2 inverse, i.e., we want + + qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u + = floor( (b (~u) + b-1) / u), + + and the remainder + + r = b (~u) + b-1 - qh (b uh + ul) + = b (~u - qh uh) + b-1 - qh ul + + Subtraction of qh ul may underflow, which implies adjustments. + But by normalization, 2 u >= B > qh ul, so we need to adjust by + at most 2. + */ + + r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK; + + p = (mp_limb_t) qh * ul; + /* Adjustment steps taken from udiv_qrnnd_c */ + if (r < p) + { + qh--; + r += u1; + if (r >= u1) /* i.e. we didn't get carry when adding to r */ + if (r < p) + { + qh--; + r += u1; + } + } + r -= p; + + /* Low half of the quotient is + + ql = floor ( (b r + b-1) / u1). + + This is a 3/2 division (on half-limbs), for which qh is a + suitable inverse. */ + + p = (r >> (GMP_LIMB_BITS / 2)) * qh + r; + /* Unlike full-limb 3/2, we can add 1 without overflow. For this to + work, it is essential that ql is a full mp_limb_t. */ + ql = (p >> (GMP_LIMB_BITS / 2)) + 1; + + /* By the 3/2 trick, we don't need the high half limb. */ + r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1; + + if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2)))) + { + ql--; + r += u1; + } + m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql; + if (r >= u1) + { + m++; + r -= u1; + } + } + + /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a + 3/2 inverse. */ + if (u0 > 0) + { + mp_limb_t th, tl; + r = ~r; + r += u0; + if (r < u0) + { + m--; + if (r >= u1) + { + m--; + r -= u1; + } + r -= u1; + } + gmp_umul_ppmm (th, tl, u0, m); + r += th; + if (r < th) + { + m--; + m -= ((r > u1) | ((r == u1) & (tl > u0))); + } + } + + return m; +} + +struct gmp_div_inverse +{ + /* Normalization shift count. */ + unsigned shift; + /* Normalized divisor (d0 unused for mpn_div_qr_1) */ + mp_limb_t d1, d0; + /* Inverse, for 2/1 or 3/2. */ + mp_limb_t di; +}; + +static void +mpn_div_qr_1_invert (struct gmp_div_inverse *inv, mp_limb_t d) +{ + unsigned shift; + + assert (d > 0); + gmp_clz (shift, d); + inv->shift = shift; + inv->d1 = d << shift; + inv->di = mpn_invert_limb (inv->d1); +} + +static void +mpn_div_qr_2_invert (struct gmp_div_inverse *inv, + mp_limb_t d1, mp_limb_t d0) +{ + unsigned shift; + + assert (d1 > 0); + gmp_clz (shift, d1); + inv->shift = shift; + if (shift > 0) + { + d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); + d0 <<= shift; + } + inv->d1 = d1; + inv->d0 = d0; + inv->di = mpn_invert_3by2 (d1, d0); +} + +static void +mpn_div_qr_invert (struct gmp_div_inverse *inv, + mp_srcptr dp, mp_size_t dn) +{ + assert (dn > 0); + + if (dn == 1) + mpn_div_qr_1_invert (inv, dp[0]); + else if (dn == 2) + mpn_div_qr_2_invert (inv, dp[1], dp[0]); + else + { + unsigned shift; + mp_limb_t d1, d0; + + d1 = dp[dn-1]; + d0 = dp[dn-2]; + assert (d1 > 0); + gmp_clz (shift, d1); + inv->shift = shift; + if (shift > 0) + { + d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); + d0 = (d0 << shift) | (dp[dn-3] >> (GMP_LIMB_BITS - shift)); + } + inv->d1 = d1; + inv->d0 = d0; + inv->di = mpn_invert_3by2 (d1, d0); + } +} + +/* Not matching current public gmp interface, rather corresponding to + the sbpi1_div_* functions. */ +static mp_limb_t +mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn, + const struct gmp_div_inverse *inv) +{ + mp_limb_t d, di; + mp_limb_t r; + mp_ptr tp = NULL; + mp_size_t tn = 0; + + if (inv->shift > 0) + { + /* Shift, reusing qp area if possible. In-place shift if qp == np. */ + tp = qp; + if (!tp) + { + tn = nn; + tp = gmp_alloc_limbs (tn); + } + r = mpn_lshift (tp, np, nn, inv->shift); + np = tp; + } + else + r = 0; + + d = inv->d1; + di = inv->di; + while (--nn >= 0) + { + mp_limb_t q; + + gmp_udiv_qrnnd_preinv (q, r, r, np[nn], d, di); + if (qp) + qp[nn] = q; + } + if (tn) + gmp_free_limbs (tp, tn); + + return r >> inv->shift; +} + +static void +mpn_div_qr_2_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn, + const struct gmp_div_inverse *inv) +{ + unsigned shift; + mp_size_t i; + mp_limb_t d1, d0, di, r1, r0; + + assert (nn >= 2); + shift = inv->shift; + d1 = inv->d1; + d0 = inv->d0; + di = inv->di; + + if (shift > 0) + r1 = mpn_lshift (np, np, nn, shift); + else + r1 = 0; + + r0 = np[nn - 1]; + + i = nn - 2; + do + { + mp_limb_t n0, q; + n0 = np[i]; + gmp_udiv_qr_3by2 (q, r1, r0, r1, r0, n0, d1, d0, di); + + if (qp) + qp[i] = q; + } + while (--i >= 0); + + if (shift > 0) + { + assert ((r0 & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - shift))) == 0); + r0 = (r0 >> shift) | (r1 << (GMP_LIMB_BITS - shift)); + r1 >>= shift; + } + + np[1] = r1; + np[0] = r0; +} + +static void +mpn_div_qr_pi1 (mp_ptr qp, + mp_ptr np, mp_size_t nn, mp_limb_t n1, + mp_srcptr dp, mp_size_t dn, + mp_limb_t dinv) +{ + mp_size_t i; + + mp_limb_t d1, d0; + mp_limb_t cy, cy1; + mp_limb_t q; + + assert (dn > 2); + assert (nn >= dn); + + d1 = dp[dn - 1]; + d0 = dp[dn - 2]; + + assert ((d1 & GMP_LIMB_HIGHBIT) != 0); + /* Iteration variable is the index of the q limb. + * + * We divide + * by + */ + + i = nn - dn; + do + { + mp_limb_t n0 = np[dn-1+i]; + + if (n1 == d1 && n0 == d0) + { + q = GMP_LIMB_MAX; + mpn_submul_1 (np+i, dp, dn, q); + n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */ + } + else + { + gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv); + + cy = mpn_submul_1 (np + i, dp, dn-2, q); + + cy1 = n0 < cy; + n0 = n0 - cy; + cy = n1 < cy1; + n1 = n1 - cy1; + np[dn-2+i] = n0; + + if (cy != 0) + { + n1 += d1 + mpn_add_n (np + i, np + i, dp, dn - 1); + q--; + } + } + + if (qp) + qp[i] = q; + } + while (--i >= 0); + + np[dn - 1] = n1; +} + +static void +mpn_div_qr_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn, + mp_srcptr dp, mp_size_t dn, + const struct gmp_div_inverse *inv) +{ + assert (dn > 0); + assert (nn >= dn); + + if (dn == 1) + np[0] = mpn_div_qr_1_preinv (qp, np, nn, inv); + else if (dn == 2) + mpn_div_qr_2_preinv (qp, np, nn, inv); + else + { + mp_limb_t nh; + unsigned shift; + + assert (inv->d1 == dp[dn-1]); + assert (inv->d0 == dp[dn-2]); + assert ((inv->d1 & GMP_LIMB_HIGHBIT) != 0); + + shift = inv->shift; + if (shift > 0) + nh = mpn_lshift (np, np, nn, shift); + else + nh = 0; + + mpn_div_qr_pi1 (qp, np, nn, nh, dp, dn, inv->di); + + if (shift > 0) + gmp_assert_nocarry (mpn_rshift (np, np, dn, shift)); + } +} + +static void +mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn) +{ + struct gmp_div_inverse inv; + mp_ptr tp = NULL; + + assert (dn > 0); + assert (nn >= dn); + + mpn_div_qr_invert (&inv, dp, dn); + if (dn > 2 && inv.shift > 0) + { + tp = gmp_alloc_limbs (dn); + gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift)); + dp = tp; + } + mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv); + if (tp) + gmp_free_limbs (tp, dn); +} + + +/* MPN base conversion. */ +static unsigned +mpn_base_power_of_two_p (unsigned b) +{ + switch (b) + { + case 2: return 1; + case 4: return 2; + case 8: return 3; + case 16: return 4; + case 32: return 5; + case 64: return 6; + case 128: return 7; + case 256: return 8; + default: return 0; + } +} + +struct mpn_base_info +{ + /* bb is the largest power of the base which fits in one limb, and + exp is the corresponding exponent. */ + unsigned exp; + mp_limb_t bb; +}; + +static void +mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b) +{ + mp_limb_t m; + mp_limb_t p; + unsigned exp; + + m = GMP_LIMB_MAX / b; + for (exp = 1, p = b; p <= m; exp++) + p *= b; + + info->exp = exp; + info->bb = p; +} + +static mp_bitcnt_t +mpn_limb_size_in_base_2 (mp_limb_t u) +{ + unsigned shift; + + assert (u > 0); + gmp_clz (shift, u); + return GMP_LIMB_BITS - shift; +} + +static size_t +mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un) +{ + unsigned char mask; + size_t sn, j; + mp_size_t i; + unsigned shift; + + sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]) + + bits - 1) / bits; + + mask = (1U << bits) - 1; + + for (i = 0, j = sn, shift = 0; j-- > 0;) + { + unsigned char digit = up[i] >> shift; + + shift += bits; + + if (shift >= GMP_LIMB_BITS && ++i < un) + { + shift -= GMP_LIMB_BITS; + digit |= up[i] << (bits - shift); + } + sp[j] = digit & mask; + } + return sn; +} + +/* We generate digits from the least significant end, and reverse at + the end. */ +static size_t +mpn_limb_get_str (unsigned char *sp, mp_limb_t w, + const struct gmp_div_inverse *binv) +{ + mp_size_t i; + for (i = 0; w > 0; i++) + { + mp_limb_t h, l, r; + + h = w >> (GMP_LIMB_BITS - binv->shift); + l = w << binv->shift; + + gmp_udiv_qrnnd_preinv (w, r, h, l, binv->d1, binv->di); + assert ((r & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - binv->shift))) == 0); + r >>= binv->shift; + + sp[i] = r; + } + return i; +} + +static size_t +mpn_get_str_other (unsigned char *sp, + int base, const struct mpn_base_info *info, + mp_ptr up, mp_size_t un) +{ + struct gmp_div_inverse binv; + size_t sn; + size_t i; + + mpn_div_qr_1_invert (&binv, base); + + sn = 0; + + if (un > 1) + { + struct gmp_div_inverse bbinv; + mpn_div_qr_1_invert (&bbinv, info->bb); + + do + { + mp_limb_t w; + size_t done; + w = mpn_div_qr_1_preinv (up, up, un, &bbinv); + un -= (up[un-1] == 0); + done = mpn_limb_get_str (sp + sn, w, &binv); + + for (sn += done; done < info->exp; done++) + sp[sn++] = 0; + } + while (un > 1); + } + sn += mpn_limb_get_str (sp + sn, up[0], &binv); + + /* Reverse order */ + for (i = 0; 2*i + 1 < sn; i++) + { + unsigned char t = sp[i]; + sp[i] = sp[sn - i - 1]; + sp[sn - i - 1] = t; + } + + return sn; +} + +size_t +mpn_get_str (unsigned char *sp, int base, mp_ptr up, mp_size_t un) +{ + unsigned bits; + + assert (un > 0); + assert (up[un-1] > 0); + + bits = mpn_base_power_of_two_p (base); + if (bits) + return mpn_get_str_bits (sp, bits, up, un); + else + { + struct mpn_base_info info; + + mpn_get_base_info (&info, base); + return mpn_get_str_other (sp, base, &info, up, un); + } +} + +static mp_size_t +mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn, + unsigned bits) +{ + mp_size_t rn; + mp_limb_t limb; + unsigned shift; + + for (limb = 0, rn = 0, shift = 0; sn-- > 0; ) + { + limb |= (mp_limb_t) sp[sn] << shift; + shift += bits; + if (shift >= GMP_LIMB_BITS) + { + shift -= GMP_LIMB_BITS; + rp[rn++] = limb; + /* Next line is correct also if shift == 0, + bits == 8, and mp_limb_t == unsigned char. */ + limb = (unsigned int) sp[sn] >> (bits - shift); + } + } + if (limb != 0) + rp[rn++] = limb; + else + rn = mpn_normalized_size (rp, rn); + return rn; +} + +/* Result is usually normalized, except for all-zero input, in which + case a single zero limb is written at *RP, and 1 is returned. */ +static mp_size_t +mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn, + mp_limb_t b, const struct mpn_base_info *info) +{ + mp_size_t rn; + mp_limb_t w; + unsigned k; + size_t j; + + assert (sn > 0); + + k = 1 + (sn - 1) % info->exp; + + j = 0; + w = sp[j++]; + while (--k != 0) + w = w * b + sp[j++]; + + rp[0] = w; + + for (rn = 1; j < sn;) + { + mp_limb_t cy; + + w = sp[j++]; + for (k = 1; k < info->exp; k++) + w = w * b + sp[j++]; + + cy = mpn_mul_1 (rp, rp, rn, info->bb); + cy += mpn_add_1 (rp, rp, rn, w); + if (cy > 0) + rp[rn++] = cy; + } + assert (j == sn); + + return rn; +} + +mp_size_t +mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base) +{ + unsigned bits; + + if (sn == 0) + return 0; + + bits = mpn_base_power_of_two_p (base); + if (bits) + return mpn_set_str_bits (rp, sp, sn, bits); + else + { + struct mpn_base_info info; + + mpn_get_base_info (&info, base); + return mpn_set_str_other (rp, sp, sn, base, &info); + } +} + + +/* MPZ interface */ +void +mpz_init (mpz_t r) +{ + static const mp_limb_t dummy_limb = GMP_LIMB_MAX & 0xc1a0; + + r->_mp_alloc = 0; + r->_mp_size = 0; + r->_mp_d = (mp_ptr) &dummy_limb; +} + +/* The utility of this function is a bit limited, since many functions + assigns the result variable using mpz_swap. */ +void +mpz_init2 (mpz_t r, mp_bitcnt_t bits) +{ + mp_size_t rn; + + bits -= (bits != 0); /* Round down, except if 0 */ + rn = 1 + bits / GMP_LIMB_BITS; + + r->_mp_alloc = rn; + r->_mp_size = 0; + r->_mp_d = gmp_alloc_limbs (rn); +} + +void +mpz_clear (mpz_t r) +{ + if (r->_mp_alloc) + gmp_free_limbs (r->_mp_d, r->_mp_alloc); +} + +static mp_ptr +mpz_realloc (mpz_t r, mp_size_t size) +{ + size = GMP_MAX (size, 1); + + if (r->_mp_alloc) + r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size); + else + r->_mp_d = gmp_alloc_limbs (size); + r->_mp_alloc = size; + + if (GMP_ABS (r->_mp_size) > size) + r->_mp_size = 0; + + return r->_mp_d; +} + +/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */ +#define MPZ_REALLOC(z,n) ((n) > (z)->_mp_alloc \ + ? mpz_realloc(z,n) \ + : (z)->_mp_d) + +/* MPZ assignment and basic conversions. */ +void +mpz_set_si (mpz_t r, signed long int x) +{ + if (x >= 0) + mpz_set_ui (r, x); + else /* (x < 0) */ + if (GMP_LIMB_BITS < GMP_ULONG_BITS) + { + mpz_set_ui (r, GMP_NEG_CAST (unsigned long int, x)); + mpz_neg (r, r); + } + else + { + r->_mp_size = -1; + MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x); + } +} + +void +mpz_set_ui (mpz_t r, unsigned long int x) +{ + if (x > 0) + { + r->_mp_size = 1; + MPZ_REALLOC (r, 1)[0] = x; + if (GMP_LIMB_BITS < GMP_ULONG_BITS) + { + int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; + while (x >>= LOCAL_GMP_LIMB_BITS) + { + ++ r->_mp_size; + MPZ_REALLOC (r, r->_mp_size)[r->_mp_size - 1] = x; + } + } + } + else + r->_mp_size = 0; +} + +void +mpz_set (mpz_t r, const mpz_t x) +{ + /* Allow the NOP r == x */ + if (r != x) + { + mp_size_t n; + mp_ptr rp; + + n = GMP_ABS (x->_mp_size); + rp = MPZ_REALLOC (r, n); + + mpn_copyi (rp, x->_mp_d, n); + r->_mp_size = x->_mp_size; + } +} + +void +mpz_init_set_si (mpz_t r, signed long int x) +{ + mpz_init (r); + mpz_set_si (r, x); +} + +void +mpz_init_set_ui (mpz_t r, unsigned long int x) +{ + mpz_init (r); + mpz_set_ui (r, x); +} + +void +mpz_init_set (mpz_t r, const mpz_t x) +{ + mpz_init (r); + mpz_set (r, x); +} + +int +mpz_fits_slong_p (const mpz_t u) +{ + return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0; +} + +static int +mpn_absfits_ulong_p (mp_srcptr up, mp_size_t un) +{ + int ulongsize = GMP_ULONG_BITS / GMP_LIMB_BITS; + mp_limb_t ulongrem = 0; + + if (GMP_ULONG_BITS % GMP_LIMB_BITS != 0) + ulongrem = (mp_limb_t) (ULONG_MAX >> GMP_LIMB_BITS * ulongsize) + 1; + + return un <= ulongsize || (up[ulongsize] < ulongrem && un == ulongsize + 1); +} + +int +mpz_fits_ulong_p (const mpz_t u) +{ + mp_size_t us = u->_mp_size; + + return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us); +} + +int +mpz_fits_sint_p (const mpz_t u) +{ + return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0; +} + +int +mpz_fits_uint_p (const mpz_t u) +{ + return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0; +} + +int +mpz_fits_sshort_p (const mpz_t u) +{ + return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0; +} + +int +mpz_fits_ushort_p (const mpz_t u) +{ + return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0; +} + +long int +mpz_get_si (const mpz_t u) +{ + unsigned long r = mpz_get_ui (u); + unsigned long c = -LONG_MAX - LONG_MIN; + + if (u->_mp_size < 0) + /* This expression is necessary to properly handle -LONG_MIN */ + return -(long) c - (long) ((r - c) & LONG_MAX); + else + return (long) (r & LONG_MAX); +} + +unsigned long int +mpz_get_ui (const mpz_t u) +{ + if (GMP_LIMB_BITS < GMP_ULONG_BITS) + { + int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; + unsigned long r = 0; + mp_size_t n = GMP_ABS (u->_mp_size); + n = GMP_MIN (n, 1 + (mp_size_t) (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS); + while (--n >= 0) + r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n]; + return r; + } + + return u->_mp_size == 0 ? 0 : u->_mp_d[0]; +} + +size_t +mpz_size (const mpz_t u) +{ + return GMP_ABS (u->_mp_size); +} + +mp_limb_t +mpz_getlimbn (const mpz_t u, mp_size_t n) +{ + if (n >= 0 && n < GMP_ABS (u->_mp_size)) + return u->_mp_d[n]; + else + return 0; +} + +void +mpz_realloc2 (mpz_t x, mp_bitcnt_t n) +{ + mpz_realloc (x, 1 + (n - (n != 0)) / GMP_LIMB_BITS); +} + +mp_srcptr +mpz_limbs_read (mpz_srcptr x) +{ + return x->_mp_d; +} + +mp_ptr +mpz_limbs_modify (mpz_t x, mp_size_t n) +{ + assert (n > 0); + return MPZ_REALLOC (x, n); +} + +mp_ptr +mpz_limbs_write (mpz_t x, mp_size_t n) +{ + return mpz_limbs_modify (x, n); +} + +void +mpz_limbs_finish (mpz_t x, mp_size_t xs) +{ + mp_size_t xn; + xn = mpn_normalized_size (x->_mp_d, GMP_ABS (xs)); + x->_mp_size = xs < 0 ? -xn : xn; +} + +static mpz_srcptr +mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs) +{ + x->_mp_alloc = 0; + x->_mp_d = (mp_ptr) xp; + x->_mp_size = xs; + return x; +} + +mpz_srcptr +mpz_roinit_n (mpz_t x, mp_srcptr xp, mp_size_t xs) +{ + mpz_roinit_normal_n (x, xp, xs); + mpz_limbs_finish (x, xs); + return x; +} + + +/* Conversions and comparison to double. */ +void +mpz_set_d (mpz_t r, double x) +{ + int sign; + mp_ptr rp; + mp_size_t rn, i; + double B; + double Bi; + mp_limb_t f; + + /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is + zero or infinity. */ + if (x != x || x == x * 0.5) + { + r->_mp_size = 0; + return; + } + + sign = x < 0.0 ; + if (sign) + x = - x; + + if (x < 1.0) + { + r->_mp_size = 0; + return; + } + B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); + Bi = 1.0 / B; + for (rn = 1; x >= B; rn++) + x *= Bi; + + rp = MPZ_REALLOC (r, rn); + + f = (mp_limb_t) x; + x -= f; + assert (x < 1.0); + i = rn-1; + rp[i] = f; + while (--i >= 0) + { + x = B * x; + f = (mp_limb_t) x; + x -= f; + assert (x < 1.0); + rp[i] = f; + } + + r->_mp_size = sign ? - rn : rn; +} + +void +mpz_init_set_d (mpz_t r, double x) +{ + mpz_init (r); + mpz_set_d (r, x); +} + +double +mpz_get_d (const mpz_t u) +{ + int m; + mp_limb_t l; + mp_size_t un; + double x; + double B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); + + un = GMP_ABS (u->_mp_size); + + if (un == 0) + return 0.0; + + l = u->_mp_d[--un]; + gmp_clz (m, l); + m = m + GMP_DBL_MANT_BITS - GMP_LIMB_BITS; + if (m < 0) + l &= GMP_LIMB_MAX << -m; + + for (x = l; --un >= 0;) + { + x = B*x; + if (m > 0) { + l = u->_mp_d[un]; + m -= GMP_LIMB_BITS; + if (m < 0) + l &= GMP_LIMB_MAX << -m; + x += l; + } + } + + if (u->_mp_size < 0) + x = -x; + + return x; +} + +int +mpz_cmpabs_d (const mpz_t x, double d) +{ + mp_size_t xn; + double B, Bi; + mp_size_t i; + + xn = x->_mp_size; + d = GMP_ABS (d); + + if (xn != 0) + { + xn = GMP_ABS (xn); + + B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); + Bi = 1.0 / B; + + /* Scale d so it can be compared with the top limb. */ + for (i = 1; i < xn; i++) + d *= Bi; + + if (d >= B) + return -1; + + /* Compare floor(d) to top limb, subtract and cancel when equal. */ + for (i = xn; i-- > 0;) + { + mp_limb_t f, xl; + + f = (mp_limb_t) d; + xl = x->_mp_d[i]; + if (xl > f) + return 1; + else if (xl < f) + return -1; + d = B * (d - f); + } + } + return - (d > 0.0); +} + +int +mpz_cmp_d (const mpz_t x, double d) +{ + if (x->_mp_size < 0) + { + if (d >= 0.0) + return -1; + else + return -mpz_cmpabs_d (x, d); + } + else + { + if (d < 0.0) + return 1; + else + return mpz_cmpabs_d (x, d); + } +} + + +/* MPZ comparisons and the like. */ +int +mpz_sgn (const mpz_t u) +{ + return GMP_CMP (u->_mp_size, 0); +} + +int +mpz_cmp_si (const mpz_t u, long v) +{ + mp_size_t usize = u->_mp_size; + + if (v >= 0) + return mpz_cmp_ui (u, v); + else if (usize >= 0) + return 1; + else + return - mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, v)); +} + +int +mpz_cmp_ui (const mpz_t u, unsigned long v) +{ + mp_size_t usize = u->_mp_size; + + if (usize < 0) + return -1; + else + return mpz_cmpabs_ui (u, v); +} + +int +mpz_cmp (const mpz_t a, const mpz_t b) +{ + mp_size_t asize = a->_mp_size; + mp_size_t bsize = b->_mp_size; + + if (asize != bsize) + return (asize < bsize) ? -1 : 1; + else if (asize >= 0) + return mpn_cmp (a->_mp_d, b->_mp_d, asize); + else + return mpn_cmp (b->_mp_d, a->_mp_d, -asize); +} + +int +mpz_cmpabs_ui (const mpz_t u, unsigned long v) +{ + mp_size_t un = GMP_ABS (u->_mp_size); + + if (! mpn_absfits_ulong_p (u->_mp_d, un)) + return 1; + else + { + unsigned long uu = mpz_get_ui (u); + return GMP_CMP(uu, v); + } +} + +int +mpz_cmpabs (const mpz_t u, const mpz_t v) +{ + return mpn_cmp4 (u->_mp_d, GMP_ABS (u->_mp_size), + v->_mp_d, GMP_ABS (v->_mp_size)); +} + +void +mpz_abs (mpz_t r, const mpz_t u) +{ + mpz_set (r, u); + r->_mp_size = GMP_ABS (r->_mp_size); +} + +void +mpz_neg (mpz_t r, const mpz_t u) +{ + mpz_set (r, u); + r->_mp_size = -r->_mp_size; +} + +void +mpz_swap (mpz_t u, mpz_t v) +{ + MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc); + MPN_PTR_SWAP (u->_mp_d, u->_mp_size, v->_mp_d, v->_mp_size); +} + + +/* MPZ addition and subtraction */ + + +void +mpz_add_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + mpz_t bb; + mpz_init_set_ui (bb, b); + mpz_add (r, a, bb); + mpz_clear (bb); +} + +void +mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b) +{ + mpz_ui_sub (r, b, a); + mpz_neg (r, r); +} + +void +mpz_ui_sub (mpz_t r, unsigned long a, const mpz_t b) +{ + mpz_neg (r, b); + mpz_add_ui (r, r, a); +} + +static mp_size_t +mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t an = GMP_ABS (a->_mp_size); + mp_size_t bn = GMP_ABS (b->_mp_size); + mp_ptr rp; + mp_limb_t cy; + + if (an < bn) + { + MPZ_SRCPTR_SWAP (a, b); + MP_SIZE_T_SWAP (an, bn); + } + + rp = MPZ_REALLOC (r, an + 1); + cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn); + + rp[an] = cy; + + return an + cy; +} + +static mp_size_t +mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t an = GMP_ABS (a->_mp_size); + mp_size_t bn = GMP_ABS (b->_mp_size); + int cmp; + mp_ptr rp; + + cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn); + if (cmp > 0) + { + rp = MPZ_REALLOC (r, an); + gmp_assert_nocarry (mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn)); + return mpn_normalized_size (rp, an); + } + else if (cmp < 0) + { + rp = MPZ_REALLOC (r, bn); + gmp_assert_nocarry (mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an)); + return -mpn_normalized_size (rp, bn); + } + else + return 0; +} + +void +mpz_add (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t rn; + + if ( (a->_mp_size ^ b->_mp_size) >= 0) + rn = mpz_abs_add (r, a, b); + else + rn = mpz_abs_sub (r, a, b); + + r->_mp_size = a->_mp_size >= 0 ? rn : - rn; +} + +void +mpz_sub (mpz_t r, const mpz_t a, const mpz_t b) +{ + mp_size_t rn; + + if ( (a->_mp_size ^ b->_mp_size) >= 0) + rn = mpz_abs_sub (r, a, b); + else + rn = mpz_abs_add (r, a, b); + + r->_mp_size = a->_mp_size >= 0 ? rn : - rn; +} + + +/* MPZ multiplication */ +void +mpz_mul_si (mpz_t r, const mpz_t u, long int v) +{ + if (v < 0) + { + mpz_mul_ui (r, u, GMP_NEG_CAST (unsigned long int, v)); + mpz_neg (r, r); + } + else + mpz_mul_ui (r, u, v); +} + +void +mpz_mul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mpz_t vv; + mpz_init_set_ui (vv, v); + mpz_mul (r, u, vv); + mpz_clear (vv); + return; +} + +void +mpz_mul (mpz_t r, const mpz_t u, const mpz_t v) +{ + int sign; + mp_size_t un, vn, rn; + mpz_t t; + mp_ptr tp; + + un = u->_mp_size; + vn = v->_mp_size; + + if (un == 0 || vn == 0) + { + r->_mp_size = 0; + return; + } + + sign = (un ^ vn) < 0; + + un = GMP_ABS (un); + vn = GMP_ABS (vn); + + mpz_init2 (t, (un + vn) * GMP_LIMB_BITS); + + tp = t->_mp_d; + if (un >= vn) + mpn_mul (tp, u->_mp_d, un, v->_mp_d, vn); + else + mpn_mul (tp, v->_mp_d, vn, u->_mp_d, un); + + rn = un + vn; + rn -= tp[rn-1] == 0; + + t->_mp_size = sign ? - rn : rn; + mpz_swap (r, t); + mpz_clear (t); +} + +void +mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits) +{ + mp_size_t un, rn; + mp_size_t limbs; + unsigned shift; + mp_ptr rp; + + un = GMP_ABS (u->_mp_size); + if (un == 0) + { + r->_mp_size = 0; + return; + } + + limbs = bits / GMP_LIMB_BITS; + shift = bits % GMP_LIMB_BITS; + + rn = un + limbs + (shift > 0); + rp = MPZ_REALLOC (r, rn); + if (shift > 0) + { + mp_limb_t cy = mpn_lshift (rp + limbs, u->_mp_d, un, shift); + rp[rn-1] = cy; + rn -= (cy == 0); + } + else + mpn_copyd (rp + limbs, u->_mp_d, un); + + mpn_zero (rp, limbs); + + r->_mp_size = (u->_mp_size < 0) ? - rn : rn; +} + +void +mpz_addmul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mpz_t t; + mpz_init_set_ui (t, v); + mpz_mul (t, u, t); + mpz_add (r, r, t); + mpz_clear (t); +} + +void +mpz_submul_ui (mpz_t r, const mpz_t u, unsigned long int v) +{ + mpz_t t; + mpz_init_set_ui (t, v); + mpz_mul (t, u, t); + mpz_sub (r, r, t); + mpz_clear (t); +} + +void +mpz_addmul (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t t; + mpz_init (t); + mpz_mul (t, u, v); + mpz_add (r, r, t); + mpz_clear (t); +} + +void +mpz_submul (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t t; + mpz_init (t); + mpz_mul (t, u, v); + mpz_sub (r, r, t); + mpz_clear (t); +} + + +/* MPZ division */ +enum mpz_div_round_mode { GMP_DIV_FLOOR, GMP_DIV_CEIL, GMP_DIV_TRUNC }; + +/* Allows q or r to be zero. Returns 1 iff remainder is non-zero. */ +static int +mpz_div_qr (mpz_t q, mpz_t r, + const mpz_t n, const mpz_t d, enum mpz_div_round_mode mode) +{ + mp_size_t ns, ds, nn, dn, qs; + ns = n->_mp_size; + ds = d->_mp_size; + + if (ds == 0) + gmp_die("mpz_div_qr: Divide by zero."); + + if (ns == 0) + { + if (q) + q->_mp_size = 0; + if (r) + r->_mp_size = 0; + return 0; + } + + nn = GMP_ABS (ns); + dn = GMP_ABS (ds); + + qs = ds ^ ns; + + if (nn < dn) + { + if (mode == GMP_DIV_CEIL && qs >= 0) + { + /* q = 1, r = n - d */ + if (r) + mpz_sub (r, n, d); + if (q) + mpz_set_ui (q, 1); + } + else if (mode == GMP_DIV_FLOOR && qs < 0) + { + /* q = -1, r = n + d */ + if (r) + mpz_add (r, n, d); + if (q) + mpz_set_si (q, -1); + } + else + { + /* q = 0, r = d */ + if (r) + mpz_set (r, n); + if (q) + q->_mp_size = 0; + } + return 1; + } + else + { + mp_ptr np, qp; + mp_size_t qn, rn; + mpz_t tq, tr; + + mpz_init_set (tr, n); + np = tr->_mp_d; + + qn = nn - dn + 1; + + if (q) + { + mpz_init2 (tq, qn * GMP_LIMB_BITS); + qp = tq->_mp_d; + } + else + qp = NULL; + + mpn_div_qr (qp, np, nn, d->_mp_d, dn); + + if (qp) + { + qn -= (qp[qn-1] == 0); + + tq->_mp_size = qs < 0 ? -qn : qn; + } + rn = mpn_normalized_size (np, dn); + tr->_mp_size = ns < 0 ? - rn : rn; + + if (mode == GMP_DIV_FLOOR && qs < 0 && rn != 0) + { + if (q) + mpz_sub_ui (tq, tq, 1); + if (r) + mpz_add (tr, tr, d); + } + else if (mode == GMP_DIV_CEIL && qs >= 0 && rn != 0) + { + if (q) + mpz_add_ui (tq, tq, 1); + if (r) + mpz_sub (tr, tr, d); + } + + if (q) + { + mpz_swap (tq, q); + mpz_clear (tq); + } + if (r) + mpz_swap (tr, r); + + mpz_clear (tr); + + return rn != 0; + } +} + +void +mpz_cdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, r, n, d, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_CEIL); +} + +void +mpz_fdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_r (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, GMP_DIV_TRUNC); +} + +void +mpz_mod (mpz_t r, const mpz_t n, const mpz_t d) +{ + mpz_div_qr (NULL, r, n, d, d->_mp_size >= 0 ? GMP_DIV_FLOOR : GMP_DIV_CEIL); +} + +static void +mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index, + enum mpz_div_round_mode mode) +{ + mp_size_t un, qn; + mp_size_t limb_cnt; + mp_ptr qp; + int adjust; + + un = u->_mp_size; + if (un == 0) + { + q->_mp_size = 0; + return; + } + limb_cnt = bit_index / GMP_LIMB_BITS; + qn = GMP_ABS (un) - limb_cnt; + bit_index %= GMP_LIMB_BITS; + + if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */ + /* Note: Below, the final indexing at limb_cnt is valid because at + that point we have qn > 0. */ + adjust = (qn <= 0 + || !mpn_zero_p (u->_mp_d, limb_cnt) + || (u->_mp_d[limb_cnt] + & (((mp_limb_t) 1 << bit_index) - 1))); + else + adjust = 0; + + if (qn <= 0) + qn = 0; + else + { + qp = MPZ_REALLOC (q, qn); + + if (bit_index != 0) + { + mpn_rshift (qp, u->_mp_d + limb_cnt, qn, bit_index); + qn -= qp[qn - 1] == 0; + } + else + { + mpn_copyi (qp, u->_mp_d + limb_cnt, qn); + } + } + + q->_mp_size = qn; + + if (adjust) + mpz_add_ui (q, q, 1); + if (un < 0) + mpz_neg (q, q); +} + +static void +mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index, + enum mpz_div_round_mode mode) +{ + mp_size_t us, un, rn; + mp_ptr rp; + mp_limb_t mask; + + us = u->_mp_size; + if (us == 0 || bit_index == 0) + { + r->_mp_size = 0; + return; + } + rn = (bit_index + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + assert (rn > 0); + + rp = MPZ_REALLOC (r, rn); + un = GMP_ABS (us); + + mask = GMP_LIMB_MAX >> (rn * GMP_LIMB_BITS - bit_index); + + if (rn > un) + { + /* Quotient (with truncation) is zero, and remainder is + non-zero */ + if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ + { + /* Have to negate and sign extend. */ + mp_size_t i; + + gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un)); + for (i = un; i < rn - 1; i++) + rp[i] = GMP_LIMB_MAX; + + rp[rn-1] = mask; + us = -us; + } + else + { + /* Just copy */ + if (r != u) + mpn_copyi (rp, u->_mp_d, un); + + rn = un; + } + } + else + { + if (r != u) + mpn_copyi (rp, u->_mp_d, rn - 1); + + rp[rn-1] = u->_mp_d[rn-1] & mask; + + if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ + { + /* If r != 0, compute 2^{bit_count} - r. */ + mpn_neg (rp, rp, rn); + + rp[rn-1] &= mask; + + /* us is not used for anything else, so we can modify it + here to indicate flipped sign. */ + us = -us; + } + } + rn = mpn_normalized_size (rp, rn); + r->_mp_size = us < 0 ? -rn : rn; +} + +void +mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL); +} + +void +mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC); +} + +void +mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL); +} + +void +mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR); +} + +void +mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) +{ + mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC); +} + +void +mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) +{ + gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC)); +} + +int +mpz_divisible_p (const mpz_t n, const mpz_t d) +{ + return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; +} + +int +mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m) +{ + mpz_t t; + int res; + + /* a == b (mod 0) iff a == b */ + if (mpz_sgn (m) == 0) + return (mpz_cmp (a, b) == 0); + + mpz_init (t); + mpz_sub (t, a, b); + res = mpz_divisible_p (t, m); + mpz_clear (t); + + return res; +} + +static unsigned long +mpz_div_qr_ui (mpz_t q, mpz_t r, + const mpz_t n, unsigned long d, enum mpz_div_round_mode mode) +{ + unsigned long ret; + mpz_t rr, dd; + + mpz_init (rr); + mpz_init_set_ui (dd, d); + mpz_div_qr (q, rr, n, dd, mode); + mpz_clear (dd); + ret = mpz_get_ui (rr); + + if (r) + mpz_swap (r, rr); + mpz_clear (rr); + + return ret; +} + +unsigned long +mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL); +} +unsigned long +mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); +} +unsigned long +mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_cdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL); +} + +unsigned long +mpz_fdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR); +} + +unsigned long +mpz_tdiv_ui (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC); +} + +unsigned long +mpz_mod_ui (mpz_t r, const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); +} + +void +mpz_divexact_ui (mpz_t q, const mpz_t n, unsigned long d) +{ + gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC)); +} + +int +mpz_divisible_ui_p (const mpz_t n, unsigned long d) +{ + return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; +} + + +/* GCD */ +static mp_limb_t +mpn_gcd_11 (mp_limb_t u, mp_limb_t v) +{ + unsigned shift; + + assert ( (u | v) > 0); + + if (u == 0) + return v; + else if (v == 0) + return u; + + gmp_ctz (shift, u | v); + + u >>= shift; + v >>= shift; + + if ( (u & 1) == 0) + MP_LIMB_T_SWAP (u, v); + + while ( (v & 1) == 0) + v >>= 1; + + while (u != v) + { + if (u > v) + { + u -= v; + do + u >>= 1; + while ( (u & 1) == 0); + } + else + { + v -= u; + do + v >>= 1; + while ( (v & 1) == 0); + } + } + return u << shift; +} + +unsigned long +mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v) +{ + mpz_t t; + mpz_init_set_ui(t, v); + mpz_gcd (t, u, t); + if (v > 0) + v = mpz_get_ui (t); + + if (g) + mpz_swap (t, g); + + mpz_clear (t); + + return v; +} + +static mp_bitcnt_t +mpz_make_odd (mpz_t r) +{ + mp_bitcnt_t shift; + + assert (r->_mp_size > 0); + /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */ + shift = mpn_scan1 (r->_mp_d, 0); + mpz_tdiv_q_2exp (r, r, shift); + + return shift; +} + +void +mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v) +{ + mpz_t tu, tv; + mp_bitcnt_t uz, vz, gz; + + if (u->_mp_size == 0) + { + mpz_abs (g, v); + return; + } + if (v->_mp_size == 0) + { + mpz_abs (g, u); + return; + } + + mpz_init (tu); + mpz_init (tv); + + mpz_abs (tu, u); + uz = mpz_make_odd (tu); + mpz_abs (tv, v); + vz = mpz_make_odd (tv); + gz = GMP_MIN (uz, vz); + + if (tu->_mp_size < tv->_mp_size) + mpz_swap (tu, tv); + + mpz_tdiv_r (tu, tu, tv); + if (tu->_mp_size == 0) + { + mpz_swap (g, tv); + } + else + for (;;) + { + int c; + + mpz_make_odd (tu); + c = mpz_cmp (tu, tv); + if (c == 0) + { + mpz_swap (g, tu); + break; + } + if (c < 0) + mpz_swap (tu, tv); + + if (tv->_mp_size == 1) + { + mp_limb_t *gp; + + mpz_tdiv_r (tu, tu, tv); + gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */ + *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]); + + g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */ + break; + } + mpz_sub (tu, tu, tv); + } + mpz_clear (tu); + mpz_clear (tv); + mpz_mul_2exp (g, g, gz); +} + +void +mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v) +{ + mpz_t tu, tv, s0, s1, t0, t1; + mp_bitcnt_t uz, vz, gz; + mp_bitcnt_t power; + + if (u->_mp_size == 0) + { + /* g = 0 u + sgn(v) v */ + signed long sign = mpz_sgn (v); + mpz_abs (g, v); + if (s) + s->_mp_size = 0; + if (t) + mpz_set_si (t, sign); + return; + } + + if (v->_mp_size == 0) + { + /* g = sgn(u) u + 0 v */ + signed long sign = mpz_sgn (u); + mpz_abs (g, u); + if (s) + mpz_set_si (s, sign); + if (t) + t->_mp_size = 0; + return; + } + + mpz_init (tu); + mpz_init (tv); + mpz_init (s0); + mpz_init (s1); + mpz_init (t0); + mpz_init (t1); + + mpz_abs (tu, u); + uz = mpz_make_odd (tu); + mpz_abs (tv, v); + vz = mpz_make_odd (tv); + gz = GMP_MIN (uz, vz); + + uz -= gz; + vz -= gz; + + /* Cofactors corresponding to odd gcd. gz handled later. */ + if (tu->_mp_size < tv->_mp_size) + { + mpz_swap (tu, tv); + MPZ_SRCPTR_SWAP (u, v); + MPZ_PTR_SWAP (s, t); + MP_BITCNT_T_SWAP (uz, vz); + } + + /* Maintain + * + * u = t0 tu + t1 tv + * v = s0 tu + s1 tv + * + * where u and v denote the inputs with common factors of two + * eliminated, and det (s0, t0; s1, t1) = 2^p. Then + * + * 2^p tu = s1 u - t1 v + * 2^p tv = -s0 u + t0 v + */ + + /* After initial division, tu = q tv + tu', we have + * + * u = 2^uz (tu' + q tv) + * v = 2^vz tv + * + * or + * + * t0 = 2^uz, t1 = 2^uz q + * s0 = 0, s1 = 2^vz + */ + + mpz_tdiv_qr (t1, tu, tu, tv); + mpz_mul_2exp (t1, t1, uz); + + mpz_setbit (s1, vz); + power = uz + vz; + + if (tu->_mp_size > 0) + { + mp_bitcnt_t shift; + shift = mpz_make_odd (tu); + mpz_setbit (t0, uz + shift); + power += shift; + + for (;;) + { + int c; + c = mpz_cmp (tu, tv); + if (c == 0) + break; + + if (c < 0) + { + /* tv = tv' + tu + * + * u = t0 tu + t1 (tv' + tu) = (t0 + t1) tu + t1 tv' + * v = s0 tu + s1 (tv' + tu) = (s0 + s1) tu + s1 tv' */ + + mpz_sub (tv, tv, tu); + mpz_add (t0, t0, t1); + mpz_add (s0, s0, s1); + + shift = mpz_make_odd (tv); + mpz_mul_2exp (t1, t1, shift); + mpz_mul_2exp (s1, s1, shift); + } + else + { + mpz_sub (tu, tu, tv); + mpz_add (t1, t0, t1); + mpz_add (s1, s0, s1); + + shift = mpz_make_odd (tu); + mpz_mul_2exp (t0, t0, shift); + mpz_mul_2exp (s0, s0, shift); + } + power += shift; + } + } + else + mpz_setbit (t0, uz); + + /* Now tv = odd part of gcd, and -s0 and t0 are corresponding + cofactors. */ + + mpz_mul_2exp (tv, tv, gz); + mpz_neg (s0, s0); + + /* 2^p g = s0 u + t0 v. Eliminate one factor of two at a time. To + adjust cofactors, we need u / g and v / g */ + + mpz_divexact (s1, v, tv); + mpz_abs (s1, s1); + mpz_divexact (t1, u, tv); + mpz_abs (t1, t1); + + while (power-- > 0) + { + /* s0 u + t0 v = (s0 - v/g) u - (t0 + u/g) v */ + if (mpz_odd_p (s0) || mpz_odd_p (t0)) + { + mpz_sub (s0, s0, s1); + mpz_add (t0, t0, t1); + } + assert (mpz_even_p (t0) && mpz_even_p (s0)); + mpz_tdiv_q_2exp (s0, s0, 1); + mpz_tdiv_q_2exp (t0, t0, 1); + } + + /* Arrange so that |s| < |u| / 2g */ + mpz_add (s1, s0, s1); + if (mpz_cmpabs (s0, s1) > 0) + { + mpz_swap (s0, s1); + mpz_sub (t0, t0, t1); + } + if (u->_mp_size < 0) + mpz_neg (s0, s0); + if (v->_mp_size < 0) + mpz_neg (t0, t0); + + mpz_swap (g, tv); + if (s) + mpz_swap (s, s0); + if (t) + mpz_swap (t, t0); + + mpz_clear (tu); + mpz_clear (tv); + mpz_clear (s0); + mpz_clear (s1); + mpz_clear (t0); + mpz_clear (t1); +} + +void +mpz_lcm (mpz_t r, const mpz_t u, const mpz_t v) +{ + mpz_t g; + + if (u->_mp_size == 0 || v->_mp_size == 0) + { + r->_mp_size = 0; + return; + } + + mpz_init (g); + + mpz_gcd (g, u, v); + mpz_divexact (g, u, g); + mpz_mul (r, g, v); + + mpz_clear (g); + mpz_abs (r, r); +} + +void +mpz_lcm_ui (mpz_t r, const mpz_t u, unsigned long v) +{ + if (v == 0 || u->_mp_size == 0) + { + r->_mp_size = 0; + return; + } + + v /= mpz_gcd_ui (NULL, u, v); + mpz_mul_ui (r, u, v); + + mpz_abs (r, r); +} + +int +mpz_invert (mpz_t r, const mpz_t u, const mpz_t m) +{ + mpz_t g, tr; + int invertible; + + if (u->_mp_size == 0 || mpz_cmpabs_ui (m, 1) <= 0) + return 0; + + mpz_init (g); + mpz_init (tr); + + mpz_gcdext (g, tr, NULL, u, m); + invertible = (mpz_cmp_ui (g, 1) == 0); + + if (invertible) + { + if (tr->_mp_size < 0) + { + if (m->_mp_size >= 0) + mpz_add (tr, tr, m); + else + mpz_sub (tr, tr, m); + } + mpz_swap (r, tr); + } + + mpz_clear (g); + mpz_clear (tr); + return invertible; +} + + +/* Higher level operations (sqrt, pow and root) */ + +void +mpz_pow_ui (mpz_t r, const mpz_t b, unsigned long e) +{ + unsigned long bit; + mpz_t tr; + mpz_init_set_ui (tr, 1); + + bit = GMP_ULONG_HIGHBIT; + do + { + mpz_mul (tr, tr, tr); + if (e & bit) + mpz_mul (tr, tr, b); + bit >>= 1; + } + while (bit > 0); + + mpz_swap (r, tr); + mpz_clear (tr); +} + +void +mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e) +{ + mpz_t b; + + mpz_init_set_ui (b, blimb); + mpz_pow_ui (r, b, e); + mpz_clear (b); +} + +void +mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m) +{ + mpz_t tr; + mpz_t base; + mp_size_t en, mn; + mp_srcptr mp; + struct gmp_div_inverse minv; + unsigned shift; + mp_ptr tp = NULL; + + en = GMP_ABS (e->_mp_size); + mn = GMP_ABS (m->_mp_size); + if (mn == 0) + gmp_die ("mpz_powm: Zero modulo."); + + if (en == 0) + { + mpz_set_ui (r, mpz_cmpabs_ui (m, 1)); + return; + } + + mp = m->_mp_d; + mpn_div_qr_invert (&minv, mp, mn); + shift = minv.shift; + + if (shift > 0) + { + /* To avoid shifts, we do all our reductions, except the final + one, using a *normalized* m. */ + minv.shift = 0; + + tp = gmp_alloc_limbs (mn); + gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift)); + mp = tp; + } + + mpz_init (base); + + if (e->_mp_size < 0) + { + if (!mpz_invert (base, b, m)) + gmp_die ("mpz_powm: Negative exponent and non-invertible base."); + } + else + { + mp_size_t bn; + mpz_abs (base, b); + + bn = base->_mp_size; + if (bn >= mn) + { + mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv); + bn = mn; + } + + /* We have reduced the absolute value. Now take care of the + sign. Note that we get zero represented non-canonically as + m. */ + if (b->_mp_size < 0) + { + mp_ptr bp = MPZ_REALLOC (base, mn); + gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn)); + bn = mn; + } + base->_mp_size = mpn_normalized_size (base->_mp_d, bn); + } + mpz_init_set_ui (tr, 1); + + while (--en >= 0) + { + mp_limb_t w = e->_mp_d[en]; + mp_limb_t bit; + + bit = GMP_LIMB_HIGHBIT; + do + { + mpz_mul (tr, tr, tr); + if (w & bit) + mpz_mul (tr, tr, base); + if (tr->_mp_size > mn) + { + mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); + tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); + } + bit >>= 1; + } + while (bit > 0); + } + + /* Final reduction */ + if (tr->_mp_size >= mn) + { + minv.shift = shift; + mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); + tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); + } + if (tp) + gmp_free_limbs (tp, mn); + + mpz_swap (r, tr); + mpz_clear (tr); + mpz_clear (base); +} + +void +mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m) +{ + mpz_t e; + + mpz_init_set_ui (e, elimb); + mpz_powm (r, b, e, m); + mpz_clear (e); +} + +/* x=trunc(y^(1/z)), r=y-x^z */ +void +mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z) +{ + int sgn; + mp_bitcnt_t bc; + mpz_t t, u; + + sgn = y->_mp_size < 0; + if ((~z & sgn) != 0) + gmp_die ("mpz_rootrem: Negative argument, with even root."); + if (z == 0) + gmp_die ("mpz_rootrem: Zeroth root."); + + if (mpz_cmpabs_ui (y, 1) <= 0) { + if (x) + mpz_set (x, y); + if (r) + r->_mp_size = 0; + return; + } + + mpz_init (u); + mpz_init (t); + bc = (mpz_sizeinbase (y, 2) - 1) / z + 1; + mpz_setbit (t, bc); + + if (z == 2) /* simplify sqrt loop: z-1 == 1 */ + do { + mpz_swap (u, t); /* u = x */ + mpz_tdiv_q (t, y, u); /* t = y/x */ + mpz_add (t, t, u); /* t = y/x + x */ + mpz_tdiv_q_2exp (t, t, 1); /* x'= (y/x + x)/2 */ + } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ + else /* z != 2 */ { + mpz_t v; + + mpz_init (v); + if (sgn) + mpz_neg (t, t); + + do { + mpz_swap (u, t); /* u = x */ + mpz_pow_ui (t, u, z - 1); /* t = x^(z-1) */ + mpz_tdiv_q (t, y, t); /* t = y/x^(z-1) */ + mpz_mul_ui (v, u, z - 1); /* v = x*(z-1) */ + mpz_add (t, t, v); /* t = y/x^(z-1) + x*(z-1) */ + mpz_tdiv_q_ui (t, t, z); /* x'=(y/x^(z-1) + x*(z-1))/z */ + } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ + + mpz_clear (v); + } + + if (r) { + mpz_pow_ui (t, u, z); + mpz_sub (r, y, t); + } + if (x) + mpz_swap (x, u); + mpz_clear (u); + mpz_clear (t); +} + +int +mpz_root (mpz_t x, const mpz_t y, unsigned long z) +{ + int res; + mpz_t r; + + mpz_init (r); + mpz_rootrem (x, r, y, z); + res = r->_mp_size == 0; + mpz_clear (r); + + return res; +} + +/* Compute s = floor(sqrt(u)) and r = u - s^2. Allows r == NULL */ +void +mpz_sqrtrem (mpz_t s, mpz_t r, const mpz_t u) +{ + mpz_rootrem (s, r, u, 2); +} + +void +mpz_sqrt (mpz_t s, const mpz_t u) +{ + mpz_rootrem (s, NULL, u, 2); +} + +int +mpz_perfect_square_p (const mpz_t u) +{ + if (u->_mp_size <= 0) + return (u->_mp_size == 0); + else + return mpz_root (NULL, u, 2); +} + +int +mpn_perfect_square_p (mp_srcptr p, mp_size_t n) +{ + mpz_t t; + + assert (n > 0); + assert (p [n-1] != 0); + return mpz_root (NULL, mpz_roinit_normal_n (t, p, n), 2); +} + +mp_size_t +mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n) +{ + mpz_t s, r, u; + mp_size_t res; + + assert (n > 0); + assert (p [n-1] != 0); + + mpz_init (r); + mpz_init (s); + mpz_rootrem (s, r, mpz_roinit_normal_n (u, p, n), 2); + + assert (s->_mp_size == (n+1)/2); + mpn_copyd (sp, s->_mp_d, s->_mp_size); + mpz_clear (s); + res = r->_mp_size; + if (rp) + mpn_copyd (rp, r->_mp_d, res); + mpz_clear (r); + return res; +} + +/* Combinatorics */ + +void +mpz_mfac_uiui (mpz_t x, unsigned long n, unsigned long m) +{ + mpz_set_ui (x, n + (n == 0)); + if (m + 1 < 2) return; + while (n > m + 1) + mpz_mul_ui (x, x, n -= m); +} + +void +mpz_2fac_ui (mpz_t x, unsigned long n) +{ + mpz_mfac_uiui (x, n, 2); +} + +void +mpz_fac_ui (mpz_t x, unsigned long n) +{ + mpz_mfac_uiui (x, n, 1); +} + +void +mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k) +{ + mpz_t t; + + mpz_set_ui (r, k <= n); + + if (k > (n >> 1)) + k = (k <= n) ? n - k : 0; + + mpz_init (t); + mpz_fac_ui (t, k); + + for (; k > 0; --k) + mpz_mul_ui (r, r, n--); + + mpz_divexact (r, r, t); + mpz_clear (t); +} + + +/* Primality testing */ + +/* Computes Kronecker (a/b) with odd b, a!=0 and GCD(a,b) = 1 */ +/* Adapted from JACOBI_BASE_METHOD==4 in mpn/generic/jacbase.c */ +static int +gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b) +{ + int c, bit = 0; + + assert (b & 1); + assert (a != 0); + /* assert (mpn_gcd_11 (a, b) == 1); */ + + /* Below, we represent a and b shifted right so that the least + significant one bit is implicit. */ + b >>= 1; + + gmp_ctz(c, a); + a >>= 1; + + for (;;) + { + a >>= c; + /* (2/b) = -1 if b = 3 or 5 mod 8 */ + bit ^= c & (b ^ (b >> 1)); + if (a < b) + { + if (a == 0) + return bit & 1 ? -1 : 1; + bit ^= a & b; + a = b - a; + b -= a; + } + else + { + a -= b; + assert (a != 0); + } + + gmp_ctz(c, a); + ++c; + } +} + +static void +gmp_lucas_step_k_2k (mpz_t V, mpz_t Qk, const mpz_t n) +{ + mpz_mod (Qk, Qk, n); + /* V_{2k} <- V_k ^ 2 - 2Q^k */ + mpz_mul (V, V, V); + mpz_submul_ui (V, Qk, 2); + mpz_tdiv_r (V, V, n); + /* Q^{2k} = (Q^k)^2 */ + mpz_mul (Qk, Qk, Qk); +} + +/* Computes V_k, Q^k (mod n) for the Lucas' sequence */ +/* with P=1, Q=Q; k = (n>>b0)|1. */ +/* Requires an odd n > 4; b0 > 0; -2*Q must not overflow a long */ +/* Returns (U_k == 0) and sets V=V_k and Qk=Q^k. */ +static int +gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q, + mp_bitcnt_t b0, const mpz_t n) +{ + mp_bitcnt_t bs; + mpz_t U; + int res; + + assert (b0 > 0); + assert (Q <= - (LONG_MIN / 2)); + assert (Q >= - (LONG_MAX / 2)); + assert (mpz_cmp_ui (n, 4) > 0); + assert (mpz_odd_p (n)); + + mpz_init_set_ui (U, 1); /* U1 = 1 */ + mpz_set_ui (V, 1); /* V1 = 1 */ + mpz_set_si (Qk, Q); + + for (bs = mpz_sizeinbase (n, 2) - 1; --bs >= b0;) + { + /* U_{2k} <- U_k * V_k */ + mpz_mul (U, U, V); + /* V_{2k} <- V_k ^ 2 - 2Q^k */ + /* Q^{2k} = (Q^k)^2 */ + gmp_lucas_step_k_2k (V, Qk, n); + + /* A step k->k+1 is performed if the bit in $n$ is 1 */ + /* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */ + /* should be 1 in $n+1$ (bs == b0) */ + if (b0 == bs || mpz_tstbit (n, bs)) + { + /* Q^{k+1} <- Q^k * Q */ + mpz_mul_si (Qk, Qk, Q); + /* U_{k+1} <- (U_k + V_k) / 2 */ + mpz_swap (U, V); /* Keep in V the old value of U_k */ + mpz_add (U, U, V); + /* We have to compute U/2, so we need an even value, */ + /* equivalent (mod n) */ + if (mpz_odd_p (U)) + mpz_add (U, U, n); + mpz_tdiv_q_2exp (U, U, 1); + /* V_{k+1} <-(D*U_k + V_k) / 2 = + U_{k+1} + (D-1)/2*U_k = U_{k+1} - 2Q*U_k */ + mpz_mul_si (V, V, -2*Q); + mpz_add (V, U, V); + mpz_tdiv_r (V, V, n); + } + mpz_tdiv_r (U, U, n); + } + + res = U->_mp_size == 0; + mpz_clear (U); + return res; +} + +/* Performs strong Lucas' test on x, with parameters suggested */ +/* for the BPSW test. Qk is only passed to recycle a variable. */ +/* Requires GCD (x,6) = 1.*/ +static int +gmp_stronglucas (const mpz_t x, mpz_t Qk) +{ + mp_bitcnt_t b0; + mpz_t V, n; + mp_limb_t maxD, D; /* The absolute value is stored. */ + long Q; + mp_limb_t tl; + + /* Test on the absolute value. */ + mpz_roinit_normal_n (n, x->_mp_d, GMP_ABS (x->_mp_size)); + + assert (mpz_odd_p (n)); + /* assert (mpz_gcd_ui (NULL, n, 6) == 1); */ + if (mpz_root (Qk, n, 2)) + return 0; /* A square is composite. */ + + /* Check Ds up to square root (in case, n is prime) + or avoid overflows */ + maxD = (Qk->_mp_size == 1) ? Qk->_mp_d [0] - 1 : GMP_LIMB_MAX; + + D = 3; + /* Search a D such that (D/n) = -1 in the sequence 5,-7,9,-11,.. */ + /* For those Ds we have (D/n) = (n/|D|) */ + do + { + if (D >= maxD) + return 1 + (D != GMP_LIMB_MAX); /* (1 + ! ~ D) */ + D += 2; + tl = mpz_tdiv_ui (n, D); + if (tl == 0) + return 0; + } + while (gmp_jacobi_coprime (tl, D) == 1); + + mpz_init (V); + + /* n-(D/n) = n+1 = d*2^{b0}, with d = (n>>b0) | 1 */ + b0 = mpn_common_scan (~ n->_mp_d[0], 0, n->_mp_d, n->_mp_size, GMP_LIMB_MAX); + /* b0 = mpz_scan0 (n, 0); */ + + /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */ + Q = (D & 2) ? (long) (D >> 2) + 1 : -(long) (D >> 2); + + if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */ + while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */ + /* V <- V ^ 2 - 2Q^k */ + /* Q^{2k} = (Q^k)^2 */ + gmp_lucas_step_k_2k (V, Qk, n); + + mpz_clear (V); + return (b0 != 0); +} + +static int +gmp_millerrabin (const mpz_t n, const mpz_t nm1, mpz_t y, + const mpz_t q, mp_bitcnt_t k) +{ + assert (k > 0); + + /* Caller must initialize y to the base. */ + mpz_powm (y, y, q, n); + + if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0) + return 1; + + while (--k > 0) + { + mpz_powm_ui (y, y, 2, n); + if (mpz_cmp (y, nm1) == 0) + return 1; + } + return 0; +} + +/* This product is 0xc0cfd797, and fits in 32 bits. */ +#define GMP_PRIME_PRODUCT \ + (3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL) + +/* Bit (p+1)/2 is set, for each odd prime <= 61 */ +#define GMP_PRIME_MASK 0xc96996dcUL + +int +mpz_probab_prime_p (const mpz_t n, int reps) +{ + mpz_t nm1; + mpz_t q; + mpz_t y; + mp_bitcnt_t k; + int is_prime; + int j; + + /* Note that we use the absolute value of n only, for compatibility + with the real GMP. */ + if (mpz_even_p (n)) + return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0; + + /* Above test excludes n == 0 */ + assert (n->_mp_size != 0); + + if (mpz_cmpabs_ui (n, 64) < 0) + return (GMP_PRIME_MASK >> (n->_mp_d[0] >> 1)) & 2; + + if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1) + return 0; + + /* All prime factors are >= 31. */ + if (mpz_cmpabs_ui (n, 31*31) < 0) + return 2; + + mpz_init (nm1); + mpz_init (q); + + /* Find q and k, where q is odd and n = 1 + 2**k * q. */ + mpz_abs (nm1, n); + nm1->_mp_d[0] -= 1; + /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */ + k = mpn_scan1 (nm1->_mp_d, 0); + mpz_tdiv_q_2exp (q, nm1, k); + + /* BPSW test */ + mpz_init_set_ui (y, 2); + is_prime = gmp_millerrabin (n, nm1, y, q, k) && gmp_stronglucas (n, y); + reps -= 24; /* skip the first 24 repetitions */ + + /* Use Miller-Rabin, with a deterministic sequence of bases, a[j] = + j^2 + j + 41 using Euler's polynomial. We potentially stop early, + if a[j] >= n - 1. Since n >= 31*31, this can happen only if reps > + 30 (a[30] == 971 > 31*31 == 961). */ + + for (j = 0; is_prime & (j < reps); j++) + { + mpz_set_ui (y, (unsigned long) j*j+j+41); + if (mpz_cmp (y, nm1) >= 0) + { + /* Don't try any further bases. This "early" break does not affect + the result for any reasonable reps value (<=5000 was tested) */ + assert (j >= 30); + break; + } + is_prime = gmp_millerrabin (n, nm1, y, q, k); + } + mpz_clear (nm1); + mpz_clear (q); + mpz_clear (y); + + return is_prime; +} + + +/* Logical operations and bit manipulation. */ + +/* Numbers are treated as if represented in two's complement (and + infinitely sign extended). For a negative values we get the two's + complement from -x = ~x + 1, where ~ is bitwise complement. + Negation transforms + + xxxx10...0 + + into + + yyyy10...0 + + where yyyy is the bitwise complement of xxxx. So least significant + bits, up to and including the first one bit, are unchanged, and + the more significant bits are all complemented. + + To change a bit from zero to one in a negative number, subtract the + corresponding power of two from the absolute value. This can never + underflow. To change a bit from one to zero, add the corresponding + power of two, and this might overflow. E.g., if x = -001111, the + two's complement is 110001. Clearing the least significant bit, we + get two's complement 110000, and -010000. */ + +int +mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t limb_index; + unsigned shift; + mp_size_t ds; + mp_size_t dn; + mp_limb_t w; + int bit; + + ds = d->_mp_size; + dn = GMP_ABS (ds); + limb_index = bit_index / GMP_LIMB_BITS; + if (limb_index >= dn) + return ds < 0; + + shift = bit_index % GMP_LIMB_BITS; + w = d->_mp_d[limb_index]; + bit = (w >> shift) & 1; + + if (ds < 0) + { + /* d < 0. Check if any of the bits below is set: If so, our bit + must be complemented. */ + if (shift > 0 && (mp_limb_t) (w << (GMP_LIMB_BITS - shift)) > 0) + return bit ^ 1; + while (--limb_index >= 0) + if (d->_mp_d[limb_index] > 0) + return bit ^ 1; + } + return bit; +} + +static void +mpz_abs_add_bit (mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t dn, limb_index; + mp_limb_t bit; + mp_ptr dp; + + dn = GMP_ABS (d->_mp_size); + + limb_index = bit_index / GMP_LIMB_BITS; + bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); + + if (limb_index >= dn) + { + mp_size_t i; + /* The bit should be set outside of the end of the number. + We have to increase the size of the number. */ + dp = MPZ_REALLOC (d, limb_index + 1); + + dp[limb_index] = bit; + for (i = dn; i < limb_index; i++) + dp[i] = 0; + dn = limb_index + 1; + } + else + { + mp_limb_t cy; + + dp = d->_mp_d; + + cy = mpn_add_1 (dp + limb_index, dp + limb_index, dn - limb_index, bit); + if (cy > 0) + { + dp = MPZ_REALLOC (d, dn + 1); + dp[dn++] = cy; + } + } + + d->_mp_size = (d->_mp_size < 0) ? - dn : dn; +} + +static void +mpz_abs_sub_bit (mpz_t d, mp_bitcnt_t bit_index) +{ + mp_size_t dn, limb_index; + mp_ptr dp; + mp_limb_t bit; + + dn = GMP_ABS (d->_mp_size); + dp = d->_mp_d; + + limb_index = bit_index / GMP_LIMB_BITS; + bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); + + assert (limb_index < dn); + + gmp_assert_nocarry (mpn_sub_1 (dp + limb_index, dp + limb_index, + dn - limb_index, bit)); + dn = mpn_normalized_size (dp, dn); + d->_mp_size = (d->_mp_size < 0) ? - dn : dn; +} + +void +mpz_setbit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (!mpz_tstbit (d, bit_index)) + { + if (d->_mp_size >= 0) + mpz_abs_add_bit (d, bit_index); + else + mpz_abs_sub_bit (d, bit_index); + } +} + +void +mpz_clrbit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (mpz_tstbit (d, bit_index)) + { + if (d->_mp_size >= 0) + mpz_abs_sub_bit (d, bit_index); + else + mpz_abs_add_bit (d, bit_index); + } +} + +void +mpz_combit (mpz_t d, mp_bitcnt_t bit_index) +{ + if (mpz_tstbit (d, bit_index) ^ (d->_mp_size < 0)) + mpz_abs_sub_bit (d, bit_index); + else + mpz_abs_add_bit (d, bit_index); +} + +void +mpz_com (mpz_t r, const mpz_t u) +{ + mpz_add_ui (r, u, 1); + mpz_neg (r, r); +} + +void +mpz_and (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, rn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + r->_mp_size = 0; + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc & vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + /* If the smaller input is positive, higher limbs don't matter. */ + rn = vx ? un : vn; + + rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = ( (ul & vl) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < rn; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = ( (ul & vx) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[rn++] = rc; + else + rn = mpn_normalized_size (rp, rn); + + r->_mp_size = rx ? -rn : rn; +} + +void +mpz_ior (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, rn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + mpz_set (r, u); + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc | vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + /* If the smaller input is negative, by sign extension higher limbs + don't matter. */ + rn = vx ? vn : un; + + rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = ( (ul | vl) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < rn; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = ( (ul | vx) ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[rn++] = rc; + else + rn = mpn_normalized_size (rp, rn); + + r->_mp_size = rx ? -rn : rn; +} + +void +mpz_xor (mpz_t r, const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, i; + mp_ptr up, vp, rp; + + mp_limb_t ux, vx, rx; + mp_limb_t uc, vc, rc; + mp_limb_t ul, vl, rl; + + un = GMP_ABS (u->_mp_size); + vn = GMP_ABS (v->_mp_size); + if (un < vn) + { + MPZ_SRCPTR_SWAP (u, v); + MP_SIZE_T_SWAP (un, vn); + } + if (vn == 0) + { + mpz_set (r, u); + return; + } + + uc = u->_mp_size < 0; + vc = v->_mp_size < 0; + rc = uc ^ vc; + + ux = -uc; + vx = -vc; + rx = -rc; + + rp = MPZ_REALLOC (r, un + (mp_size_t) rc); + + up = u->_mp_d; + vp = v->_mp_d; + + i = 0; + do + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + vl = (vp[i] ^ vx) + vc; + vc = vl < vc; + + rl = (ul ^ vl ^ rx) + rc; + rc = rl < rc; + rp[i] = rl; + } + while (++i < vn); + assert (vc == 0); + + for (; i < un; i++) + { + ul = (up[i] ^ ux) + uc; + uc = ul < uc; + + rl = (ul ^ ux) + rc; + rc = rl < rc; + rp[i] = rl; + } + if (rc) + rp[un++] = rc; + else + un = mpn_normalized_size (rp, un); + + r->_mp_size = rx ? -un : un; +} + +static unsigned +gmp_popcount_limb (mp_limb_t x) +{ + unsigned c; + + /* Do 16 bits at a time, to avoid limb-sized constants. */ + int LOCAL_SHIFT_BITS = 16; + for (c = 0; x > 0;) + { + unsigned w = x - ((x >> 1) & 0x5555); + w = ((w >> 2) & 0x3333) + (w & 0x3333); + w = (w >> 4) + w; + w = ((w >> 8) & 0x000f) + (w & 0x000f); + c += w; + if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) + x >>= LOCAL_SHIFT_BITS; + else + x = 0; + } + return c; +} + +mp_bitcnt_t +mpn_popcount (mp_srcptr p, mp_size_t n) +{ + mp_size_t i; + mp_bitcnt_t c; + + for (c = 0, i = 0; i < n; i++) + c += gmp_popcount_limb (p[i]); + + return c; +} + +mp_bitcnt_t +mpz_popcount (const mpz_t u) +{ + mp_size_t un; + + un = u->_mp_size; + + if (un < 0) + return ~(mp_bitcnt_t) 0; + + return mpn_popcount (u->_mp_d, un); +} + +mp_bitcnt_t +mpz_hamdist (const mpz_t u, const mpz_t v) +{ + mp_size_t un, vn, i; + mp_limb_t uc, vc, ul, vl, comp; + mp_srcptr up, vp; + mp_bitcnt_t c; + + un = u->_mp_size; + vn = v->_mp_size; + + if ( (un ^ vn) < 0) + return ~(mp_bitcnt_t) 0; + + comp = - (uc = vc = (un < 0)); + if (uc) + { + assert (vn < 0); + un = -un; + vn = -vn; + } + + up = u->_mp_d; + vp = v->_mp_d; + + if (un < vn) + MPN_SRCPTR_SWAP (up, un, vp, vn); + + for (i = 0, c = 0; i < vn; i++) + { + ul = (up[i] ^ comp) + uc; + uc = ul < uc; + + vl = (vp[i] ^ comp) + vc; + vc = vl < vc; + + c += gmp_popcount_limb (ul ^ vl); + } + assert (vc == 0); + + for (; i < un; i++) + { + ul = (up[i] ^ comp) + uc; + uc = ul < uc; + + c += gmp_popcount_limb (ul ^ comp); + } + + return c; +} + +mp_bitcnt_t +mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit) +{ + mp_ptr up; + mp_size_t us, un, i; + mp_limb_t limb, ux; + + us = u->_mp_size; + un = GMP_ABS (us); + i = starting_bit / GMP_LIMB_BITS; + + /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit + for u<0. Notice this test picks up any u==0 too. */ + if (i >= un) + return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit); + + up = u->_mp_d; + ux = 0; + limb = up[i]; + + if (starting_bit != 0) + { + if (us < 0) + { + ux = mpn_zero_p (up, i); + limb = ~ limb + ux; + ux = - (mp_limb_t) (limb >= ux); + } + + /* Mask to 0 all bits before starting_bit, thus ignoring them. */ + limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS); + } + + return mpn_common_scan (limb, i, up, un, ux); +} + +mp_bitcnt_t +mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit) +{ + mp_ptr up; + mp_size_t us, un, i; + mp_limb_t limb, ux; + + us = u->_mp_size; + ux = - (mp_limb_t) (us >= 0); + un = GMP_ABS (us); + i = starting_bit / GMP_LIMB_BITS; + + /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for + u<0. Notice this test picks up all cases of u==0 too. */ + if (i >= un) + return (ux ? starting_bit : ~(mp_bitcnt_t) 0); + + up = u->_mp_d; + limb = up[i] ^ ux; + + if (ux == 0) + limb -= mpn_zero_p (up, i); /* limb = ~(~limb + zero_p) */ + + /* Mask all bits before starting_bit, thus ignoring them. */ + limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS); + + return mpn_common_scan (limb, i, up, un, ux); +} + + +/* MPZ base conversion. */ + +size_t +mpz_sizeinbase (const mpz_t u, int base) +{ + mp_size_t un, tn; + mp_srcptr up; + mp_ptr tp; + mp_bitcnt_t bits; + struct gmp_div_inverse bi; + size_t ndigits; + + assert (base >= 2); + assert (base <= 62); + + un = GMP_ABS (u->_mp_size); + if (un == 0) + return 1; + + up = u->_mp_d; + + bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]); + switch (base) + { + case 2: + return bits; + case 4: + return (bits + 1) / 2; + case 8: + return (bits + 2) / 3; + case 16: + return (bits + 3) / 4; + case 32: + return (bits + 4) / 5; + /* FIXME: Do something more clever for the common case of base + 10. */ + } + + tp = gmp_alloc_limbs (un); + mpn_copyi (tp, up, un); + mpn_div_qr_1_invert (&bi, base); + + tn = un; + ndigits = 0; + do + { + ndigits++; + mpn_div_qr_1_preinv (tp, tp, tn, &bi); + tn -= (tp[tn-1] == 0); + } + while (tn > 0); + + gmp_free_limbs (tp, un); + return ndigits; +} + +char * +mpz_get_str (char *sp, int base, const mpz_t u) +{ + unsigned bits; + const char *digits; + mp_size_t un; + size_t i, sn, osn; + + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + if (base > 1) + { + if (base <= 36) + digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + else if (base > 62) + return NULL; + } + else if (base >= -1) + base = 10; + else + { + base = -base; + if (base > 36) + return NULL; + } + + sn = 1 + mpz_sizeinbase (u, base); + if (!sp) + { + osn = 1 + sn; + sp = (char *) gmp_alloc (osn); + } + else + osn = 0; + un = GMP_ABS (u->_mp_size); + + if (un == 0) + { + sp[0] = '0'; + sn = 1; + goto ret; + } + + i = 0; + + if (u->_mp_size < 0) + sp[i++] = '-'; + + bits = mpn_base_power_of_two_p (base); + + if (bits) + /* Not modified in this case. */ + sn = i + mpn_get_str_bits ((unsigned char *) sp + i, bits, u->_mp_d, un); + else + { + struct mpn_base_info info; + mp_ptr tp; + + mpn_get_base_info (&info, base); + tp = gmp_alloc_limbs (un); + mpn_copyi (tp, u->_mp_d, un); + + sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un); + gmp_free_limbs (tp, un); + } + + for (; i < sn; i++) + sp[i] = digits[(unsigned char) sp[i]]; + +ret: + sp[sn] = '\0'; + if (osn && osn != sn + 1) + sp = (char*) gmp_realloc (sp, osn, sn + 1); + return sp; +} + +int +mpz_set_str (mpz_t r, const char *sp, int base) +{ + unsigned bits, value_of_a; + mp_size_t rn, alloc; + mp_ptr rp; + size_t dn, sn; + int sign; + unsigned char *dp; + + assert (base == 0 || (base >= 2 && base <= 62)); + + while (isspace( (unsigned char) *sp)) + sp++; + + sign = (*sp == '-'); + sp += sign; + + if (base == 0) + { + if (sp[0] == '0') + { + if (sp[1] == 'x' || sp[1] == 'X') + { + base = 16; + sp += 2; + } + else if (sp[1] == 'b' || sp[1] == 'B') + { + base = 2; + sp += 2; + } + else + base = 8; + } + else + base = 10; + } + + if (!*sp) + { + r->_mp_size = 0; + return -1; + } + sn = strlen(sp); + dp = (unsigned char *) gmp_alloc (sn); + + value_of_a = (base > 36) ? 36 : 10; + for (dn = 0; *sp; sp++) + { + unsigned digit; + + if (isspace ((unsigned char) *sp)) + continue; + else if (*sp >= '0' && *sp <= '9') + digit = *sp - '0'; + else if (*sp >= 'a' && *sp <= 'z') + digit = *sp - 'a' + value_of_a; + else if (*sp >= 'A' && *sp <= 'Z') + digit = *sp - 'A' + 10; + else + digit = base; /* fail */ + + if (digit >= (unsigned) base) + { + gmp_free (dp, sn); + r->_mp_size = 0; + return -1; + } + + dp[dn++] = digit; + } + + if (!dn) + { + gmp_free (dp, sn); + r->_mp_size = 0; + return -1; + } + bits = mpn_base_power_of_two_p (base); + + if (bits > 0) + { + alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + rp = MPZ_REALLOC (r, alloc); + rn = mpn_set_str_bits (rp, dp, dn, bits); + } + else + { + struct mpn_base_info info; + mpn_get_base_info (&info, base); + alloc = (dn + info.exp - 1) / info.exp; + rp = MPZ_REALLOC (r, alloc); + rn = mpn_set_str_other (rp, dp, dn, base, &info); + /* Normalization, needed for all-zero input. */ + assert (rn > 0); + rn -= rp[rn-1] == 0; + } + assert (rn <= alloc); + gmp_free (dp, sn); + + r->_mp_size = sign ? - rn : rn; + + return 0; +} + +int +mpz_init_set_str (mpz_t r, const char *sp, int base) +{ + mpz_init (r); + return mpz_set_str (r, sp, base); +} + +size_t +mpz_out_str (FILE *stream, int base, const mpz_t x) +{ + char *str; + size_t len, n; + + str = mpz_get_str (NULL, base, x); + if (!str) + return 0; + len = strlen (str); + n = fwrite (str, 1, len, stream); + gmp_free (str, len + 1); + return n; +} + + +static int +gmp_detect_endian (void) +{ + static const int i = 2; + const unsigned char *p = (const unsigned char *) &i; + return 1 - *p; +} + +/* Import and export. Does not support nails. */ +void +mpz_import (mpz_t r, size_t count, int order, size_t size, int endian, + size_t nails, const void *src) +{ + const unsigned char *p; + ptrdiff_t word_step; + mp_ptr rp; + mp_size_t rn; + + /* The current (partial) limb. */ + mp_limb_t limb; + /* The number of bytes already copied to this limb (starting from + the low end). */ + size_t bytes; + /* The index where the limb should be stored, when completed. */ + mp_size_t i; + + if (nails != 0) + gmp_die ("mpz_import: Nails not supported."); + + assert (order == 1 || order == -1); + assert (endian >= -1 && endian <= 1); + + if (endian == 0) + endian = gmp_detect_endian (); + + p = (unsigned char *) src; + + word_step = (order != endian) ? 2 * size : 0; + + /* Process bytes from the least significant end, so point p at the + least significant word. */ + if (order == 1) + { + p += size * (count - 1); + word_step = - word_step; + } + + /* And at least significant byte of that word. */ + if (endian == 1) + p += (size - 1); + + rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t); + rp = MPZ_REALLOC (r, rn); + + for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step) + { + size_t j; + for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) + { + limb |= (mp_limb_t) *p << (bytes++ * CHAR_BIT); + if (bytes == sizeof(mp_limb_t)) + { + rp[i++] = limb; + bytes = 0; + limb = 0; + } + } + } + assert (i + (bytes > 0) == rn); + if (limb != 0) + rp[i++] = limb; + else + i = mpn_normalized_size (rp, i); + + r->_mp_size = i; +} + +void * +mpz_export (void *r, size_t *countp, int order, size_t size, int endian, + size_t nails, const mpz_t u) +{ + size_t count; + mp_size_t un; + + if (nails != 0) + gmp_die ("mpz_export: Nails not supported."); + + assert (order == 1 || order == -1); + assert (endian >= -1 && endian <= 1); + assert (size > 0 || u->_mp_size == 0); + + un = u->_mp_size; + count = 0; + if (un != 0) + { + size_t k; + unsigned char *p; + ptrdiff_t word_step; + /* The current (partial) limb. */ + mp_limb_t limb; + /* The number of bytes left to do in this limb. */ + size_t bytes; + /* The index where the limb was read. */ + mp_size_t i; + + un = GMP_ABS (un); + + /* Count bytes in top limb. */ + limb = u->_mp_d[un-1]; + assert (limb != 0); + + k = (GMP_LIMB_BITS <= CHAR_BIT); + if (!k) + { + do { + int LOCAL_CHAR_BIT = CHAR_BIT; + k++; limb >>= LOCAL_CHAR_BIT; + } while (limb != 0); + } + /* else limb = 0; */ + + count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size; + + if (!r) + r = gmp_alloc (count * size); + + if (endian == 0) + endian = gmp_detect_endian (); + + p = (unsigned char *) r; + + word_step = (order != endian) ? 2 * size : 0; + + /* Process bytes from the least significant end, so point p at the + least significant word. */ + if (order == 1) + { + p += size * (count - 1); + word_step = - word_step; + } + + /* And at least significant byte of that word. */ + if (endian == 1) + p += (size - 1); + + for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step) + { + size_t j; + for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian) + { + if (sizeof (mp_limb_t) == 1) + { + if (i < un) + *p = u->_mp_d[i++]; + else + *p = 0; + } + else + { + int LOCAL_CHAR_BIT = CHAR_BIT; + if (bytes == 0) + { + if (i < un) + limb = u->_mp_d[i++]; + bytes = sizeof (mp_limb_t); + } + *p = limb; + limb >>= LOCAL_CHAR_BIT; + bytes--; + } + } + } + assert (i == un); + assert (k == count); + } + + if (countp) + *countp = count; + + return r; +} diff --git a/cross/lib/mini-gmp.h b/cross/lib/mini-gmp.h new file mode 100644 index 00000000000..59c24cf5111 --- /dev/null +++ b/cross/lib/mini-gmp.h @@ -0,0 +1,310 @@ +/* mini-gmp, a minimalistic implementation of a GNU GMP subset. + +Copyright 2011-2015, 2017, 2019-2021 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP 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 General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +/* About mini-gmp: This is a minimal implementation of a subset of the + GMP interface. It is intended for inclusion into applications which + have modest bignums needs, as a fallback when the real GMP library + is not installed. + + This file defines the public interface. */ + +#ifndef __MINI_GMP_H__ +#define __MINI_GMP_H__ + +/* For size_t */ +#include + +#if defined (__cplusplus) +extern "C" { +#endif + +void mp_set_memory_functions (void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t)); + +void mp_get_memory_functions (void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t)); + +#ifndef MINI_GMP_LIMB_TYPE +#define MINI_GMP_LIMB_TYPE long +#endif + +typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t; +typedef long mp_size_t; +typedef unsigned long mp_bitcnt_t; + +typedef mp_limb_t *mp_ptr; +typedef const mp_limb_t *mp_srcptr; + +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; + +typedef __mpz_struct mpz_t[1]; + +typedef __mpz_struct *mpz_ptr; +typedef const __mpz_struct *mpz_srcptr; + +extern const int mp_bits_per_limb; + +void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); +void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); +void mpn_zero (mp_ptr, mp_size_t); + +int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t); +int mpn_zero_p (mp_srcptr, mp_size_t); + +mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); + +mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); +mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); + +mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); +void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); +void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); +int mpn_perfect_square_p (mp_srcptr, mp_size_t); +mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); + +mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); +mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); + +mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t); +mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t); + +void mpn_com (mp_ptr, mp_srcptr, mp_size_t); +mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); + +mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t); + +mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t); +#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0) + +size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); +mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); + +void mpz_init (mpz_t); +void mpz_init2 (mpz_t, mp_bitcnt_t); +void mpz_clear (mpz_t); + +#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0]) +#define mpz_even_p(z) (! mpz_odd_p (z)) + +int mpz_sgn (const mpz_t); +int mpz_cmp_si (const mpz_t, long); +int mpz_cmp_ui (const mpz_t, unsigned long); +int mpz_cmp (const mpz_t, const mpz_t); +int mpz_cmpabs_ui (const mpz_t, unsigned long); +int mpz_cmpabs (const mpz_t, const mpz_t); +int mpz_cmp_d (const mpz_t, double); +int mpz_cmpabs_d (const mpz_t, double); + +void mpz_abs (mpz_t, const mpz_t); +void mpz_neg (mpz_t, const mpz_t); +void mpz_swap (mpz_t, mpz_t); + +void mpz_add_ui (mpz_t, const mpz_t, unsigned long); +void mpz_add (mpz_t, const mpz_t, const mpz_t); +void mpz_sub_ui (mpz_t, const mpz_t, unsigned long); +void mpz_ui_sub (mpz_t, unsigned long, const mpz_t); +void mpz_sub (mpz_t, const mpz_t, const mpz_t); + +void mpz_mul_si (mpz_t, const mpz_t, long int); +void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_mul (mpz_t, const mpz_t, const mpz_t); +void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_addmul (mpz_t, const mpz_t, const mpz_t); +void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int); +void mpz_submul (mpz_t, const mpz_t, const mpz_t); + +void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t); +void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t); +void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t); +void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t); + +void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); +void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); + +void mpz_mod (mpz_t, const mpz_t, const mpz_t); + +void mpz_divexact (mpz_t, const mpz_t, const mpz_t); + +int mpz_divisible_p (const mpz_t, const mpz_t); +int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t); + +unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long); +unsigned long mpz_cdiv_ui (const mpz_t, unsigned long); +unsigned long mpz_fdiv_ui (const mpz_t, unsigned long); +unsigned long mpz_tdiv_ui (const mpz_t, unsigned long); + +unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long); + +void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long); + +int mpz_divisible_ui_p (const mpz_t, unsigned long); + +unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long); +void mpz_gcd (mpz_t, const mpz_t, const mpz_t); +void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t); +void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long); +void mpz_lcm (mpz_t, const mpz_t, const mpz_t); +int mpz_invert (mpz_t, const mpz_t, const mpz_t); + +void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t); +void mpz_sqrt (mpz_t, const mpz_t); +int mpz_perfect_square_p (const mpz_t); + +void mpz_pow_ui (mpz_t, const mpz_t, unsigned long); +void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long); +void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t); +void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t); + +void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long); +int mpz_root (mpz_t, const mpz_t, unsigned long); + +void mpz_fac_ui (mpz_t, unsigned long); +void mpz_2fac_ui (mpz_t, unsigned long); +void mpz_mfac_uiui (mpz_t, unsigned long, unsigned long); +void mpz_bin_uiui (mpz_t, unsigned long, unsigned long); + +int mpz_probab_prime_p (const mpz_t, int); + +int mpz_tstbit (const mpz_t, mp_bitcnt_t); +void mpz_setbit (mpz_t, mp_bitcnt_t); +void mpz_clrbit (mpz_t, mp_bitcnt_t); +void mpz_combit (mpz_t, mp_bitcnt_t); + +void mpz_com (mpz_t, const mpz_t); +void mpz_and (mpz_t, const mpz_t, const mpz_t); +void mpz_ior (mpz_t, const mpz_t, const mpz_t); +void mpz_xor (mpz_t, const mpz_t, const mpz_t); + +mp_bitcnt_t mpz_popcount (const mpz_t); +mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t); +mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t); +mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t); + +int mpz_fits_slong_p (const mpz_t); +int mpz_fits_ulong_p (const mpz_t); +int mpz_fits_sint_p (const mpz_t); +int mpz_fits_uint_p (const mpz_t); +int mpz_fits_sshort_p (const mpz_t); +int mpz_fits_ushort_p (const mpz_t); +long int mpz_get_si (const mpz_t); +unsigned long int mpz_get_ui (const mpz_t); +double mpz_get_d (const mpz_t); +size_t mpz_size (const mpz_t); +mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t); + +void mpz_realloc2 (mpz_t, mp_bitcnt_t); +mp_srcptr mpz_limbs_read (mpz_srcptr); +mp_ptr mpz_limbs_modify (mpz_t, mp_size_t); +mp_ptr mpz_limbs_write (mpz_t, mp_size_t); +void mpz_limbs_finish (mpz_t, mp_size_t); +mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t); + +#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} + +void mpz_set_si (mpz_t, signed long int); +void mpz_set_ui (mpz_t, unsigned long int); +void mpz_set (mpz_t, const mpz_t); +void mpz_set_d (mpz_t, double); + +void mpz_init_set_si (mpz_t, signed long int); +void mpz_init_set_ui (mpz_t, unsigned long int); +void mpz_init_set (mpz_t, const mpz_t); +void mpz_init_set_d (mpz_t, double); + +size_t mpz_sizeinbase (const mpz_t, int); +char *mpz_get_str (char *, int, const mpz_t); +int mpz_set_str (mpz_t, const char *, int); +int mpz_init_set_str (mpz_t, const char *, int); + +/* This long list taken from gmp.h. */ +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ + || defined (__STDIO_LOADED) /* VMS */ \ + || defined (_STDIO) /* HPE NonStop */ \ + || defined (__DEFINED_FILE) /* musl */ +size_t mpz_out_str (FILE *, int, const mpz_t); +#endif + +void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *); +void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t); + +#if defined (__cplusplus) +} +#endif +#endif /* __MINI_GMP_H__ */ diff --git a/cross/lib/minmax.h b/cross/lib/minmax.h new file mode 100644 index 00000000000..1fbfc6616cf --- /dev/null +++ b/cross/lib/minmax.h @@ -0,0 +1,60 @@ +/* MIN, MAX macros. + Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _MINMAX_H +#define _MINMAX_H + +/* Note: MIN, MAX are also defined in on some systems + (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about + MIN, MAX macro redefinitions on some systems; the workaround is to + #include this file as the last one among the #include list. */ + +/* Before we define the following symbols we get the file + since otherwise we get redefinitions on some systems if is + included after this file. Likewise for . + If more than one of these system headers define MIN and MAX, pick just + one of the headers (because the definitions most likely are the same). */ +#if HAVE_MINMAX_IN_LIMITS_H +# include +#elif HAVE_MINMAX_IN_SYS_PARAM_H +# include +#endif + +/* Note: MIN and MAX should be used with two arguments of the + same type. They might not return the minimum and maximum of their two + arguments, if the arguments have different types or have unusual + floating-point values. For example, on a typical host with 32-bit 'int', + 64-bit 'long long', and 64-bit IEEE 754 'double' types: + + MAX (-1, 2147483648) returns 4294967295. + MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0. + MAX (NaN, 0.0) returns 0.0. + MAX (+0.0, -0.0) returns -0.0. + + and in each case the answer is in some sense bogus. */ + +/* MAX(a,b) returns the maximum of A and B. */ +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* MIN(a,b) returns the minimum of A and B. */ +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#endif /* _MINMAX_H */ diff --git a/cross/lib/mkostemp.c b/cross/lib/mkostemp.c new file mode 100644 index 00000000000..5cd5b3ac583 --- /dev/null +++ b/cross/lib/mkostemp.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2023 Free Software + Foundation, Inc. + This file is derived from the one in the GNU C Library. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if !_LIBC +# include +#endif + +#include + +#if !_LIBC +# include "tempname.h" +# define __gen_tempname gen_tempname +# ifndef __GTFILE +# define __GT_FILE GT_FILE +# endif +#endif + +#include + +#ifndef __GT_FILE +# define __GT_FILE 0 +#endif + +/* Generate a unique temporary file name from XTEMPLATE. + The last six characters of XTEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + Then open the file and return a fd. */ +int +mkostemp (char *xtemplate, int flags) +{ + return __gen_tempname (xtemplate, 0, flags, __GT_FILE); +} diff --git a/cross/lib/mktime-internal.h b/cross/lib/mktime-internal.h new file mode 100644 index 00000000000..709c36bdf56 --- /dev/null +++ b/cross/lib/mktime-internal.h @@ -0,0 +1,79 @@ +/* Internals of mktime and related functions + Copyright 2016-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Eggert . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +/* mktime_offset_t is a signed type wide enough to hold a UTC offset + in seconds, and used as part of the type of the offset-guess + argument to mktime_internal. In Glibc, it is always long int. + When in Gnulib, use time_t on platforms where time_t + is signed, to be compatible with platforms like BeOS that export + this implementation detail of mktime. On platforms where time_t is + unsigned, GNU and POSIX code can assume 'int' is at least 32 bits + which is wide enough for a UTC offset. */ +#ifdef _LIBC +typedef long int mktime_offset_t; +#elif defined TIME_T_IS_SIGNED +typedef time_t mktime_offset_t; +#else +typedef int mktime_offset_t; +#endif + +/* The source code uses identifiers like __time64_t for glibc + timestamps that can contain 64-bit values even when time_t is only + 32 bits. These are just macros for the ordinary identifiers unless + compiling within glibc when time_t is 32 bits. */ +#if ! (defined _LIBC && __TIMESIZE != 64) +# undef __time64_t +# define __time64_t time_t +# define __gmtime64_r __gmtime_r +# define __localtime64_r __localtime_r +# define __mktime64 mktime +# define __timegm64 timegm +#endif + +#ifndef _LIBC + +/* Although glibc source code uses leading underscores, Gnulib wants + ordinary names. + + Portable standalone applications should supply a that + declares a POSIX-compliant localtime_r, for the benefit of older + implementations that lack localtime_r or have a nonstandard one. + Similarly for gmtime_r. See the gnulib time_r module for one way + to implement this. */ + +# undef __gmtime_r +# undef __localtime_r +# define __gmtime_r gmtime_r +# define __localtime_r localtime_r + +# define __mktime_internal mktime_internal + +#endif + +/* Subroutine of mktime. Return the time_t representation of TP and + normalize TP, given that a struct tm * maps to a time_t as performed + by FUNC. Record next guess for localtime-gmtime offset in *OFFSET. */ +extern __time64_t __mktime_internal (struct tm *tp, + struct tm *(*func) (__time64_t const *, + struct tm *), + mktime_offset_t *offset) attribute_hidden; diff --git a/cross/lib/mktime.c b/cross/lib/mktime.c new file mode 100644 index 00000000000..94a4320e6ca --- /dev/null +++ b/cross/lib/mktime.c @@ -0,0 +1,578 @@ +/* Convert a 'struct tm' to a time_t value. + Copyright (C) 1993-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Eggert . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +/* The following macros influence what gets defined when this file is compiled: + + Macro/expression Which gnulib module This compilation unit + should define + + _LIBC (glibc proper) mktime + + NEED_MKTIME_WORKING mktime rpl_mktime + || NEED_MKTIME_WINDOWS + + NEED_MKTIME_INTERNAL mktime-internal mktime_internal + */ + +#ifndef _LIBC +# include +#endif + +/* Assume that leap seconds are possible, unless told otherwise. + If the host has a 'zic' command with a '-L leapsecondfilename' option, + then it supports leap seconds; otherwise it probably doesn't. */ +#ifndef LEAP_SECONDS_POSSIBLE +# define LEAP_SECONDS_POSSIBLE 1 +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef NEED_MKTIME_INTERNAL +# define NEED_MKTIME_INTERNAL 0 +#endif +#ifndef NEED_MKTIME_WINDOWS +# define NEED_MKTIME_WINDOWS 0 +#endif +#ifndef NEED_MKTIME_WORKING +# define NEED_MKTIME_WORKING 0 +#endif + +#include "mktime-internal.h" + +#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS) +static void +my_tzset (void) +{ +# if NEED_MKTIME_WINDOWS + /* Rectify the value of the environment variable TZ. + There are four possible kinds of such values: + - Traditional US time zone names, e.g. "PST8PDT". Syntax: see + + - Time zone names based on geography, that contain one or more + slashes, e.g. "Europe/Moscow". + - Time zone names based on geography, without slashes, e.g. + "Singapore". + - Time zone names that contain explicit DST rules. Syntax: see + + The Microsoft CRT understands only the first kind. It produces incorrect + results if the value of TZ is of the other kinds. + But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value + of the second kind for most geographies, or of the first kind in a few + other geographies. If it is of the second kind, neutralize it. For the + Microsoft CRT, an absent or empty TZ means the time zone that the user + has set in the Windows Control Panel. + If the value of TZ is of the third or fourth kind -- Cygwin programs + understand these syntaxes as well --, it does not matter whether we + neutralize it or not, since these values occur only when a Cygwin user + has set TZ explicitly; this case is 1. rare and 2. under the user's + responsibility. */ + const char *tz = getenv ("TZ"); + if (tz != NULL && strchr (tz, '/') != NULL) + _putenv ("TZ="); +# else + tzset (); +# endif +} +# undef __tzset +# define __tzset() my_tzset () +#endif + +#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL + +/* A signed type that can represent an integer number of years + multiplied by four times the number of seconds in a year. It is + needed when converting a tm_year value times the number of seconds + in a year. The factor of four comes because these products need + to be subtracted from each other, and sometimes with an offset + added to them, and then with another timestamp added, without + worrying about overflow. + + Much of the code uses long_int to represent __time64_t values, to + lessen the hassle of dealing with platforms where __time64_t is + unsigned, and because long_int should suffice to represent all + __time64_t values that mktime can generate even on platforms where + __time64_t is wider than the int components of struct tm. */ + +#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60 +typedef long int long_int; +#else +typedef long long int long_int; +#endif +verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60); + +/* Shift A right by B bits portably, by dividing A by 2**B and + truncating towards minus infinity. B should be in the range 0 <= B + <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful + bits in a long_int. LONG_INT_BITS is at least 32. + + ISO C99 says that A >> B is implementation-defined if A < 0. Some + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift + right in the usual way when A < 0, so SHR falls back on division if + ordinary A >> B doesn't seem to be the usual signed shift. */ + +static long_int +shr (long_int a, int b) +{ + long_int one = 1; + return (-one >> 1 == -1 + ? a >> b + : (a + (a < 0)) / (one << b) - (a < 0)); +} + +/* Bounds for the intersection of __time64_t and long_int. */ + +static long_int const mktime_min + = ((TYPE_SIGNED (__time64_t) + && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int)) + ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t)); +static long_int const mktime_max + = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t) + ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t)); + +#define EPOCH_YEAR 1970 +#define TM_YEAR_BASE 1900 +verify (TM_YEAR_BASE % 100 == 0); + +/* Is YEAR + TM_YEAR_BASE a leap year? */ +static bool +leapyear (long_int year) +{ + /* Don't add YEAR to TM_YEAR_BASE, as that might overflow. + Also, work even if YEAR is negative. */ + return + ((year & 3) == 0 + && (year % 100 != 0 + || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3))); +} + +/* How many days come before each month (0-12). */ +#ifndef _LIBC +static +#endif +const unsigned short int __mon_yday[2][13] = + { + /* Normal years. */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years. */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } + }; + + +/* Do the values A and B differ according to the rules for tm_isdst? + A and B differ if one is zero and the other positive. */ +static bool +isdst_differ (int a, int b) +{ + return (!a != !b) && (0 <= a) && (0 <= b); +} + +/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - + (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks + were not adjusted between the timestamps. + + The YEAR values uses the same numbering as TP->tm_year. Values + need not be in the usual range. However, YEAR1 - YEAR0 must not + overflow even when multiplied by three times the number of seconds + in a year, and likewise for YDAY1 - YDAY0 and three times the + number of seconds in a day. */ + +static long_int +ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1, + int year0, int yday0, int hour0, int min0, int sec0) +{ + verify (-1 / 2 == 0); + + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid integer overflow here. */ + int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3); + int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3); + int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0); + int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0); + int a400 = shr (a100, 2); + int b400 = shr (b100, 2); + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + + /* Compute the desired time without overflowing. */ + long_int years = year1 - year0; + long_int days = 365 * years + yday1 - yday0 + intervening_leap_days; + long_int hours = 24 * days + hour1 - hour0; + long_int minutes = 60 * hours + min1 - min0; + long_int seconds = 60 * minutes + sec1 - sec0; + return seconds; +} + +/* Return the average of A and B, even if A + B would overflow. + Round toward positive infinity. */ +static long_int +long_int_avg (long_int a, long_int b) +{ + return shr (a, 1) + shr (b, 1) + ((a | b) & 1); +} + +/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC) + minus *TP seconds, assuming no clock adjustments occurred between + the two timestamps. + + YEAR and YDAY must not be so large that multiplying them by three times the + number of seconds in a year (or day, respectively) would overflow long_int. + *TP should be in the usual range. */ +static long_int +tm_diff (long_int year, long_int yday, int hour, int min, int sec, + struct tm const *tp) +{ + return ydhms_diff (year, yday, hour, min, sec, + tp->tm_year, tp->tm_yday, + tp->tm_hour, tp->tm_min, tp->tm_sec); +} + +/* Use CONVERT to convert T to a struct tm value in *TM. T must be in + range for __time64_t. Return TM if successful, NULL (setting errno) on + failure. */ +static struct tm * +convert_time (struct tm *(*convert) (const __time64_t *, struct tm *), + long_int t, struct tm *tm) +{ + __time64_t x = t; + return convert (&x, tm); +} + +/* Use CONVERT to convert *T to a broken down time in *TP. + If *T is out of range for conversion, adjust it so that + it is the nearest in-range value and then convert that. + A value is in range if it fits in both __time64_t and long_int. + Return TP on success, NULL (setting errno) on failure. */ +static struct tm * +ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), + long_int *t, struct tm *tp) +{ + long_int t1 = (*t < mktime_min ? mktime_min + : *t <= mktime_max ? *t : mktime_max); + struct tm *r = convert_time (convert, t1, tp); + if (r) + { + *t = t1; + return r; + } + if (errno != EOVERFLOW) + return NULL; + + long_int bad = t1; + long_int ok = 0; + struct tm oktm; oktm.tm_sec = -1; + + /* BAD is a known out-of-range value, and OK is a known in-range one. + Use binary search to narrow the range between BAD and OK until + they differ by 1. */ + while (true) + { + long_int mid = long_int_avg (ok, bad); + if (mid == ok || mid == bad) + break; + if (convert_time (convert, mid, tp)) + ok = mid, oktm = *tp; + else if (errno != EOVERFLOW) + return NULL; + else + bad = mid; + } + + if (oktm.tm_sec < 0) + return NULL; + *t = ok; + *tp = oktm; + return tp; +} + + +/* Convert *TP to a __time64_t value, inverting + the monotonic and mostly-unit-linear conversion function CONVERT. + Use *OFFSET to keep track of a guess at the offset of the result, + compared to what the result would be for UTC without leap seconds. + If *OFFSET's guess is correct, only one CONVERT call is needed. + If successful, set *TP to the canonicalized struct tm; + otherwise leave *TP alone, return ((time_t) -1) and set errno. + This function is external because it is used also by timegm.c. */ +__time64_t +__mktime_internal (struct tm *tp, + struct tm *(*convert) (const __time64_t *, struct tm *), + mktime_offset_t *offset) +{ + struct tm tm; + + /* The maximum number of probes (calls to CONVERT) should be enough + to handle any combinations of time zone rule changes, solar time, + leap seconds, and oscillations around a spring-forward gap. + POSIX.1 prohibits leap seconds, but some hosts have them anyway. */ + int remaining_probes = 6; + + /* Time requested. Copy it in case CONVERT modifies *TP; this can + occur if TP is localtime's returned value and CONVERT is localtime. */ + int sec = tp->tm_sec; + int min = tp->tm_min; + int hour = tp->tm_hour; + int mday = tp->tm_mday; + int mon = tp->tm_mon; + int year_requested = tp->tm_year; + int isdst = tp->tm_isdst; + + /* 1 if the previous probe was DST. */ + int dst2 = 0; + + /* Ensure that mon is in range, and set year accordingly. */ + int mon_remainder = mon % 12; + int negative_mon_remainder = mon_remainder < 0; + int mon_years = mon / 12 - negative_mon_remainder; + long_int lyear_requested = year_requested; + long_int year = lyear_requested + mon_years; + + /* The other values need not be in range: + the remaining code handles overflows correctly. */ + + /* Calculate day of year from year, month, and day of month. + The result need not be in range. */ + int mon_yday = ((__mon_yday[leapyear (year)] + [mon_remainder + 12 * negative_mon_remainder]) + - 1); + long_int lmday = mday; + long_int yday = mon_yday + lmday; + + mktime_offset_t off = *offset; + int negative_offset_guess; + + int sec_requested = sec; + + if (LEAP_SECONDS_POSSIBLE) + { + /* Handle out-of-range seconds specially, + since ydhms_diff assumes every minute has 60 seconds. */ + if (sec < 0) + sec = 0; + if (59 < sec) + sec = 59; + } + + /* Invert CONVERT by probing. First assume the same offset as last + time. */ + + INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess); + long_int t0 = ydhms_diff (year, yday, hour, min, sec, + EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, + negative_offset_guess); + long_int t = t0, t1 = t0, t2 = t0; + + /* Repeatedly use the error to improve the guess. */ + + while (true) + { + if (! ranged_convert (convert, &t, &tm)) + return -1; + long_int dt = tm_diff (year, yday, hour, min, sec, &tm); + if (dt == 0) + break; + + if (t == t1 && t != t2 + && (tm.tm_isdst < 0 + || (isdst < 0 + ? dst2 <= (tm.tm_isdst != 0) + : (isdst != 0) != (tm.tm_isdst != 0)))) + /* We can't possibly find a match, as we are oscillating + between two values. The requested time probably falls + within a spring-forward gap of size DT. Follow the common + practice in this case, which is to return a time that is DT + away from the requested time, preferring a time whose + tm_isdst differs from the requested value. (If no tm_isdst + was requested and only one of the two values has a nonzero + tm_isdst, prefer that value.) In practice, this is more + useful than returning -1. */ + goto offset_found; + + remaining_probes--; + if (remaining_probes == 0) + { + __set_errno (EOVERFLOW); + return -1; + } + + t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0; + } + + /* We have a match. Check whether tm.tm_isdst has the requested + value, if any. */ + if (isdst_differ (isdst, tm.tm_isdst)) + { + /* tm.tm_isdst has the wrong value. Look for a neighboring + time with the right value, and use its UTC offset. + + Heuristic: probe the adjacent timestamps in both directions, + looking for the desired isdst. If none is found within a + reasonable duration bound, assume a one-hour DST difference. + This should work for all real time zone histories in the tz + database. */ + + /* +1 if we wanted standard time but got DST, -1 if the reverse. */ + int dst_difference = (isdst == 0) - (tm.tm_isdst == 0); + + /* Distance between probes when looking for a DST boundary. In + tzdata2003a, the shortest period of DST is 601200 seconds + (e.g., America/Recife starting 2000-10-08 01:00), and the + shortest period of non-DST surrounded by DST is 694800 + seconds (Africa/Tunis starting 1943-04-17 01:00). Use the + minimum of these two values, so we don't miss these short + periods when probing. */ + int stride = 601200; + + /* In TZDB 2021e, the longest period of DST (or of non-DST), in + which the DST (or adjacent DST) difference is not one hour, + is 457243209 seconds: e.g., America/Cambridge_Bay with leap + seconds, starting 1965-10-31 00:00 in a switch from + double-daylight time (-05) to standard time (-07), and + continuing to 1980-04-27 02:00 in a switch from standard time + (-07) to daylight time (-06). */ + int duration_max = 457243209; + + /* Search in both directions, so the maximum distance is half + the duration; add the stride to avoid off-by-1 problems. */ + int delta_bound = duration_max / 2 + stride; + + int delta, direction; + + for (delta = stride; delta < delta_bound; delta += stride) + for (direction = -1; direction <= 1; direction += 2) + { + long_int ot; + if (! INT_ADD_WRAPV (t, delta * direction, &ot)) + { + struct tm otm; + if (! ranged_convert (convert, &ot, &otm)) + return -1; + if (! isdst_differ (isdst, otm.tm_isdst)) + { + /* We found the desired tm_isdst. + Extrapolate back to the desired time. */ + long_int gt = ot + tm_diff (year, yday, hour, min, sec, + &otm); + if (mktime_min <= gt && gt <= mktime_max) + { + if (convert_time (convert, gt, &tm)) + { + t = gt; + goto offset_found; + } + if (errno != EOVERFLOW) + return -1; + } + } + } + } + + /* No unusual DST offset was found nearby. Assume one-hour DST. */ + t += 60 * 60 * dst_difference; + if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm)) + goto offset_found; + + __set_errno (EOVERFLOW); + return -1; + } + + offset_found: + /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS. + This is just a heuristic to speed up the next mktime call, and + correctness is unaffected if integer overflow occurs here. */ + INT_SUBTRACT_WRAPV (t, t0, offset); + INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset); + + if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec) + { + /* Adjust time to reflect the tm_sec requested, not the normalized value. + Also, repair any damage from a false match due to a leap second. */ + long_int sec_adjustment = sec == 0 && tm.tm_sec == 60; + sec_adjustment -= sec; + sec_adjustment += sec_requested; + if (INT_ADD_WRAPV (t, sec_adjustment, &t) + || ! (mktime_min <= t && t <= mktime_max)) + { + __set_errno (EOVERFLOW); + return -1; + } + if (! convert_time (convert, t, &tm)) + return -1; + } + + *tp = tm; + return t; +} + +#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */ + +#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS + +/* Convert *TP to a __time64_t value. */ +__time64_t +__mktime64 (struct tm *tp) +{ + /* POSIX.1 8.1.1 requires that whenever mktime() is called, the + time zone names contained in the external variable 'tzname' shall + be set as if the tzset() function had been called. */ + __tzset (); + +# if defined _LIBC || NEED_MKTIME_WORKING + static mktime_offset_t localtime_offset; + return __mktime_internal (tp, __localtime64_r, &localtime_offset); +# else +# undef mktime + return mktime (tp); +# endif +} +#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ + +#if defined _LIBC && __TIMESIZE != 64 + +libc_hidden_def (__mktime64) + +time_t +mktime (struct tm *tp) +{ + struct tm tm = *tp; + __time64_t t = __mktime64 (&tm); + if (in_time_t_range (t)) + { + *tp = tm; + return t; + } + else + { + __set_errno (EOVERFLOW); + return -1; + } +} + +#endif + +weak_alias (mktime, timelocal) +libc_hidden_def (mktime) +libc_hidden_weak (timelocal) diff --git a/cross/lib/nanosleep.c b/cross/lib/nanosleep.c new file mode 100644 index 00000000000..3f295f49b5d --- /dev/null +++ b/cross/lib/nanosleep.c @@ -0,0 +1,193 @@ +/* Provide a replacement for the POSIX nanosleep function. + + Copyright (C) 1999-2000, 2002, 2004-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering + and Bruno Haible for the native Windows part */ + +#include + +#include + +#include "intprops.h" + +#include +#include +#include +#include + +#include + +#include + + +enum { BILLION = 1000 * 1000 * 1000 }; + +#if HAVE_BUG_BIG_NANOSLEEP + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +# undef nanosleep +{ + /* nanosleep mishandles large sleeps due to internal overflow problems. + The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which + can't sleep more than 24.85 days (2^31 milliseconds). Similarly, + cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds). + Solve this by breaking the sleep up into smaller chunks. */ + + if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) + { + errno = EINVAL; + return -1; + } + + { + /* Verify that time_t is large enough. */ + static_assert (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60); + const time_t limit = 24 * 24 * 60 * 60; + time_t seconds = requested_delay->tv_sec; + struct timespec intermediate; + intermediate.tv_nsec = requested_delay->tv_nsec; + + while (limit < seconds) + { + int result; + intermediate.tv_sec = limit; + result = nanosleep (&intermediate, remaining_delay); + seconds -= limit; + if (result) + { + if (remaining_delay) + remaining_delay->tv_sec += seconds; + return result; + } + intermediate.tv_nsec = 0; + } + intermediate.tv_sec = seconds; + return nanosleep (&intermediate, remaining_delay); + } +} + +#elif defined _WIN32 && ! defined __CYGWIN__ +/* Native Windows platforms. */ + +# define WIN32_LEAN_AND_MEAN +# include + +/* The Windows API function Sleep() has a resolution of about 15 ms and takes + at least 5 ms to execute. We use this function for longer time periods. + Additionally, we use busy-looping over short time periods, to get a + resolution of about 0.01 ms. In order to measure such short timespans, + we use the QueryPerformanceCounter() function. */ + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +{ + static bool initialized; + /* Number of performance counter increments per nanosecond, + or zero if it could not be determined. */ + static double ticks_per_nanosecond; + + if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) + { + errno = EINVAL; + return -1; + } + + /* For requested delays of one second or more, 15ms resolution is + sufficient. */ + if (requested_delay->tv_sec == 0) + { + if (!initialized) + { + /* Initialize ticks_per_nanosecond. */ + LARGE_INTEGER ticks_per_second; + + if (QueryPerformanceFrequency (&ticks_per_second)) + ticks_per_nanosecond = + (double) ticks_per_second.QuadPart / 1000000000.0; + + initialized = true; + } + if (ticks_per_nanosecond) + { + /* QueryPerformanceFrequency worked. We can use + QueryPerformanceCounter. Use a combination of Sleep and + busy-looping. */ + /* Number of milliseconds to pass to the Sleep function. + Since Sleep can take up to 8 ms less or 8 ms more than requested + (or maybe more if the system is loaded), we subtract 10 ms. */ + int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10; + /* Determine how many ticks to delay. */ + LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond; + /* Start. */ + LARGE_INTEGER counter_before; + if (QueryPerformanceCounter (&counter_before)) + { + /* Wait until the performance counter has reached this value. + We don't need to worry about overflow, because the performance + counter is reset at reboot, and with a frequency of 3.6E6 + ticks per second 63 bits suffice for over 80000 years. */ + LONGLONG wait_until = counter_before.QuadPart + wait_ticks; + /* Use Sleep for the longest part. */ + if (sleep_millis > 0) + Sleep (sleep_millis); + /* Busy-loop for the rest. */ + for (;;) + { + LARGE_INTEGER counter_after; + if (!QueryPerformanceCounter (&counter_after)) + /* QueryPerformanceCounter failed, but succeeded earlier. + Should not happen. */ + break; + if (counter_after.QuadPart >= wait_until) + /* The requested time has elapsed. */ + break; + } + goto done; + } + } + } + /* Implementation for long delays and as fallback. */ + Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000); + + done: + /* Sleep is not interruptible. So there is no remaining delay. */ + if (remaining_delay != NULL) + { + remaining_delay->tv_sec = 0; + remaining_delay->tv_nsec = 0; + } + return 0; +} + +#else +/* Other platforms lacking nanosleep. + It's not clear whether these are still practical porting targets. + For now, just fall back on pselect. */ + +/* Suspend execution for at least *REQUESTED_DELAY seconds. The + *REMAINING_DELAY part isn't implemented yet. */ + +int +nanosleep (const struct timespec *requested_delay, + struct timespec *remaining_delay) +{ + return pselect (0, NULL, NULL, NULL, requested_delay, NULL); +} +#endif diff --git a/cross/lib/nproc.c b/cross/lib/nproc.c new file mode 100644 index 00000000000..2740c458c11 --- /dev/null +++ b/cross/lib/nproc.c @@ -0,0 +1,404 @@ +/* Detect the number of processors. + + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Glen Lenker and Bruno Haible. */ + +#include +#include "nproc.h" + +#include +#include +#include + +#if HAVE_PTHREAD_GETAFFINITY_NP && 0 +# include +# include +#endif +#if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP +# include +#endif + +#include + +#if HAVE_SYS_PSTAT_H +# include +#endif + +#if HAVE_SYS_SYSMP_H +# include +#endif + +#if HAVE_SYS_PARAM_H +# include +#endif + +#if HAVE_SYS_SYSCTL_H && ! defined __GLIBC__ +# include +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#include "c-ctype.h" + +#include "minmax.h" + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +/* Return the number of processors available to the current process, based + on a modern system call that returns the "affinity" between the current + process and each CPU. Return 0 if unknown or if such a system call does + not exist. */ +static unsigned long +num_processors_via_affinity_mask (void) +{ + /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np, + but with different APIs. Also it requires linking with -lpthread. + Therefore this code is not enabled. + glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has + sched_getaffinity_np. */ +#if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0 + { + cpu_set_t set; + + if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0) + { + unsigned long count; + +# ifdef CPU_COUNT + /* glibc >= 2.6 has the CPU_COUNT macro. */ + count = CPU_COUNT (&set); +# else + size_t i; + + count = 0; + for (i = 0; i < CPU_SETSIZE; i++) + if (CPU_ISSET (i, &set)) + count++; +# endif + if (count > 0) + return count; + } + } +#elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0 + { + cpuset_t *set; + + set = cpuset_create (); + if (set != NULL) + { + unsigned long count = 0; + + if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set) + == 0) + { + cpuid_t i; + + for (i = 0;; i++) + { + int ret = cpuset_isset (i, set); + if (ret < 0) + break; + if (ret > 0) + count++; + } + } + cpuset_destroy (set); + if (count > 0) + return count; + } + } +#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */ + { + cpu_set_t set; + + if (sched_getaffinity (0, sizeof (set), &set) == 0) + { + unsigned long count; + +# ifdef CPU_COUNT + /* glibc >= 2.6 has the CPU_COUNT macro. */ + count = CPU_COUNT (&set); +# else + size_t i; + + count = 0; + for (i = 0; i < CPU_SETSIZE; i++) + if (CPU_ISSET (i, &set)) + count++; +# endif + if (count > 0) + return count; + } + } +#elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */ + { + cpuset_t *set; + + set = cpuset_create (); + if (set != NULL) + { + unsigned long count = 0; + + if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0) + { + cpuid_t i; + + for (i = 0;; i++) + { + int ret = cpuset_isset (i, set); + if (ret < 0) + break; + if (ret > 0) + count++; + } + } + cpuset_destroy (set); + if (count > 0) + return count; + } + } +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ + { /* This works on native Windows platforms. */ + DWORD_PTR process_mask; + DWORD_PTR system_mask; + + if (GetProcessAffinityMask (GetCurrentProcess (), + &process_mask, &system_mask)) + { + DWORD_PTR mask = process_mask; + unsigned long count = 0; + + for (; mask != 0; mask = mask >> 1) + if (mask & 1) + count++; + if (count > 0) + return count; + } + } +#endif + + return 0; +} + + +/* Return the total number of processors. Here QUERY must be one of + NPROC_ALL, NPROC_CURRENT. The result is guaranteed to be at least 1. */ +static unsigned long int +num_processors_ignoring_omp (enum nproc_query query) +{ + /* On systems with a modern affinity mask system call, we have + sysconf (_SC_NPROCESSORS_CONF) + >= sysconf (_SC_NPROCESSORS_ONLN) + >= num_processors_via_affinity_mask () + The first number is the number of CPUs configured in the system. + The second number is the number of CPUs available to the scheduler. + The third number is the number of CPUs available to the current process. + + Note! On Linux systems with glibc, the first and second number come from + the /sys and /proc file systems (see + glibc/sysdeps/unix/sysv/linux/getsysstats.c). + In some situations these file systems are not mounted, and the sysconf call + returns 1 or 2 (), + which does not reflect the reality. */ + + if (query == NPROC_CURRENT) + { + /* Try the modern affinity mask system call. */ + { + unsigned long nprocs = num_processors_via_affinity_mask (); + + if (nprocs > 0) + return nprocs; + } + +#if defined _SC_NPROCESSORS_ONLN + { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris, + Cygwin, Haiku. */ + long int nprocs = sysconf (_SC_NPROCESSORS_ONLN); + if (nprocs > 0) + return nprocs; + } +#endif + } + else /* query == NPROC_ALL */ + { +#if defined _SC_NPROCESSORS_CONF + { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris, + Cygwin, Haiku. */ + long int nprocs = sysconf (_SC_NPROCESSORS_CONF); + +# if __GLIBC__ >= 2 && defined __linux__ + /* On Linux systems with glibc, this information comes from the /sys and + /proc file systems (see glibc/sysdeps/unix/sysv/linux/getsysstats.c). + In some situations these file systems are not mounted, and the + sysconf call returns 1 or 2. But we wish to guarantee that + num_processors (NPROC_ALL) >= num_processors (NPROC_CURRENT). */ + if (nprocs == 1 || nprocs == 2) + { + unsigned long nprocs_current = num_processors_via_affinity_mask (); + + if (/* nprocs_current > 0 && */ nprocs_current > nprocs) + nprocs = nprocs_current; + } +# endif + + if (nprocs > 0) + return nprocs; + } +#endif + } + +#if HAVE_PSTAT_GETDYNAMIC + { /* This works on HP-UX. */ + struct pst_dynamic psd; + if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0) + { + /* The field psd_proc_cnt contains the number of active processors. + In newer releases of HP-UX 11, the field psd_max_proc_cnt includes + deactivated processors. */ + if (query == NPROC_CURRENT) + { + if (psd.psd_proc_cnt > 0) + return psd.psd_proc_cnt; + } + else + { + if (psd.psd_max_proc_cnt > 0) + return psd.psd_max_proc_cnt; + } + } + } +#endif + +#if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS + { /* This works on IRIX. */ + /* MP_NPROCS yields the number of installed processors. + MP_NAPROCS yields the number of processors available to unprivileged + processes. */ + int nprocs = + sysmp (query == NPROC_CURRENT && getuid () != 0 + ? MP_NAPROCS + : MP_NPROCS); + if (nprocs > 0) + return nprocs; + } +#endif + + /* Finally, as fallback, use the APIs that don't distinguish between + NPROC_CURRENT and NPROC_ALL. */ + +#if HAVE_SYSCTL && ! defined __GLIBC__ && defined HW_NCPU + { /* This works on macOS, FreeBSD, NetBSD, OpenBSD. + macOS 10.14 does not allow mib to be const. */ + int nprocs; + size_t len = sizeof (nprocs); + static int mib[][2] = { +# ifdef HW_NCPUONLINE + { CTL_HW, HW_NCPUONLINE }, +# endif + { CTL_HW, HW_NCPU } + }; + for (int i = 0; i < ARRAY_SIZE (mib); i++) + { + if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0 + && len == sizeof (nprocs) + && 0 < nprocs) + return nprocs; + } + } +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ + { /* This works on native Windows platforms. */ + SYSTEM_INFO system_info; + GetSystemInfo (&system_info); + if (0 < system_info.dwNumberOfProcessors) + return system_info.dwNumberOfProcessors; + } +#endif + + return 1; +} + +/* Parse OMP environment variables without dependence on OMP. + Return 0 for invalid values. */ +static unsigned long int +parse_omp_threads (char const* threads) +{ + unsigned long int ret = 0; + + if (threads == NULL) + return ret; + + /* The OpenMP spec says that the value assigned to the environment variables + "may have leading and trailing white space". */ + while (*threads != '\0' && c_isspace (*threads)) + threads++; + + /* Convert it from positive decimal to 'unsigned long'. */ + if (c_isdigit (*threads)) + { + char *endptr = NULL; + unsigned long int value = strtoul (threads, &endptr, 10); + + if (endptr != NULL) + { + while (*endptr != '\0' && c_isspace (*endptr)) + endptr++; + if (*endptr == '\0') + return value; + /* Also accept the first value in a nesting level, + since we can't determine the nesting level from env vars. */ + else if (*endptr == ',') + return value; + } + } + + return ret; +} + +unsigned long int +num_processors (enum nproc_query query) +{ + unsigned long int omp_env_limit = ULONG_MAX; + + if (query == NPROC_CURRENT_OVERRIDABLE) + { + unsigned long int omp_env_threads; + /* Honor the OpenMP environment variables, recognized also by all + programs that are based on OpenMP. */ + omp_env_threads = parse_omp_threads (getenv ("OMP_NUM_THREADS")); + omp_env_limit = parse_omp_threads (getenv ("OMP_THREAD_LIMIT")); + if (! omp_env_limit) + omp_env_limit = ULONG_MAX; + + if (omp_env_threads) + return MIN (omp_env_threads, omp_env_limit); + + query = NPROC_CURRENT; + } + /* Here query is one of NPROC_ALL, NPROC_CURRENT. */ + { + unsigned long nprocs = num_processors_ignoring_omp (query); + return MIN (nprocs, omp_env_limit); + } +} diff --git a/cross/lib/nproc.h b/cross/lib/nproc.h new file mode 100644 index 00000000000..7b8b16d37cd --- /dev/null +++ b/cross/lib/nproc.h @@ -0,0 +1,46 @@ +/* Detect the number of processors. + + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Glen Lenker and Bruno Haible. */ + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* A "processor" in this context means a thread execution unit, that is either + - an execution core in a (possibly multi-core) chip, in a (possibly multi- + chip) module, in a single computer, or + - a thread execution unit inside a core + (hyper-threading, see ). + Which of the two definitions is used, is unspecified. */ + +enum nproc_query +{ + NPROC_ALL, /* total number of processors */ + NPROC_CURRENT, /* processors available to the current process */ + NPROC_CURRENT_OVERRIDABLE /* likewise, but overridable through the + OMP_NUM_THREADS environment variable */ +}; + +/* Return the total number of processors. The result is guaranteed to + be at least 1. */ +extern unsigned long int num_processors (enum nproc_query query); + +#ifdef __cplusplus +} +#endif /* C++ */ diff --git a/cross/lib/nstrftime.c b/cross/lib/nstrftime.c new file mode 100644 index 00000000000..68bb560910d --- /dev/null +++ b/cross/lib/nstrftime.c @@ -0,0 +1,1490 @@ +/* Copyright (C) 1991-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#ifdef _LIBC +# define USE_IN_EXTENDED_LOCALE_MODEL 1 +# define HAVE_STRUCT_ERA_ENTRY 1 +# define HAVE_TM_GMTOFF 1 +# define HAVE_STRUCT_TM_TM_ZONE 1 +# define HAVE_TZNAME 1 +# include "../locale/localeinfo.h" +#else +# include +# if FPRINTFTIME +# include "fprintftime.h" +# else +# include "strftime.h" +# endif +# include "time-internal.h" +#endif + +#include +#include +#include + +#if HAVE_TZNAME && !HAVE_DECL_TZNAME +extern char *tzname[]; +#endif + +/* Do multibyte processing if multibyte encodings are supported, unless + multibyte sequences are safe in formats. Multibyte sequences are + safe if they cannot contain byte sequences that look like format + conversion specifications. The multibyte encodings used by the + C library on the various platforms (UTF-8, GB2312, GBK, CP936, + GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949, + SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%' + cannot occur in a multibyte character except in the first byte. + + The DEC-HANYU encoding used on OSF/1 is not safe for formats, but + this encoding has never been seen in real-life use, so we ignore + it. */ +#if !(defined __osf__ && 0) +# define MULTIBYTE_IS_FORMAT_SAFE 1 +#endif +#define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE) + +#if DO_MULTIBYTE +# include + static const mbstate_t mbstate_zero; +#endif + +#include +#include +#include +#include + +#include "attribute.h" +#include + +#ifdef COMPILE_WIDE +# include +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# define L_(Str) L##Str +# define NLW(Sym) _NL_W##Sym + +# define MEMCPY(d, s, n) __wmemcpy (d, s, n) +# define STRLEN(s) __wcslen (s) + +#else +# define CHAR_T char +# define UCHAR_T unsigned char +# define L_(Str) Str +# define NLW(Sym) Sym +# define ABALTMON_1 _NL_ABALTMON_1 + +# define MEMCPY(d, s, n) memcpy (d, s, n) +# define STRLEN(s) strlen (s) + +#endif + +/* Shift A right by B bits portably, by dividing A by 2**B and + truncating towards minus infinity. A and B should be free of side + effects, and B should be in the range 0 <= B <= INT_BITS - 2, where + INT_BITS is the number of useful bits in an int. GNU code can + assume that INT_BITS is at least 32. + + ISO C99 says that A >> B is implementation-defined if A < 0. Some + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift + right in the usual way when A < 0, so SHR falls back on division if + ordinary A >> B doesn't seem to be the usual signed shift. */ +#define SHR(a, b) \ + (-1 >> 1 == -1 \ + ? (a) >> (b) \ + : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0)) + +#define TM_YEAR_BASE 1900 + +#ifndef __isleap +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +#endif + + +#ifdef _LIBC +# define mktime_z(tz, tm) mktime (tm) +# define tzname __tzname +# define tzset __tzset +#endif + +#ifndef FPRINTFTIME +# define FPRINTFTIME 0 +#endif + +#if FPRINTFTIME +# define STREAM_OR_CHAR_T FILE +# define STRFTIME_ARG(x) /* empty */ +#else +# define STREAM_OR_CHAR_T CHAR_T +# define STRFTIME_ARG(x) x, +#endif + +#if FPRINTFTIME +# define memset_byte(P, Len, Byte) \ + do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0) +# define memset_space(P, Len) memset_byte (P, Len, ' ') +# define memset_zero(P, Len) memset_byte (P, Len, '0') +#elif defined COMPILE_WIDE +# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len)) +# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len)) +#else +# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len)) +# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len)) +#endif + +#if FPRINTFTIME +# define advance(P, N) +#else +# define advance(P, N) ((P) += (N)) +#endif + +#define add(n, f) width_add (width, n, f) +#define width_add(width, n, f) \ + do \ + { \ + size_t _n = (n); \ + size_t _w = pad == L_('-') || width < 0 ? 0 : width; \ + size_t _incr = _n < _w ? _w : _n; \ + if (_incr >= maxsize - i) \ + { \ + errno = ERANGE; \ + return 0; \ + } \ + if (p) \ + { \ + if (_n < _w) \ + { \ + size_t _delta = _w - _n; \ + if (pad == L_('0') || pad == L_('+')) \ + memset_zero (p, _delta); \ + else \ + memset_space (p, _delta); \ + } \ + f; \ + advance (p, _n); \ + } \ + i += _incr; \ + } while (0) + +#define add1(c) width_add1 (width, c) +#if FPRINTFTIME +# define width_add1(width, c) width_add (width, 1, fputc (c, p)) +#else +# define width_add1(width, c) width_add (width, 1, *p = c) +#endif + +#define cpy(n, s) width_cpy (width, n, s) +#if FPRINTFTIME +# define width_cpy(width, n, s) \ + width_add (width, n, \ + do \ + { \ + if (to_lowcase) \ + fwrite_lowcase (p, (s), _n); \ + else if (to_uppcase) \ + fwrite_uppcase (p, (s), _n); \ + else \ + { \ + /* Ignore the value of fwrite. The caller can determine whether \ + an error occurred by inspecting ferror (P). All known fwrite \ + implementations set the stream's error indicator when they \ + fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \ + not require this. */ \ + fwrite (s, _n, 1, p); \ + } \ + } \ + while (0) \ + ) +#else +# define width_cpy(width, n, s) \ + width_add (width, n, \ + if (to_lowcase) \ + memcpy_lowcase (p, (s), _n LOCALE_ARG); \ + else if (to_uppcase) \ + memcpy_uppcase (p, (s), _n LOCALE_ARG); \ + else \ + MEMCPY ((void *) p, (void const *) (s), _n)) +#endif + +#ifdef COMPILE_WIDE +# ifndef USE_IN_EXTENDED_LOCALE_MODEL +# undef __mbsrtowcs_l +# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st) +# endif +# define widen(os, ws, l) \ + { \ + mbstate_t __st; \ + const char *__s = os; \ + memset (&__st, '\0', sizeof (__st)); \ + l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \ + ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \ + (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \ + } +#endif + + +#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +# define strftime __strftime_l +# define wcsftime __wcsftime_l +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , locale_t loc +# define LOCALE_ARG , loc +# define HELPER_LOCALE_ARG , current +#else +# define LOCALE_PARAM +# define LOCALE_ARG +# ifdef _LIBC +# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME) +# else +# define HELPER_LOCALE_ARG +# endif +#endif + +#ifdef COMPILE_WIDE +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define TOUPPER(Ch, L) __towupper_l (Ch, L) +# define TOLOWER(Ch, L) __towlower_l (Ch, L) +# else +# define TOUPPER(Ch, L) towupper (Ch) +# define TOLOWER(Ch, L) towlower (Ch) +# endif +#else +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define TOUPPER(Ch, L) __toupper_l (Ch, L) +# define TOLOWER(Ch, L) __tolower_l (Ch, L) +# else +# define TOUPPER(Ch, L) toupper (Ch) +# define TOLOWER(Ch, L) tolower (Ch) +# endif +#endif +/* We don't use 'isdigit' here since the locale dependent + interpretation is not what we want here. We only need to accept + the arabic digits in the ASCII range. One day there is perhaps a + more reliable way to accept other sets of digits. */ +#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9) + +#if FPRINTFTIME +static void +fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len) +{ + while (len-- > 0) + { + fputc (TOLOWER ((UCHAR_T) *src, loc), fp); + ++src; + } +} + +static void +fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len) +{ + while (len-- > 0) + { + fputc (TOUPPER ((UCHAR_T) *src, loc), fp); + ++src; + } +} +#else +static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, + size_t len LOCALE_PARAM); + +static CHAR_T * +memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) +{ + while (len-- > 0) + dest[len] = TOLOWER ((UCHAR_T) src[len], loc); + return dest; +} + +static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, + size_t len LOCALE_PARAM); + +static CHAR_T * +memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) +{ + while (len-- > 0) + dest[len] = TOUPPER ((UCHAR_T) src[len], loc); + return dest; +} +#endif + + +#if ! HAVE_TM_GMTOFF +/* Yield the difference between *A and *B, + measured in seconds, ignoring leap seconds. */ +# define tm_diff ftime_tm_diff +static int tm_diff (const struct tm *, const struct tm *); +static int +tm_diff (const struct tm *a, const struct tm *b) +{ + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid int overflow in leap day calculations, + but it's OK to assume that A and B are close to each other. */ + int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3); + int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3); + int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0); + int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0); + int a400 = SHR (a100, 2); + int b400 = SHR (b100, 2); + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + int years = a->tm_year - b->tm_year; + int days = (365 * years + intervening_leap_days + + (a->tm_yday - b->tm_yday)); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} +#endif /* ! HAVE_TM_GMTOFF */ + + + +/* The number of days from the first day of the first ISO week of this + year to the year day YDAY with week day WDAY. ISO weeks start on + Monday; the first ISO week has the year's first Thursday. YDAY may + be as small as YDAY_MINIMUM. */ +#define ISO_WEEK_START_WDAY 1 /* Monday */ +#define ISO_WEEK1_WDAY 4 /* Thursday */ +#define YDAY_MINIMUM (-366) +static int iso_week_days (int, int); +static __inline int +iso_week_days (int yday, int wday) +{ + /* Add enough to the first operand of % to make it nonnegative. */ + int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; + return (yday + - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 + + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); +} + + +/* When compiling this file, GNU applications can #define my_strftime + to a symbol (typically nstrftime) to get an extended strftime with + extra arguments TZ and NS. */ + +#if FPRINTFTIME +# undef my_strftime +# define my_strftime fprintftime +#endif + +#ifdef my_strftime +# define extra_args , tz, ns +# define extra_args_spec , timezone_t tz, int ns +#else +# if defined COMPILE_WIDE +# define my_strftime wcsftime +# define nl_get_alt_digit _nl_get_walt_digit +# else +# define my_strftime strftime +# define nl_get_alt_digit _nl_get_alt_digit +# endif +# define extra_args +# define extra_args_spec +/* We don't have this information in general. */ +# define tz 1 +# define ns 0 +#endif + +static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t) + const CHAR_T *, const struct tm *, + bool, int, int, bool * + extra_args_spec LOCALE_PARAM); + +/* Write information from TP into S according to the format + string FORMAT, writing no more that MAXSIZE characters + (including the terminating '\0') and returning number of + characters written. If S is NULL, nothing will be written + anywhere, so to determine how many characters would be + written, use NULL for S and (size_t) -1 for MAXSIZE. */ +size_t +my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) + const CHAR_T *format, + const struct tm *tp extra_args_spec LOCALE_PARAM) +{ + bool tzset_called = false; + return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false, + 0, -1, &tzset_called extra_args LOCALE_ARG); +} +libc_hidden_def (my_strftime) + +/* Just like my_strftime, above, but with more parameters. + UPCASE indicates that the result should be converted to upper case. + YR_SPEC and WIDTH specify the padding and width for the year. + *TZSET_CALLED indicates whether tzset has been called here. */ +static size_t +__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) + const CHAR_T *format, + const struct tm *tp, bool upcase, + int yr_spec, int width, bool *tzset_called + extra_args_spec LOCALE_PARAM) +{ +#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL + struct __locale_data *const current = loc->__locales[LC_TIME]; +#endif +#if FPRINTFTIME + size_t maxsize = (size_t) -1; +#endif + + int saved_errno = errno; + int hour12 = tp->tm_hour; +#ifdef _NL_CURRENT + /* We cannot make the following values variables since we must delay + the evaluation of these values until really needed since some + expressions might not be valid in every situation. The 'struct tm' + might be generated by a strptime() call that initialized + only a few elements. Dereference the pointers only if the format + requires this. Then it is ok to fail if the pointers are invalid. */ +# define a_wkday \ + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))) +# define f_wkday \ + ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))) +# define a_month \ + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))) +# define f_month \ + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) +# define a_altmonth \ + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon))) +# define f_altmonth \ + ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ + ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon))) +# define ampm \ + ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ + ? NLW(PM_STR) : NLW(AM_STR))) + +# define aw_len STRLEN (a_wkday) +# define am_len STRLEN (a_month) +# define aam_len STRLEN (a_altmonth) +# define ap_len STRLEN (ampm) +#endif +#if HAVE_TZNAME + char **tzname_vec = tzname; +#endif + const char *zone; + size_t i = 0; + STREAM_OR_CHAR_T *p = s; + const CHAR_T *f; +#if DO_MULTIBYTE && !defined COMPILE_WIDE + const char *format_end = NULL; +#endif + + zone = NULL; +#if HAVE_STRUCT_TM_TM_ZONE + /* The POSIX test suite assumes that setting + the environment variable TZ to a new value before calling strftime() + will influence the result (the %Z format) even if the information in + TP is computed with a totally different time zone. + This is bogus: though POSIX allows bad behavior like this, + POSIX does not require it. Do the right thing instead. */ + zone = (const char *) tp->tm_zone; +#endif +#if HAVE_TZNAME + if (!tz) + { + if (! (zone && *zone)) + zone = "GMT"; + } + else + { +# if !HAVE_STRUCT_TM_TM_ZONE + /* Infer the zone name from *TZ instead of from TZNAME. */ + tzname_vec = tz->tzname_copy; +# endif + } + /* The tzset() call might have changed the value. */ + if (!(zone && *zone) && tp->tm_isdst >= 0) + { + /* POSIX.1 requires that local time zone information be used as + though strftime called tzset. */ +# ifndef my_strftime + if (!*tzset_called) + { + tzset (); + *tzset_called = true; + } +# endif + zone = tzname_vec[tp->tm_isdst != 0]; + } +#endif + if (! zone) + zone = ""; + + if (hour12 > 12) + hour12 -= 12; + else + if (hour12 == 0) + hour12 = 12; + + for (f = format; *f != '\0'; width = -1, f++) + { + int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */ + int modifier; /* Field modifier ('E', 'O', or 0). */ + int digits = 0; /* Max digits for numeric format. */ + int number_value; /* Numeric value to be printed. */ + unsigned int u_number_value; /* (unsigned int) number_value. */ + bool negative_number; /* The number is negative. */ + bool always_output_a_sign; /* +/- should always be output. */ + int tz_colon_mask; /* Bitmask of where ':' should appear. */ + const CHAR_T *subfmt; + CHAR_T *bufp; + CHAR_T buf[1 + + 2 /* for the two colons in a %::z or %:::z time zone */ + + (sizeof (int) < sizeof (time_t) + ? INT_STRLEN_BOUND (time_t) + : INT_STRLEN_BOUND (int))]; + bool to_lowcase = false; + bool to_uppcase = upcase; + size_t colons; + bool change_case = false; + int format_char; + int subwidth; + +#if DO_MULTIBYTE && !defined COMPILE_WIDE + switch (*f) + { + case L_('%'): + break; + + case L_('\b'): case L_('\t'): case L_('\n'): + case L_('\v'): case L_('\f'): case L_('\r'): + case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'): + case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'): + case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'): + case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'): + case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'): + case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'): + case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'): + case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'): + case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'): + case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'): + case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'): + case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'): + case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'): + case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'): + case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'): + case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'): + case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'): + case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'): + case L_('~'): + /* The C Standard requires these 98 characters (plus '%') to + be in the basic execution character set. None of these + characters can start a multibyte sequence, so they need + not be analyzed further. */ + add1 (*f); + continue; + + default: + /* Copy this multibyte sequence until we reach its end, find + an error, or come back to the initial shift state. */ + { + mbstate_t mbstate = mbstate_zero; + size_t len = 0; + size_t fsize; + + if (! format_end) + format_end = f + strlen (f) + 1; + fsize = format_end - f; + + do + { + size_t bytes = mbrlen (f + len, fsize - len, &mbstate); + + if (bytes == 0) + break; + + if (bytes == (size_t) -2) + { + len += strlen (f + len); + break; + } + + if (bytes == (size_t) -1) + { + len++; + break; + } + + len += bytes; + } + while (! mbsinit (&mbstate)); + + cpy (len, f); + f += len - 1; + continue; + } + } + +#else /* ! DO_MULTIBYTE */ + + /* Either multibyte encodings are not supported, they are + safe for formats, so any non-'%' byte can be copied through, + or this is the wide character version. */ + if (*f != L_('%')) + { + add1 (*f); + continue; + } + +#endif /* ! DO_MULTIBYTE */ + + char const *percent = f; + + /* Check for flags that can modify a format. */ + while (1) + { + switch (*++f) + { + /* This influences the number formats. */ + case L_('_'): + case L_('-'): + case L_('+'): + case L_('0'): + pad = *f; + continue; + + /* This changes textual output. */ + case L_('^'): + to_uppcase = true; + continue; + case L_('#'): + change_case = true; + continue; + + default: + break; + } + break; + } + + if (ISDIGIT (*f)) + { + width = 0; + do + { + if (INT_MULTIPLY_WRAPV (width, 10, &width) + || INT_ADD_WRAPV (width, *f - L_('0'), &width)) + width = INT_MAX; + ++f; + } + while (ISDIGIT (*f)); + } + + /* Check for modifiers. */ + switch (*f) + { + case L_('E'): + case L_('O'): + modifier = *f++; + break; + + default: + modifier = 0; + break; + } + + /* Now do the specified format. */ + format_char = *f; + switch (format_char) + { +#define DO_NUMBER(d, v) \ + do \ + { \ + digits = d; \ + number_value = v; \ + goto do_number; \ + } \ + while (0) +#define DO_SIGNED_NUMBER(d, negative, v) \ + DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number) +#define DO_YEARISH(d, negative, v) \ + DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish) +#define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \ + do \ + { \ + digits = d; \ + negative_number = negative; \ + u_number_value = v; \ + goto label; \ + } \ + while (0) + + /* The mask is not what you might think. + When the ordinal i'th bit is set, insert a colon + before the i'th digit of the time zone representation. */ +#define DO_TZ_OFFSET(d, mask, v) \ + do \ + { \ + digits = d; \ + tz_colon_mask = mask; \ + u_number_value = v; \ + goto do_tz_offset; \ + } \ + while (0) +#define DO_NUMBER_SPACEPAD(d, v) \ + do \ + { \ + digits = d; \ + number_value = v; \ + goto do_number_spacepad; \ + } \ + while (0) + + case L_('%'): + if (f - 1 != percent) + goto bad_percent; + add1 (*f); + break; + + case L_('a'): + if (modifier != 0) + goto bad_format; + if (change_case) + { + to_uppcase = true; + to_lowcase = false; + } +#ifdef _NL_CURRENT + cpy (aw_len, a_wkday); + break; +#else + goto underlying_strftime; +#endif + + case 'A': + if (modifier != 0) + goto bad_format; + if (change_case) + { + to_uppcase = true; + to_lowcase = false; + } +#ifdef _NL_CURRENT + cpy (STRLEN (f_wkday), f_wkday); + break; +#else + goto underlying_strftime; +#endif + + case L_('b'): + case L_('h'): + if (change_case) + { + to_uppcase = true; + to_lowcase = false; + } + if (modifier == L_('E')) + goto bad_format; +#ifdef _NL_CURRENT + if (modifier == L_('O')) + cpy (aam_len, a_altmonth); + else + cpy (am_len, a_month); + break; +#else + goto underlying_strftime; +#endif + + case L_('B'): + if (modifier == L_('E')) + goto bad_format; + if (change_case) + { + to_uppcase = true; + to_lowcase = false; + } +#ifdef _NL_CURRENT + if (modifier == L_('O')) + cpy (STRLEN (f_altmonth), f_altmonth); + else + cpy (STRLEN (f_month), f_month); + break; +#else + goto underlying_strftime; +#endif + + case L_('c'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == L_('E') + && (*(subfmt = + (const CHAR_T *) _NL_CURRENT (LC_TIME, + NLW(ERA_D_T_FMT))) + != '\0'))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT)); +#else + goto underlying_strftime; +#endif + + subformat: + subwidth = -1; + subformat_width: + { + size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1) + subfmt, tp, to_uppcase, + pad, subwidth, tzset_called + extra_args LOCALE_ARG); + add (len, __strftime_internal (p, + STRFTIME_ARG (maxsize - i) + subfmt, tp, to_uppcase, + pad, subwidth, tzset_called + extra_args LOCALE_ARG)); + } + break; + +#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) + underlying_strftime: + { + /* The relevant information is available only via the + underlying strftime implementation, so use that. */ + char ufmt[5]; + char *u = ufmt; + char ubuf[1024]; /* enough for any single format in practice */ + size_t len; + /* Make sure we're calling the actual underlying strftime. + In some cases, config.h contains something like + "#define strftime rpl_strftime". */ +# ifdef strftime +# undef strftime + size_t strftime (); +# endif + + /* The space helps distinguish strftime failure from empty + output. */ + *u++ = ' '; + *u++ = '%'; + if (modifier != 0) + *u++ = modifier; + *u++ = format_char; + *u = '\0'; + len = strftime (ubuf, sizeof ubuf, ufmt, tp); + if (len != 0) + cpy (len - 1, ubuf + 1); + } + break; +#endif + + case L_('C'): + if (modifier == L_('E')) + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +# ifdef COMPILE_WIDE + size_t len = __wcslen (era->era_wname); + cpy (len, era->era_wname); +# else + size_t len = strlen (era->era_name); + cpy (len, era->era_name); +# endif + break; + } +#else + goto underlying_strftime; +#endif + } + + { + bool negative_year = tp->tm_year < - TM_YEAR_BASE; + bool zero_thru_1899 = !negative_year & (tp->tm_year < 0); + int century = ((tp->tm_year - 99 * zero_thru_1899) / 100 + + TM_YEAR_BASE / 100); + DO_YEARISH (2, negative_year, century); + } + + case L_('x'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == L_('E') + && (*(subfmt = + (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT))) + != L_('\0')))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT)); + goto subformat; +#else + goto underlying_strftime; +#endif + case L_('D'): + if (modifier != 0) + goto bad_format; + subfmt = L_("%m/%d/%y"); + goto subformat; + + case L_('d'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_mday); + + case L_('e'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, tp->tm_mday); + + /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE) + and then jump to one of these labels. */ + + do_tz_offset: + always_output_a_sign = true; + goto do_number_body; + + do_yearish: + if (pad == 0) + pad = yr_spec; + always_output_a_sign + = (pad == L_('+') + && ((digits == 2 ? 99 : 9999) < u_number_value + || digits < width)); + goto do_maybe_signed_number; + + do_number_spacepad: + if (pad == 0) + pad = L_('_'); + + do_number: + /* Format NUMBER_VALUE according to the MODIFIER flag. */ + negative_number = number_value < 0; + u_number_value = number_value; + + do_signed_number: + always_output_a_sign = false; + + do_maybe_signed_number: + tz_colon_mask = 0; + + do_number_body: + /* Format U_NUMBER_VALUE according to the MODIFIER flag. + NEGATIVE_NUMBER is nonzero if the original number was + negative; in this case it was converted directly to + unsigned int (i.e., modulo (UINT_MAX + 1)) without + negating it. */ + if (modifier == L_('O') && !negative_number) + { +#ifdef _NL_CURRENT + /* Get the locale specific alternate representation of + the number. If none exist NULL is returned. */ + const CHAR_T *cp = nl_get_alt_digit (u_number_value + HELPER_LOCALE_ARG); + + if (cp != NULL) + { + size_t digitlen = STRLEN (cp); + if (digitlen != 0) + { + cpy (digitlen, cp); + break; + } + } +#else + goto underlying_strftime; +#endif + } + + bufp = buf + sizeof (buf) / sizeof (buf[0]); + + if (negative_number) + u_number_value = - u_number_value; + + do + { + if (tz_colon_mask & 1) + *--bufp = ':'; + tz_colon_mask >>= 1; + *--bufp = u_number_value % 10 + L_('0'); + u_number_value /= 10; + } + while (u_number_value != 0 || tz_colon_mask != 0); + + do_number_sign_and_padding: + if (pad == 0) + pad = L_('0'); + if (width < 0) + width = digits; + + { + CHAR_T sign_char = (negative_number ? L_('-') + : always_output_a_sign ? L_('+') + : 0); + int numlen = buf + sizeof buf / sizeof buf[0] - bufp; + int shortage = width - !!sign_char - numlen; + int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage; + + if (sign_char) + { + if (pad == L_('_')) + { + if (p) + memset_space (p, padding); + i += padding; + width -= padding; + } + width_add1 (0, sign_char); + width--; + } + + cpy (numlen, bufp); + } + break; + + case L_('F'): + if (modifier != 0) + goto bad_format; + if (pad == 0 && width < 0) + { + pad = L_('+'); + subwidth = 4; + } + else + { + subwidth = width - 6; + if (subwidth < 0) + subwidth = 0; + } + subfmt = L_("%Y-%m-%d"); + goto subformat_width; + + case L_('H'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_hour); + + case L_('I'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, hour12); + + case L_('k'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, tp->tm_hour); + + case L_('l'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER_SPACEPAD (2, hour12); + + case L_('j'): + if (modifier == L_('E')) + goto bad_format; + + DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U); + + case L_('M'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_min); + + case L_('m'): + if (modifier == L_('E')) + goto bad_format; + + DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U); + +#ifndef _LIBC + case L_('N'): /* GNU extension. */ + if (modifier == L_('E')) + goto bad_format; + { + int n = ns, ns_digits = 9; + if (width <= 0) + width = ns_digits; + int ndigs = ns_digits; + while (width < ndigs || (1 < ndigs && n % 10 == 0)) + ndigs--, n /= 10; + for (int j = ndigs; 0 < j; j--) + buf[j - 1] = n % 10 + L_('0'), n /= 10; + if (!pad) + pad = L_('0'); + width_cpy (0, ndigs, buf); + width_add (width - ndigs, 0, (void) 0); + } + break; +#endif + + case L_('n'): + add1 (L_('\n')); + break; + + case L_('P'): + to_lowcase = true; +#ifndef _NL_CURRENT + format_char = L_('p'); +#endif + FALLTHROUGH; + case L_('p'): + if (change_case) + { + to_uppcase = false; + to_lowcase = true; + } +#ifdef _NL_CURRENT + cpy (ap_len, ampm); + break; +#else + goto underlying_strftime; +#endif + + case L_('q'): /* GNU extension. */ + DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1); + + case L_('R'): + subfmt = L_("%H:%M"); + goto subformat; + + case L_('r'): +#ifdef _NL_CURRENT + if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, + NLW(T_FMT_AMPM))) + == L_('\0')) + subfmt = L_("%I:%M:%S %p"); + goto subformat; +#else + goto underlying_strftime; +#endif + + case L_('S'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, tp->tm_sec); + + case L_('s'): /* GNU extension. */ + { + struct tm ltm; + time_t t; + + ltm = *tp; + ltm.tm_yday = -1; + t = mktime_z (tz, <m); + if (ltm.tm_yday < 0) + { + errno = EOVERFLOW; + return 0; + } + + /* Generate string value for T using time_t arithmetic; + this works even if sizeof (long) < sizeof (time_t). */ + + bufp = buf + sizeof (buf) / sizeof (buf[0]); + negative_number = t < 0; + + do + { + int d = t % 10; + t /= 10; + *--bufp = (negative_number ? -d : d) + L_('0'); + } + while (t != 0); + + digits = 1; + always_output_a_sign = false; + goto do_number_sign_and_padding; + } + + case L_('X'): + if (modifier == L_('O')) + goto bad_format; +#ifdef _NL_CURRENT + if (! (modifier == L_('E') + && (*(subfmt = + (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT))) + != L_('\0')))) + subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT)); + goto subformat; +#else + goto underlying_strftime; +#endif + case L_('T'): + subfmt = L_("%H:%M:%S"); + goto subformat; + + case L_('t'): + add1 (L_('\t')); + break; + + case L_('u'): + DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1); + + case L_('U'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7); + + case L_('V'): + case L_('g'): + case L_('G'): + if (modifier == L_('E')) + goto bad_format; + { + /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE) + is a leap year, except that YEAR and YEAR - 1 both work + correctly even when (tp->tm_year + TM_YEAR_BASE) would + overflow. */ + int year = (tp->tm_year + + (tp->tm_year < 0 + ? TM_YEAR_BASE % 400 + : TM_YEAR_BASE % 400 - 400)); + int year_adjust = 0; + int days = iso_week_days (tp->tm_yday, tp->tm_wday); + + if (days < 0) + { + /* This ISO week belongs to the previous year. */ + year_adjust = -1; + days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)), + tp->tm_wday); + } + else + { + int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)), + tp->tm_wday); + if (0 <= d) + { + /* This ISO week belongs to the next year. */ + year_adjust = 1; + days = d; + } + } + + switch (*f) + { + case L_('g'): + { + int yy = (tp->tm_year % 100 + year_adjust) % 100; + DO_YEARISH (2, false, + (0 <= yy + ? yy + : tp->tm_year < -TM_YEAR_BASE - year_adjust + ? -yy + : yy + 100)); + } + + case L_('G'): + DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust, + (tp->tm_year + (unsigned int) TM_YEAR_BASE + + year_adjust)); + + default: + DO_NUMBER (2, days / 7 + 1); + } + } + + case L_('W'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7); + + case L_('w'): + if (modifier == L_('E')) + goto bad_format; + + DO_NUMBER (1, tp->tm_wday); + + case L_('Y'): + if (modifier == L_('E')) + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { +# ifdef COMPILE_WIDE + subfmt = era->era_wformat; +# else + subfmt = era->era_format; +# endif + if (pad == 0) + pad = yr_spec; + goto subformat; + } +#else + goto underlying_strftime; +#endif + } + if (modifier == L_('O')) + goto bad_format; + + DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE, + tp->tm_year + (unsigned int) TM_YEAR_BASE); + + case L_('y'): + if (modifier == L_('E')) + { +#if HAVE_STRUCT_ERA_ENTRY + struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); + if (era) + { + int delta = tp->tm_year - era->start_date[0]; + if (pad == 0) + pad = yr_spec; + DO_NUMBER (2, (era->offset + + delta * era->absolute_direction)); + } +#else + goto underlying_strftime; +#endif + } + + { + int yy = tp->tm_year % 100; + if (yy < 0) + yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100; + DO_YEARISH (2, false, yy); + } + + case L_('Z'): + if (change_case) + { + to_uppcase = false; + to_lowcase = true; + } + +#ifdef COMPILE_WIDE + { + /* The zone string is always given in multibyte form. We have + to transform it first. */ + wchar_t *wczone; + size_t len; + widen (zone, wczone, len); + cpy (len, wczone); + } +#else + cpy (strlen (zone), zone); +#endif + break; + + case L_(':'): + /* :, ::, and ::: are valid only just before 'z'. + :::: etc. are rejected later. */ + for (colons = 1; f[colons] == L_(':'); colons++) + continue; + if (f[colons] != L_('z')) + goto bad_format; + f += colons; + goto do_z_conversion; + + case L_('z'): + colons = 0; + + do_z_conversion: + if (tp->tm_isdst < 0) + break; + + { + int diff; + int hour_diff; + int min_diff; + int sec_diff; +#if HAVE_TM_GMTOFF + diff = tp->tm_gmtoff; +#else + if (!tz) + diff = 0; + else + { + struct tm gtm; + struct tm ltm; + time_t lt; + + /* POSIX.1 requires that local time zone information be used as + though strftime called tzset. */ +# ifndef my_strftime + if (!*tzset_called) + { + tzset (); + *tzset_called = true; + } +# endif + + ltm = *tp; + ltm.tm_wday = -1; + lt = mktime_z (tz, <m); + if (ltm.tm_wday < 0 || ! localtime_rz (0, <, >m)) + break; + diff = tm_diff (<m, >m); + } +#endif + + negative_number = diff < 0 || (diff == 0 && *zone == '-'); + hour_diff = diff / 60 / 60; + min_diff = diff / 60 % 60; + sec_diff = diff % 60; + + switch (colons) + { + case 0: /* +hhmm */ + DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff); + + case 1: tz_hh_mm: /* +hh:mm */ + DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff); + + case 2: tz_hh_mm_ss: /* +hh:mm:ss */ + DO_TZ_OFFSET (9, 024, + hour_diff * 10000 + min_diff * 100 + sec_diff); + + case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */ + if (sec_diff != 0) + goto tz_hh_mm_ss; + if (min_diff != 0) + goto tz_hh_mm; + DO_TZ_OFFSET (3, 0, hour_diff); + + default: + goto bad_format; + } + } + + case L_('\0'): /* GNU extension: % at end of format. */ + bad_percent: + --f; + FALLTHROUGH; + default: + /* Unknown format; output the format, including the '%', + since this is most likely the right thing to do if a + multibyte string has been misparsed. */ + bad_format: + cpy (f - percent + 1, percent); + break; + } + } + +#if ! FPRINTFTIME + if (p && maxsize != 0) + *p = L_('\0'); +#endif + + errno = saved_errno; + return i; +} diff --git a/cross/lib/open.c b/cross/lib/open.c new file mode 100644 index 00000000000..7ec8fdc35dc --- /dev/null +++ b/cross/lib/open.c @@ -0,0 +1,209 @@ +/* Open a descriptor to a file. + Copyright (C) 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Bruno Haible , 2007. */ + +/* If the user's config.h happens to include , let it include only + the system's here, so that orig_open doesn't recurse to + rpl_open. */ +#define __need_system_fcntl_h +#include + +/* Get the original definition of open. It might be defined as a macro. */ +#include +#include +#undef __need_system_fcntl_h + +static int +orig_open (const char *filename, int flags, mode_t mode) +{ +#if defined _WIN32 && !defined __CYGWIN__ + return _open (filename, flags, mode); +#else + return open (filename, flags, mode); +#endif +} + +/* Specification. */ +/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates + this include because of the preliminary #include above. */ +#include "fcntl.h" + +#include "cloexec.h" + +#include +#include +#include +#include +#include +#include + +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY 0 +#endif + +int +open (const char *filename, int flags, ...) +{ + /* 0 = unknown, 1 = yes, -1 = no. */ +#if GNULIB_defined_O_CLOEXEC + int have_cloexec = -1; +#else + static int have_cloexec; +#endif + + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +#if GNULIB_defined_O_NONBLOCK + /* The only known platform that lacks O_NONBLOCK is mingw, but it + also lacks named pipes and Unix sockets, which are the only two + file types that require non-blocking handling in open(). + Therefore, it is safe to ignore O_NONBLOCK here. It is handy + that mingw also lacks openat(), so that is also covered here. */ + flags &= ~O_NONBLOCK; +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ + if (strcmp (filename, "/dev/null") == 0) + filename = "NUL"; +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename + ends in a slash, as POSIX says such a filename must name a directory + : + "A pathname that contains at least one non- character and that + ends with one or more trailing characters shall not be resolved + successfully unless the last pathname component before the trailing + characters names an existing directory" + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + + says that it fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if ((flags & O_CREAT) + || (flags & O_ACCMODE) == O_RDWR + || (flags & O_ACCMODE) == O_WRONLY) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +#endif + + fd = orig_open (filename, + flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); + + if (flags & O_CLOEXEC) + { + if (! have_cloexec) + { + if (0 <= fd) + have_cloexec = 1; + else if (errno == EINVAL) + { + fd = orig_open (filename, flags & ~O_CLOEXEC, mode); + have_cloexec = -1; + } + } + if (have_cloexec < 0 && 0 <= fd) + set_cloexec_flag (fd, true); + } + + +#if REPLACE_FCHDIR + /* Implementing fchdir and fdopendir requires the ability to open a + directory file descriptor. If open doesn't support that (as on + mingw), we use a dummy file that behaves the same as directories + on Linux (ie. always reports EOF on attempts to read()), and + override fstat() in fchdir.c to hide the fact that we have a + dummy. */ + if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES + && ((flags & O_ACCMODE) == O_RDONLY + || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) + { + struct stat statbuf; + if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + { + /* Maximum recursion depth of 1. */ + fd = open ("/dev/null", flags, mode); + if (0 <= fd) + fd = _gl_register_fd (fd, filename); + } + else + errno = EACCES; + } +#endif + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX says such a filename must name a directory + : + "A pathname that contains at least one non- character and that + ends with one or more trailing characters shall not be resolved + successfully unless the last pathname component before the trailing + characters names an existing directory" + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +#endif + +#if REPLACE_FCHDIR + if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) + fd = _gl_register_fd (fd, filename); +#endif + + return fd; +} diff --git a/cross/lib/openat-die.c b/cross/lib/openat-die.c new file mode 100644 index 00000000000..8dab8b97429 --- /dev/null +++ b/cross/lib/openat-die.c @@ -0,0 +1,7 @@ +/* Respond to a save- or restore-cwd failure. + This should never happen with Emacs. */ +#include +#include "openat.h" +#include +void openat_save_fail (int errnum) { abort (); } +void openat_restore_fail (int errnum) { abort (); } diff --git a/cross/lib/openat-priv.h b/cross/lib/openat-priv.h new file mode 100644 index 00000000000..1d31c4e83cb --- /dev/null +++ b/cross/lib/openat-priv.h @@ -0,0 +1,64 @@ +/* Internals for openat-like functions. + + Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT_PRIV +#define _GL_HEADER_OPENAT_PRIV + +#include +#include +#include + +/* Maximum number of bytes that it is safe to allocate as a single + array on the stack, and that is known as a compile-time constant. + The assumption is that we'll touch the array very quickly, or a + temporary very near the array, provoking an out-of-memory trap. On + some operating systems, there is only one guard page for the stack, + and a page size can be as small as 4096 bytes. Subtract 64 in the + hope that this will let the compiler touch a nearby temporary and + provoke a trap. */ +#define SAFER_ALLOCA_MAX (4096 - 64) + +#define SAFER_ALLOCA(m) ((m) < SAFER_ALLOCA_MAX ? (m) : SAFER_ALLOCA_MAX) + +#if defined PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (PATH_MAX) +#elif defined _XOPEN_PATH_MAX +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (_XOPEN_PATH_MAX) +#else +# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (1024) +#endif + +char *openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file); + +/* Trying to access a BUILD_PROC_NAME file will fail on systems without + /proc support, and even on systems *with* ProcFS support. Return + nonzero if the failure may be legitimate, e.g., because /proc is not + readable, or the particular .../fd/N directory is not present. */ +#define EXPECTED_ERRNO(Errno) \ + ((Errno) == ENOTDIR || (Errno) == ENOENT \ + || (Errno) == EPERM || (Errno) == EACCES \ + || (Errno) == ENOSYS /* Solaris 8 */ \ + || (Errno) == EOPNOTSUPP /* FreeBSD */) + +/* Wrapper function shared among linkat and renameat. */ +int at_func2 (int fd1, char const *file1, + int fd2, char const *file2, + int (*func) (char const *file1, char const *file2)); + +#endif /* _GL_HEADER_OPENAT_PRIV */ diff --git a/cross/lib/openat-proc.c b/cross/lib/openat-proc.c new file mode 100644 index 00000000000..2a6a85f0696 --- /dev/null +++ b/cross/lib/openat-proc.c @@ -0,0 +1,135 @@ +/* Create /proc/self/fd-related names for subfiles of open directories. + + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +#include + +#include "openat-priv.h" + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __KLIBC__ +# include +#endif + +#include "intprops.h" + +/* Set BUF to the name of the subfile of the directory identified by + FD, where the subfile is named FILE. If successful, return BUF if + the result fits in BUF, dynamically allocated memory otherwise. + Return NULL (setting errno) on error. */ +char * +openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file) +{ + char *result = buf; + int dirlen; + + /* Make sure the caller gets ENOENT when appropriate. */ + if (!*file) + { + buf[0] = '\0'; + return buf; + } + +#ifndef __KLIBC__ +# define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/" + { + enum { + PROC_SELF_FD_DIR_SIZE_BOUND + = (sizeof PROC_SELF_FD_FORMAT - (sizeof "%d" - 1) + + INT_STRLEN_BOUND (int)) + }; + + static int proc_status = 0; + if (! proc_status) + { + /* Set PROC_STATUS to a positive value if /proc/self/fd is + reliable, and a negative value otherwise. Solaris 10 + /proc/self/fd mishandles "..", and any file name might expand + to ".." after symbolic link expansion, so avoid /proc/self/fd + if it mishandles "..". Solaris 10 has openat, but this + problem is exhibited on code that built on Solaris 8 and + running on Solaris 10. */ + + int proc_self_fd = + open ("/proc/self/fd", + O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC); + if (proc_self_fd < 0) + proc_status = -1; + else + { + /* Detect whether /proc/self/fd/%i/../fd exists, where %i is the + number of a file descriptor open on /proc/self/fd. On Linux, + that name resolves to /proc/self/fd, which was opened above. + However, on Solaris, it may resolve to /proc/self/fd/fd, which + cannot exist, since all names in /proc/self/fd are numeric. */ + char dotdot_buf[PROC_SELF_FD_DIR_SIZE_BOUND + sizeof "../fd" - 1]; + sprintf (dotdot_buf, PROC_SELF_FD_FORMAT "../fd", proc_self_fd); + proc_status = access (dotdot_buf, F_OK) ? -1 : 1; + close (proc_self_fd); + } + } + + if (proc_status < 0) + return NULL; + else + { + size_t bufsize = PROC_SELF_FD_DIR_SIZE_BOUND + strlen (file); + if (OPENAT_BUFFER_SIZE < bufsize) + { + result = malloc (bufsize); + if (! result) + return NULL; + } + + dirlen = sprintf (result, PROC_SELF_FD_FORMAT, fd); + } + } +#else + /* OS/2 kLIBC provides a function to retrieve a path from a fd. */ + { + char dir[_MAX_PATH]; + size_t bufsize; + + if (__libc_Back_ioFHToPath (fd, dir, sizeof dir)) + return NULL; + + dirlen = strlen (dir); + bufsize = dirlen + 1 + strlen (file) + 1; /* 1 for '/', 1 for null */ + if (OPENAT_BUFFER_SIZE < bufsize) + { + result = malloc (bufsize); + if (! result) + return NULL; + } + + strcpy (result, dir); + result[dirlen++] = '/'; + } +#endif + + strcpy (result + dirlen, file); + return result; +} diff --git a/cross/lib/openat.h b/cross/lib/openat.h new file mode 100644 index 00000000000..37d8eedbee4 --- /dev/null +++ b/cross/lib/openat.h @@ -0,0 +1,124 @@ +/* provide a replacement openat function + Copyright (C) 2004-2006, 2008-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Jim Meyering */ + +#ifndef _GL_HEADER_OPENAT +#define _GL_HEADER_OPENAT + +#include + +#include +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN + +#if !HAVE_OPENAT + +int openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno); +bool openat_needs_fchdir (void); + +#else + +# define openat_permissive(Fd, File, Flags, Mode, Cwd_errno) \ + openat (Fd, File, Flags, Mode) +# define openat_needs_fchdir() false + +#endif + +_Noreturn void openat_restore_fail (int); +_Noreturn void openat_save_fail (int); + +/* Using these function names makes application code + slightly more readable than it would be with + fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */ + +#if GNULIB_CHOWNAT + +# ifndef CHOWNAT_INLINE +# define CHOWNAT_INLINE _GL_INLINE +# endif + +CHOWNAT_INLINE int +chownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, 0); +} + +CHOWNAT_INLINE int +lchownat (int fd, char const *file, uid_t owner, gid_t group) +{ + return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_CHMODAT + +# ifndef CHMODAT_INLINE +# define CHMODAT_INLINE _GL_INLINE +# endif + +CHMODAT_INLINE int +chmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, 0); +} + +CHMODAT_INLINE int +lchmodat (int fd, char const *file, mode_t mode) +{ + return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); +} + +#endif + +#if GNULIB_STATAT + +# ifndef STATAT_INLINE +# define STATAT_INLINE _GL_INLINE +# endif + +_GL_ATTRIBUTE_DEPRECATED +STATAT_INLINE int +statat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, 0); +} + +_GL_ATTRIBUTE_DEPRECATED +STATAT_INLINE int +lstatat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); +} + +#endif + +/* For now, there are no wrappers named laccessat or leuidaccessat, + since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and + since access rights on symlinks are of limited utility. Likewise, + wrappers are not provided for accessat or euidaccessat, so as to + avoid dragging in -lgen on some platforms. */ + +_GL_INLINE_HEADER_END + +#endif /* _GL_HEADER_OPENAT */ diff --git a/cross/lib/pathmax.h b/cross/lib/pathmax.h new file mode 100644 index 00000000000..0dd8f3bc5ce --- /dev/null +++ b/cross/lib/pathmax.h @@ -0,0 +1,83 @@ +/* Define PATH_MAX somehow. Requires sys/types.h. + Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _PATHMAX_H +# define _PATHMAX_H + +/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, + including the terminating NUL byte. + + PATH_MAX is not defined on systems which have no limit on filename length, + such as GNU/Hurd. + + This file does *not* define PATH_MAX always. Programs that use this file + can handle the GNU/Hurd case in several ways: + - Either with a package-wide handling, or with a per-file handling, + - Either through a + #ifdef PATH_MAX + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX 8192 + #endif + or through a fallback like + #ifndef PATH_MAX + # define PATH_MAX pathconf ("/", _PC_PATH_MAX) + #endif + */ + +# include + +# include + +# ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 256 +# endif + +/* Don't include sys/param.h if it already has been. */ +# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN +# include +# endif + +# if !defined PATH_MAX && defined MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# endif + +# ifdef __hpux +/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, + *not* including the terminating NUL byte, and is set to 1023. + Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is + not defined at all any more. */ +# undef PATH_MAX +# define PATH_MAX 1024 +# endif + +# if defined _WIN32 && ! defined __CYGWIN__ +/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, + section "Maximum Path Length Limitation", + + explains that the maximum size of a filename, including the terminating + NUL byte, is 260 = 3 + 256 + 1. + This is the same value as + - FILENAME_MAX in , + - _MAX_PATH in , + - MAX_PATH in . + Undefine the original value, because mingw's gets it wrong. */ +# undef PATH_MAX +# define PATH_MAX 260 +# endif + +#endif /* _PATHMAX_H */ diff --git a/cross/lib/pipe2.c b/cross/lib/pipe2.c new file mode 100644 index 00000000000..8f06575a1dd --- /dev/null +++ b/cross/lib/pipe2.c @@ -0,0 +1,166 @@ +/* Create a pipe, with specific opening flags. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#include "binary-io.h" + +#if GNULIB_defined_O_NONBLOCK +# include "nonblocking.h" +#endif + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Native Windows API. */ + +# include + +#endif + +int +pipe2 (int fd[2], int flags) +{ + /* Mingw _pipe() corrupts fd on failure; also, if we succeed at + creating the pipe but later fail at changing fcntl, we want + to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */ + int tmp[2]; + tmp[0] = fd[0]; + tmp[1] = fd[1]; + +#if HAVE_PIPE2 +# undef pipe2 + /* Try the system call first, if it exists. (We may be running with a glibc + that has the function but with an older kernel that lacks it.) */ + { + /* Cache the information whether the system call really exists. */ + static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */ + if (have_pipe2_really >= 0) + { + int result = pipe2 (fd, flags); + if (!(result < 0 && errno == ENOSYS)) + { + have_pipe2_really = 1; + return result; + } + have_pipe2_really = -1; + } + } +#endif + + /* Check the supported flags. */ + if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0) + { + errno = EINVAL; + return -1; + } + +#if defined _WIN32 && ! defined __CYGWIN__ +/* Native Windows API. */ + + if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) + { + fd[0] = tmp[0]; + fd[1] = tmp[1]; + return -1; + } + + /* O_NONBLOCK handling. + On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the + functions defined by the gnulib module 'nonblocking'. */ +# if GNULIB_defined_O_NONBLOCK + if (flags & O_NONBLOCK) + { + if (set_nonblocking_flag (fd[0], true) != 0 + || set_nonblocking_flag (fd[1], true) != 0) + goto fail; + } +# else + { + static_assert (O_NONBLOCK == 0); + } +# endif + + return 0; + +#else +/* Unix API. */ + + if (pipe (fd) < 0) + return -1; + + /* POSIX + says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on + both fd[0] and fd[1]. */ + + /* O_NONBLOCK handling. + On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */ + if (flags & O_NONBLOCK) + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 + || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1 + || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 + || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1) + goto fail; + } + + if (flags & O_CLOEXEC) + { + int fcntl_flags; + + if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0 + || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1 + || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0 + || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) + goto fail; + } + +# if O_BINARY + if (flags & O_BINARY) + { + set_binary_mode (fd[1], O_BINARY); + set_binary_mode (fd[0], O_BINARY); + } + else if (flags & O_TEXT) + { + set_binary_mode (fd[1], O_TEXT); + set_binary_mode (fd[0], O_TEXT); + } +# endif + + return 0; + +#endif + +#if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__) + fail: + { + int saved_errno = errno; + close (fd[0]); + close (fd[1]); + fd[0] = tmp[0]; + fd[1] = tmp[1]; + errno = saved_errno; + return -1; + } +#endif +} diff --git a/cross/lib/pselect.c b/cross/lib/pselect.c new file mode 100644 index 00000000000..f5d21e1048a --- /dev/null +++ b/cross/lib/pselect.c @@ -0,0 +1,110 @@ +/* pselect - synchronous I/O multiplexing + + Copyright 2011-2023 Free Software Foundation, Inc. + + This file is part of gnulib. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Paul Eggert */ + +#include + +#include + +#include +#include + +/* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS + to see whether some of their descriptors are ready for reading, + ready for writing, or have exceptions pending. Wait for at most + TIMEOUT seconds, and use signal mask SIGMASK while waiting. A null + pointer parameter stands for no descriptors, an infinite timeout, + or an unaffected signal mask. */ + +#if !HAVE_PSELECT + +int +pselect (int nfds, fd_set *restrict rfds, + fd_set *restrict wfds, fd_set *restrict xfds, + struct timespec const *restrict timeout, + sigset_t const *restrict sigmask) +{ + int select_result; + sigset_t origmask; + struct timeval tv, *tvp; + + if (timeout) + { + if (! (0 <= timeout->tv_nsec && timeout->tv_nsec < 1000000000)) + { + errno = EINVAL; + return -1; + } + + tv.tv_sec = timeout->tv_sec; + tv.tv_usec = (timeout->tv_nsec + 999) / 1000; + tvp = &tv; + } + else + tvp = NULL; + + /* Signal mask munging should be atomic, but this is the best we can + do in this emulation. */ + if (sigmask) + pthread_sigmask (SIG_SETMASK, sigmask, &origmask); + + select_result = select (nfds, rfds, wfds, xfds, tvp); + + if (sigmask) + { + int select_errno = errno; + pthread_sigmask (SIG_SETMASK, &origmask, NULL); + errno = select_errno; + } + + return select_result; +} + +#else /* HAVE_PSELECT */ +# include +# undef pselect + +int +rpl_pselect (int nfds, fd_set *restrict rfds, + fd_set *restrict wfds, fd_set *restrict xfds, + struct timespec const *restrict timeout, + sigset_t const *restrict sigmask) +{ + int i; + + /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */ + if (nfds < 0 || nfds > FD_SETSIZE) + { + errno = EINVAL; + return -1; + } + for (i = 0; i < nfds; i++) + { + if (((rfds && FD_ISSET (i, rfds)) + || (wfds && FD_ISSET (i, wfds)) + || (xfds && FD_ISSET (i, xfds))) + && dup2 (i, i) != i) + return -1; + } + + return pselect (nfds, rfds, wfds, xfds, timeout, sigmask); +} + +#endif diff --git a/cross/lib/pthread_sigmask.c b/cross/lib/pthread_sigmask.c new file mode 100644 index 00000000000..128107582a7 --- /dev/null +++ b/cross/lib/pthread_sigmask.c @@ -0,0 +1,92 @@ +/* POSIX compatible signal blocking for threads. + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include + +#if PTHREAD_SIGMASK_INEFFECTIVE +# include +#endif + +#if PTHREAD_SIGMASK_UNBLOCK_BUG +# include +#endif + +int +pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) +#undef pthread_sigmask +{ +#if HAVE_PTHREAD_SIGMASK + int ret; + +# if PTHREAD_SIGMASK_INEFFECTIVE + sigset_t omask, omask_copy; + sigset_t *old_mask_ptr = &omask; + sigemptyset (&omask); + /* Add a signal unlikely to be blocked, so that OMASK_COPY + is unlikely to match the actual mask. */ + sigaddset (&omask, SIGILL); + memcpy (&omask_copy, &omask, sizeof omask); +# else + sigset_t *old_mask_ptr = old_mask; +# endif + + ret = pthread_sigmask (how, new_mask, old_mask_ptr); + +# if PTHREAD_SIGMASK_INEFFECTIVE + if (ret == 0) + { + /* Detect whether pthread_sigmask is currently ineffective. + Don't cache the information: libpthread.so could be dynamically + loaded after the program started and after pthread_sigmask was + called for the first time. */ + if (memcmp (&omask_copy, &omask, sizeof omask) == 0 + && pthread_sigmask (1729, &omask_copy, NULL) == 0) + { + /* pthread_sigmask is currently ineffective. The program is not + linked to -lpthread. So use sigprocmask instead. */ + return (sigprocmask (how, new_mask, old_mask) < 0 ? errno : 0); + } + + if (old_mask) + memcpy (old_mask, &omask, sizeof omask); + } +# endif +# if PTHREAD_SIGMASK_FAILS_WITH_ERRNO + if (ret == -1) + return errno; +# endif +# if PTHREAD_SIGMASK_UNBLOCK_BUG + if (ret == 0 + && new_mask != NULL + && (how == SIG_UNBLOCK || how == SIG_SETMASK)) + { + /* Give the OS the opportunity to raise signals that were pending before + the pthread_sigmask call and have now been unblocked. */ + usleep (1); + } +# endif + return ret; +#else + int ret = sigprocmask (how, new_mask, old_mask); + return (ret < 0 ? errno : 0); +#endif +} diff --git a/cross/lib/qcopy-acl.c b/cross/lib/qcopy-acl.c new file mode 100644 index 00000000000..0f4159b7fd9 --- /dev/null +++ b/cross/lib/qcopy-acl.c @@ -0,0 +1,85 @@ +/* Copy access control list from one file to another. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include "acl-internal.h" + +#if USE_XATTR + +# include + +/* Returns 1 if NAME is the name of an extended attribute that is related + to permissions, i.e. ACLs. Returns 0 otherwise. */ + +static int +is_attr_permissions (const char *name, struct error_context *ctx) +{ + return attr_copy_action (name, ctx) == ATTR_ACTION_PERMISSIONS; +} + +#endif /* USE_XATTR */ + +/* Copy access control lists from one file to another. If SOURCE_DESC is + a valid file descriptor, use file descriptor operations, else use + filename based operations on SRC_NAME. Likewise for DEST_DESC and + DST_NAME. + If access control lists are not available, fchmod the target file to + MODE. Also sets the non-permission bits of the destination file + (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. + Return 0 if successful. + Return -2 and set errno for an error relating to the source file. + Return -1 and set errno for an error relating to the destination file. */ + +int +qcopy_acl (const char *src_name, int source_desc, const char *dst_name, + int dest_desc, mode_t mode) +{ + int ret; + +#ifdef USE_XATTR + /* in case no ACLs present and also to set higher mode bits + we chmod before setting ACLs as doing it after could overwrite them + (especially true for NFSv4, posix ACL has that ugly "mask" hack that + nobody understands) */ + ret = chmod_or_fchmod (dst_name, dest_desc, mode); + /* Rather than fiddling with acls one by one, we just copy the whole ACL xattrs + (Posix or NFSv4). Of course, that won't address ACLs conversion + (i.e. posix <-> nfs4) but we can't do it anyway, so for now, we don't care + Functions attr_copy_* return 0 in case we copied something OR nothing + to copy */ + if (ret == 0) + ret = source_desc <= 0 || dest_desc <= 0 + ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) + : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, + is_attr_permissions, NULL); +#else + /* no XATTR, so we proceed the old dusty way */ + struct permission_context ctx; + + ret = get_permissions (src_name, source_desc, mode, &ctx); + if (ret != 0) + return -2; + ret = set_permissions (&ctx, dst_name, dest_desc); + free_permission_context (&ctx); +#endif + return ret; +} diff --git a/cross/lib/rawmemchr.c b/cross/lib/rawmemchr.c new file mode 100644 index 00000000000..45c6cd35276 --- /dev/null +++ b/cross/lib/rawmemchr.c @@ -0,0 +1,123 @@ +/* Searching in a string. + Copyright (C) 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +/* A function definition is only needed if HAVE_RAWMEMCHR is not defined. */ +#if !HAVE_RAWMEMCHR + +# include +# include + + +/* Find the first occurrence of C in S. */ +void * +rawmemchr (const void *s, int c_in) +{ + /* Change this typedef to experiment with performance. */ + typedef uintptr_t longword; + /* If you change the "uintptr_t", you should change UINTPTR_WIDTH to match. + This verifies that the type does not have padding bits. */ + static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (longword)); + + const unsigned char *char_ptr; + unsigned char c = c_in; + + /* Handle the first few bytes by reading one byte at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + (uintptr_t) char_ptr % alignof (longword) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + longword const *longword_ptr = s = char_ptr; + + /* Compute auxiliary longword values: + repeated_one is a value which has a 1 in every byte. + repeated_c has c in every byte. */ + longword repeated_one = (longword) -1 / UCHAR_MAX; + longword repeated_c = repeated_one * c; + longword repeated_hibit = repeated_one * (UCHAR_MAX / 2 + 1); + + /* Instead of the traditional loop which tests each byte, we will + test a longword at a time. The tricky part is testing if any of + the bytes in the longword in question are equal to + c. We first use an xor with repeated_c. This reduces the task + to testing whether any of the bytes in longword1 is zero. + + (The following comments assume 8-bit bytes, as POSIX requires; + the code's use of UCHAR_MAX should work even if bytes have more + than 8 bits.) + + We compute tmp = + ((longword1 - repeated_one) & ~longword1) & (repeated_one * 0x80). + That is, we perform the following operations: + 1. Subtract repeated_one. + 2. & ~longword1. + 3. & a mask consisting of 0x80 in every byte. + Consider what happens in each byte: + - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, + and step 3 transforms it into 0x80. A carry can also be propagated + to more significant bytes. + - If a byte of longword1 is nonzero, let its lowest 1 bit be at + position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, + the byte ends in a single bit of value 0 and k bits of value 1. + After step 2, the result is just k bits of value 1: 2^k - 1. After + step 3, the result is 0. And no carry is produced. + So, if longword1 has only non-zero bytes, tmp is zero. + Whereas if longword1 has a zero byte, call j the position of the least + significant zero byte. Then the result has a zero at positions 0, ..., + j-1 and a 0x80 at position j. We cannot predict the result at the more + significant bytes (positions j+1..3), but it does not matter since we + already have a non-zero bit at position 8*j+7. + + The test whether any byte in longword1 is zero is equivalent + to testing whether tmp is nonzero. + + This test can read beyond the end of a string, depending on where + C_IN is encountered. However, this is considered safe since the + initialization phase ensured that the read will be aligned, + therefore, the read will not cross page boundaries and will not + cause a fault. */ + + while (1) + { + longword longword1 = *longword_ptr ^ repeated_c; + + if ((((longword1 - repeated_one) & ~longword1) & repeated_hibit) != 0) + break; + longword_ptr++; + } + + char_ptr = s = longword_ptr; + + /* At this point, we know that one of the sizeof (longword) bytes + starting at char_ptr is == c. If we knew endianness, we + could determine the first such byte without any further memory + accesses, just by looking at the tmp result from the last loop + iteration. However, the following simple and portable code does + not attempt this potential optimization. */ + + while (*char_ptr != c) + char_ptr++; + return (void *) char_ptr; +} + +#endif diff --git a/cross/lib/rawmemchr.valgrind b/cross/lib/rawmemchr.valgrind new file mode 100644 index 00000000000..f3e4cb0f655 --- /dev/null +++ b/cross/lib/rawmemchr.valgrind @@ -0,0 +1,28 @@ +# Suppress a valgrind message about use of uninitialized memory in rawmemchr(). + +# Copyright (C) 2008-2023 Free Software Foundation, Inc. +# +# This file 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 file is distributed in the hope that 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 program. If not, see . + +# This use is OK because it provides only a speedup. +{ + rawmemchr-value4 + Memcheck:Value4 + fun:rawmemchr +} +{ + rawmemchr-value8 + Memcheck:Value8 + fun:rawmemchr +} diff --git a/cross/lib/readlink.c b/cross/lib/readlink.c new file mode 100644 index 00000000000..14bbb7f10ca --- /dev/null +++ b/cross/lib/readlink.c @@ -0,0 +1,104 @@ +/* Read the contents of a symbolic link. + Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + +#if !HAVE_READLINK + +/* readlink() substitute for systems that don't have a readlink() function, + such as DJGPP 2.03 and mingw32. */ + +ssize_t +readlink (char const *file, _GL_UNUSED char *buf, + _GL_UNUSED size_t bufsize) +{ + struct stat statbuf; + + /* In general we should use lstat() here, not stat(). But on platforms + without symbolic links, lstat() - if it exists - would be equivalent to + stat(), therefore we can use stat(). This saves us a configure check. */ + if (stat (file, &statbuf) >= 0) + errno = EINVAL; + return -1; +} + +#else /* HAVE_READLINK */ + +# undef readlink + +/* readlink() wrapper that uses correct types, for systems like cygwin + 1.5.x where readlink returns int, and which rejects trailing slash, + for Solaris 9. */ + +ssize_t +rpl_readlink (char const *file, char *buf, size_t bufsize) +{ +# if READLINK_TRAILING_SLASH_BUG + size_t file_len = strlen (file); + if (file_len && file[file_len - 1] == '/') + { + /* Even if FILE without the slash is a symlink to a directory, + both lstat() and stat() must resolve the trailing slash to + the directory rather than the symlink. We can therefore + safely use stat() to distinguish between EINVAL and + ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */ + struct stat st; + if (stat (file, &st) == 0 || errno == EOVERFLOW) + errno = EINVAL; + return -1; + } +# endif /* READLINK_TRAILING_SLASH_BUG */ + + ssize_t r = readlink (file, buf, bufsize); + +# if READLINK_TRUNCATE_BUG + if (r < 0 && errno == ERANGE) + { + /* Try again with a bigger buffer. This is just for test cases; + real code invariably discards short reads. */ + char stackbuf[4032]; + r = readlink (file, stackbuf, sizeof stackbuf); + if (r < 0) + { + if (errno == ERANGE) + { + /* Clear the buffer, which is good enough for real code. + Thankfully, no test cases try short reads of enormous + symlinks and what would be the point anyway? */ + r = bufsize; + memset (buf, 0, r); + } + } + else + { + if (bufsize < r) + r = bufsize; + memcpy (buf, stackbuf, r); + } + } +# endif + + return r; +} + +#endif /* HAVE_READLINK */ diff --git a/cross/lib/readlinkat.c b/cross/lib/readlinkat.c new file mode 100644 index 00000000000..7738ba8bfd5 --- /dev/null +++ b/cross/lib/readlinkat.c @@ -0,0 +1,113 @@ +/* Read a symlink relative to an open directory. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Eric Blake */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include + +#if HAVE_READLINKAT + +# undef fstatat +# undef readlinkat + +ssize_t +rpl_readlinkat (int fd, char const *file, char *buf, size_t bufsize) +{ +# if READLINK_TRAILING_SLASH_BUG + size_t file_len = strlen (file); + if (file_len && file[file_len - 1] == '/') + { + /* Even if FILE without the slash is a symlink to a directory, + both lstat() and stat() must resolve the trailing slash to + the directory rather than the symlink. We can therefore + safely use fstatat(..., 0) to distinguish between EINVAL and + ENOTDIR/ENOENT, avoiding extra overhead of rpl_fstatat(). */ + struct stat st; + if (fstatat (fd, file, &st, 0) == 0 || errno == EOVERFLOW) + errno = EINVAL; + return -1; + } +# endif /* READLINK_TRAILING_SLASH_BUG */ + + ssize_t r = readlinkat (fd, file, buf, bufsize); + +# if READLINK_TRUNCATE_BUG + if (r < 0 && errno == ERANGE) + { + /* Try again with a bigger buffer. This is just for test cases; + real code invariably discards short reads. */ + char stackbuf[4032]; + r = readlinkat (fd, file, stackbuf, sizeof stackbuf); + if (r < 0) + { + if (errno == ERANGE) + { + /* Clear the buffer, which is good enough for real code. + Thankfully, no test cases try short reads of enormous + symlinks and what would be the point anyway? */ + r = bufsize; + memset (buf, 0, r); + } + } + else + { + if (bufsize < r) + r = bufsize; + memcpy (buf, stackbuf, r); + } + } +# endif + + return r; +} + +#else + +/* Gnulib provides a readlink stub for mingw; use it for distinction + between EINVAL and ENOENT, rather than always failing with ENOSYS. */ + +/* POSIX 2008 says that unlike readlink, readlinkat returns 0 for + success instead of the buffer length. But this would render + readlinkat worthless since readlink does not guarantee a + NUL-terminated buffer. Assume this was a bug in POSIX. */ + +/* Read the contents of symlink FILE into buffer BUF of size BUFSIZE, in the + directory open on descriptor FD. If possible, do it without changing + the working directory. Otherwise, resort to using save_cwd/fchdir, + then readlink/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ + +# define AT_FUNC_NAME readlinkat +# define AT_FUNC_F1 readlink +# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t bufsize +# define AT_FUNC_POST_FILE_ARGS , buf, bufsize +# define AT_FUNC_RESULT ssize_t +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS +# undef AT_FUNC_RESULT + +#endif diff --git a/cross/lib/realloc.c b/cross/lib/realloc.c new file mode 100644 index 00000000000..1063eb09874 --- /dev/null +++ b/cross/lib/realloc.c @@ -0,0 +1,63 @@ +/* realloc() function that is glibc compatible. + + Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* written by Jim Meyering and Bruno Haible */ + +#include + +#include + +#include + +#include "xalloc-oversized.h" + +/* Call the system's realloc below. This file does not define + _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present. */ +#undef realloc + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. If P is NULL, use malloc. Otherwise if N is zero, + free P and return NULL. */ + +void * +rpl_realloc (void *p, size_t n) +{ + if (p == NULL) + return malloc (n); + + if (n == 0) + { + free (p); + return NULL; + } + + if (xalloc_oversized (n, 1)) + { + errno = ENOMEM; + return NULL; + } + + void *result = realloc (p, n); + +#if !HAVE_MALLOC_POSIX + if (result == NULL) + errno = ENOMEM; +#endif + + return result; +} diff --git a/cross/lib/regcomp.c b/cross/lib/regcomp.c new file mode 100644 index 00000000000..89478396855 --- /dev/null +++ b/cross/lib/regcomp.c @@ -0,0 +1,3788 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifdef _LIBC +# include +#endif + +static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, + size_t length, reg_syntax_t syntax); +static void re_compile_fastmap_iter (regex_t *bufp, + const re_dfastate_t *init_state, + char *fastmap); +static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); +static void free_charset (re_charset_t *cset); +static void free_workarea_compile (regex_t *preg); +static reg_errcode_t create_initial_state (re_dfa_t *dfa); +static void optimize_utf8 (re_dfa_t *dfa); +static reg_errcode_t analyze (regex_t *preg); +static reg_errcode_t preorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t postorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); +static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); +static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, + bin_tree_t *node); +static reg_errcode_t calc_first (void *extra, bin_tree_t *node); +static reg_errcode_t calc_next (void *extra, bin_tree_t *node); +static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); +static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); +static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, + unsigned int constraint); +static reg_errcode_t calc_eclosure (re_dfa_t *dfa); +static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, + Idx node, bool root); +static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); +static Idx fetch_number (re_string_t *input, re_token_t *token, + reg_syntax_t syntax); +static int peek_token (re_token_t *token, re_string_t *input, + reg_syntax_t syntax); +static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + Idx nest, reg_errcode_t *err); +static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, + re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, + reg_errcode_t *err); +static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token, int token_len, + re_dfa_t *dfa, + reg_syntax_t syntax, + bool accept_hyphen); +static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token); +static reg_errcode_t build_equiv_class (bitset_t sbcset, + re_charset_t *mbcset, + Idx *equiv_class_alloc, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + re_charset_t *mbcset, + Idx *char_class_alloc, + const char *class_name, + reg_syntax_t syntax); +static bin_tree_t *build_charclass_op (re_dfa_t *dfa, + RE_TRANSLATE_TYPE trans, + const char *class_name, + const char *extra, + bool non_match, reg_errcode_t *err); +static bin_tree_t *create_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + re_token_type_t type); +static bin_tree_t *create_token_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + const re_token_t *token); +static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); +static void free_token (re_token_t *node); +static reg_errcode_t free_tree (void *extra, bin_tree_t *node); +static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +static const char __re_error_msgid[] = + { +#define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */ + "\0" +#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +static const size_t __re_error_msgid_idx[] = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length LENGTH) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields + are set in BUFP on entry. */ + +const char * +re_compile_pattern (const char *pattern, size_t length, + struct re_pattern_buffer *bufp) +{ + reg_errcode_t ret; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub, unless RE_NO_SUB is set. */ + bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = re_compile_internal (bufp, pattern, length, re_syntax_options); + + if (!ret) + return NULL; + return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} +weak_alias (__re_compile_pattern, re_compile_pattern) + +/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (reg_syntax_t syntax) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} +weak_alias (__re_set_syntax, re_set_syntax) + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ + re_dfa_t *dfa = bufp->buffer; + char *fastmap = bufp->fastmap; + + memset (fastmap, '\0', sizeof (char) * SBC_MAX); + re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); + if (dfa->init_state != dfa->init_state_word) + re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); + if (dfa->init_state != dfa->init_state_nl) + re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); + if (dfa->init_state != dfa->init_state_begbuf) + re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); + bufp->fastmap_accurate = 1; + return 0; +} +weak_alias (__re_compile_fastmap, re_compile_fastmap) + +static __always_inline void +re_set_fastmap (char *fastmap, bool icase, int ch) +{ + fastmap[ch] = 1; + if (icase) + fastmap[tolower (ch)] = 1; +} + +/* Helper function for re_compile_fastmap. + Compile fastmap for the initial_state INIT_STATE. */ + +static void +re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + char *fastmap) +{ + re_dfa_t *dfa = bufp->buffer; + Idx node_cnt; + bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); + for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) + { + Idx node = init_state->nodes.elems[node_cnt]; + re_token_type_t type = dfa->nodes[node].type; + + if (type == CHARACTER) + { + re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + unsigned char buf[MB_LEN_MAX]; + unsigned char *p; + wchar_t wc; + mbstate_t state; + + p = buf; + *p++ = dfa->nodes[node].opr.c; + while (++node < dfa->nodes_len + && dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].mb_partial) + *p++ = dfa->nodes[node].opr.c; + memset (&state, '\0', sizeof (state)); + if (__mbrtowc (&wc, (const char *) buf, p - buf, + &state) == p - buf + && (__wcrtomb ((char *) buf, __towlower (wc), &state) + != (size_t) -1)) + re_set_fastmap (fastmap, false, buf[0]); + } + } + else if (type == SIMPLE_BRACKET) + { + int i, ch; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + { + int j; + bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (w & ((bitset_word_t) 1 << j)) + re_set_fastmap (fastmap, icase, ch); + } + } + else if (type == COMPLEX_BRACKET) + { + re_charset_t *cset = dfa->nodes[node].opr.mbcset; + Idx i; + +#ifdef _LIBC + /* See if we have to try all bytes which start multiple collation + elements. + e.g. In da_DK, we want to catch 'a' since "aa" is a valid + collation element, and don't catch 'b' since 'b' is + the only collation element which starts from 'b' (and + it is caught by SIMPLE_BRACKET). */ + if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0 + && (cset->ncoll_syms || cset->nranges)) + { + const int32_t *table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + for (i = 0; i < SBC_MAX; ++i) + if (table[i] < 0) + re_set_fastmap (fastmap, icase, i); + } +#endif /* _LIBC */ + + /* See if we have to start the match at all multibyte characters, + i.e. where we would not find an invalid sequence. This only + applies to multibyte character sets; for single byte character + sets, the SIMPLE_BRACKET again suffices. */ + if (dfa->mb_cur_max > 1 + && (cset->nchar_classes || cset->non_match || cset->nranges +#ifdef _LIBC + || cset->nequiv_classes +#endif /* _LIBC */ + )) + { + unsigned char c = 0; + do + { + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) + re_set_fastmap (fastmap, false, (int) c); + } + while (++c != 0); + } + + else + { + /* ... Else catch all bytes which can start the mbchars. */ + for (i = 0; i < cset->nmbchars; ++i) + { + char buf[256]; + mbstate_t state; + memset (&state, '\0', sizeof (state)); + if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) + re_set_fastmap (fastmap, icase, *(unsigned char *) buf); + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) + != (size_t) -1) + re_set_fastmap (fastmap, false, *(unsigned char *) buf); + } + } + } + } + else if (type == OP_PERIOD || type == OP_UTF8_PERIOD || type == END_OF_RE) + { + memset (fastmap, '\1', sizeof (char) * SBC_MAX); + if (type == END_OF_RE) + bufp->can_be_null = 1; + return; + } + } +} + +/* Entry point for POSIX code. */ +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + 'buffer' to the compiled pattern; + 'used' to the length of the compiled pattern; + 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + 'newline_anchor' to REG_NEWLINE being set in CFLAGS; + 'fastmap' to an allocated space for the fastmap; + 'fastmap_accurate' to zero; + 're_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags) +{ + reg_errcode_t ret; + reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED + : RE_SYNTAX_POSIX_BASIC); + + preg->buffer = NULL; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = re_malloc (char, SBC_MAX); + if (__glibc_unlikely (preg->fastmap == NULL)) + return REG_ESPACE; + + syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + preg->no_sub = !!(cflags & REG_NOSUB); + preg->translate = NULL; + + ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) + ret = REG_EPAREN; + + /* We have already checked preg->fastmap != NULL. */ + if (__glibc_likely (ret == REG_NOERROR)) + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. This function never fails in this implementation. */ + (void) re_compile_fastmap (preg); + else + { + /* Some error occurred while compiling the expression. */ + re_free (preg->fastmap); + preg->fastmap = NULL; + } + + return (int) ret; +} +libc_hidden_def (__regcomp) +weak_alias (__regcomp, regcomp) + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, + size_t errbuf_size) +{ + const char *msg; + size_t msg_size; + int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0]; + + if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes)) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (__glibc_likely (errbuf_size != 0)) + { + size_t cpy_size = msg_size; + if (__glibc_unlikely (msg_size > errbuf_size)) + { + cpy_size = errbuf_size - 1; + errbuf[cpy_size] = '\0'; + } + memcpy (errbuf, msg, cpy_size); + } + + return msg_size; +} +weak_alias (__regerror, regerror) + + +/* This static array is used for the map to single-byte characters when + UTF-8 is used. Otherwise we would allocate memory just to initialize + it the same all the time. UTF-8 is the preferred encoding so this is + a worthwhile optimization. */ +static const bitset_t utf8_sb_map = +{ + /* Set the first 128 bits. */ +#if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +#else +# if 4 * BITSET_WORD_BITS < ASCII_CHARS +# error "bitset_word_t is narrower than 32 bits" +# elif 3 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, +# elif 2 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, BITSET_WORD_MAX, +# elif 1 * BITSET_WORD_BITS < ASCII_CHARS + BITSET_WORD_MAX, +# endif + (BITSET_WORD_MAX + >> (SBC_MAX % BITSET_WORD_BITS == 0 + ? 0 + : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) +#endif +}; + + +static void +free_dfa_content (re_dfa_t *dfa) +{ + Idx i, j; + + if (dfa->nodes) + for (i = 0; i < dfa->nodes_len; ++i) + free_token (dfa->nodes + i); + re_free (dfa->nexts); + for (i = 0; i < dfa->nodes_len; ++i) + { + if (dfa->eclosures != NULL) + re_node_set_free (dfa->eclosures + i); + if (dfa->inveclosures != NULL) + re_node_set_free (dfa->inveclosures + i); + if (dfa->edests != NULL) + re_node_set_free (dfa->edests + i); + } + re_free (dfa->edests); + re_free (dfa->eclosures); + re_free (dfa->inveclosures); + re_free (dfa->nodes); + + if (dfa->state_table) + for (i = 0; i <= dfa->state_hash_mask; ++i) + { + struct re_state_table_entry *entry = dfa->state_table + i; + for (j = 0; j < entry->num; ++j) + { + re_dfastate_t *state = entry->array[j]; + free_state (state); + } + re_free (entry->array); + } + re_free (dfa->state_table); + if (dfa->sb_char != utf8_sb_map) + re_free (dfa->sb_char); + re_free (dfa->subexp_map); +#ifdef DEBUG + re_free (dfa->re_str); +#endif + + re_free (dfa); +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + if (__glibc_likely (dfa != NULL)) + { + lock_fini (dfa->lock); + free_dfa_content (dfa); + } + preg->buffer = NULL; + preg->allocated = 0; + + re_free (preg->fastmap); + preg->fastmap = NULL; + + re_free (preg->translate); + preg->translate = NULL; +} +libc_hidden_def (__regfree) +weak_alias (__regfree, regfree) + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +# ifdef _LIBC +/* Make these definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec above without link errors. */ +weak_function +# endif +re_comp (const char *s) +{ + reg_errcode_t ret; + char *fastmap; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (re_comp_buf.buffer) + { + fastmap = re_comp_buf.fastmap; + re_comp_buf.fastmap = NULL; + __regfree (&re_comp_buf); + memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); + re_comp_buf.fastmap = fastmap; + } + + if (re_comp_buf.fastmap == NULL) + { + re_comp_buf.fastmap = re_malloc (char, SBC_MAX); + if (re_comp_buf.fastmap == NULL) + return (char *) gettext (__re_error_msgid + + __re_error_msgid_idx[(int) REG_ESPACE]); + } + + /* Since 're_exec' always passes NULL for the 'regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + + ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); + + if (!ret) + return NULL; + + /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */ + return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} + +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + __regfree (&re_comp_buf); +} +#endif + +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. + Compile the regular expression PATTERN, whose length is LENGTH. + SYNTAX indicate regular expression's syntax. */ + +static reg_errcode_t +re_compile_internal (regex_t *preg, const char * pattern, size_t length, + reg_syntax_t syntax) +{ + reg_errcode_t err = REG_NOERROR; + re_dfa_t *dfa; + re_string_t regexp; + + /* Initialize the pattern buffer. */ + preg->fastmap_accurate = 0; + preg->syntax = syntax; + preg->not_bol = preg->not_eol = 0; + preg->used = 0; + preg->re_nsub = 0; + preg->can_be_null = 0; + preg->regs_allocated = REGS_UNALLOCATED; + + /* Initialize the dfa. */ + dfa = preg->buffer; + if (__glibc_unlikely (preg->allocated < sizeof (re_dfa_t))) + { + /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. If ->buffer is NULL this + is a simple allocation. */ + dfa = re_realloc (preg->buffer, re_dfa_t, 1); + if (dfa == NULL) + return REG_ESPACE; + preg->allocated = sizeof (re_dfa_t); + preg->buffer = dfa; + } + preg->used = sizeof (re_dfa_t); + + err = init_dfa (dfa, length); + if (__glibc_unlikely (err == REG_NOERROR && lock_init (dfa->lock) != 0)) + err = REG_ESPACE; + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } +#ifdef DEBUG + /* Note: length+1 will not overflow since it is checked in init_dfa. */ + dfa->re_str = re_malloc (char, length + 1); + strncpy (dfa->re_str, pattern, length + 1); +#endif + + err = re_string_construct (®exp, pattern, length, preg->translate, + (syntax & RE_ICASE) != 0, dfa); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_compile_internal_free_return: + free_workarea_compile (preg); + re_string_destruct (®exp); + lock_fini (dfa->lock); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } + + /* Parse the regular expression, and build a structure tree. */ + preg->re_nsub = 0; + dfa->str_tree = parse (®exp, preg, syntax, &err); + if (__glibc_unlikely (dfa->str_tree == NULL)) + goto re_compile_internal_free_return; + + /* Analyze the tree and create the nfa. */ + err = analyze (preg); + if (__glibc_unlikely (err != REG_NOERROR)) + goto re_compile_internal_free_return; + + /* If possible, do searching in single byte encoding to speed things up. */ + if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) + optimize_utf8 (dfa); + + /* Then create the initial state of the dfa. */ + err = create_initial_state (dfa); + + /* Release work areas. */ + free_workarea_compile (preg); + re_string_destruct (®exp); + + if (__glibc_unlikely (err != REG_NOERROR)) + { + lock_fini (dfa->lock); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + } + + return err; +} + +/* Initialize DFA. We use the length of the regular expression PAT_LEN + as the initial length of some arrays. */ + +static reg_errcode_t +init_dfa (re_dfa_t *dfa, size_t pat_len) +{ + __re_size_t table_size; +#ifndef _LIBC + const char *codeset_name; +#endif + size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); + size_t max_object_size = + MAX (sizeof (struct re_state_table_entry), + MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + MAX (sizeof (regmatch_t), + max_i18n_object_size)))); + + memset (dfa, '\0', sizeof (re_dfa_t)); + + /* Force allocation of str_tree_storage the first time. */ + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + + /* Avoid overflows. The extra "/ 2" is for the table_size doubling + calculation below, and for similar doubling calculations + elsewhere. And it's <= rather than <, because some of the + doubling calculations add 1 afterwards. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 + <= pat_len)) + return REG_ESPACE; + + dfa->nodes_alloc = pat_len + 1; + dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); + + /* table_size = 2 ^ ceil(log pat_len) */ + for (table_size = 1; ; table_size <<= 1) + if (table_size > pat_len) + break; + + dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); + dfa->state_hash_mask = table_size - 1; + + dfa->mb_cur_max = MB_CUR_MAX; +#ifdef _LIBC + if (dfa->mb_cur_max == 6 + && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) + dfa->is_utf8 = 1; + dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) + != 0); +#else + codeset_name = nl_langinfo (CODESET); + if ((codeset_name[0] == 'U' || codeset_name[0] == 'u') + && (codeset_name[1] == 'T' || codeset_name[1] == 't') + && (codeset_name[2] == 'F' || codeset_name[2] == 'f') + && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0) + dfa->is_utf8 = 1; + + /* We check exhaustively in the loop below if this charset is a + superset of ASCII. */ + dfa->map_notascii = 0; +#endif + + if (dfa->mb_cur_max > 1) + { + if (dfa->is_utf8) + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; + else + { + int i, j, ch; + + dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + if (__glibc_unlikely (dfa->sb_char == NULL)) + return REG_ESPACE; + + /* Set the bits corresponding to single byte chars. */ + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + { + wint_t wch = __btowc (ch); + if (wch != WEOF) + dfa->sb_char[i] |= (bitset_word_t) 1 << j; +#ifndef _LIBC + if (isascii (ch) && wch != ch) + dfa->map_notascii = 1; +#endif + } + } + } + + if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL)) + return REG_ESPACE; + return REG_NOERROR; +} + +/* Initialize WORD_CHAR table, which indicate which character is + "word". In this case "word" means that it is the word construction + character used by some operators like "\<", "\>", etc. */ + +static void +init_word_char (re_dfa_t *dfa) +{ + int i = 0; + int j; + int ch = 0; + dfa->word_ops_used = 1; + if (__glibc_likely (dfa->map_notascii == 0)) + { + bitset_word_t bits0 = 0x00000000; + bitset_word_t bits1 = 0x03ff0000; + bitset_word_t bits2 = 0x87fffffe; + bitset_word_t bits3 = 0x07fffffe; + if (BITSET_WORD_BITS == 64) + { + /* Pacify gcc -Woverflow on 32-bit platformns. */ + dfa->word_char[0] = bits1 << 31 << 1 | bits0; + dfa->word_char[1] = bits3 << 31 << 1 | bits2; + i = 2; + } + else if (BITSET_WORD_BITS == 32) + { + dfa->word_char[0] = bits0; + dfa->word_char[1] = bits1; + dfa->word_char[2] = bits2; + dfa->word_char[3] = bits3; + i = 4; + } + else + goto general_case; + ch = 128; + + if (__glibc_likely (dfa->is_utf8)) + { + memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8); + return; + } + } + + general_case: + for (; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (isalnum (ch) || ch == '_') + dfa->word_char[i] |= (bitset_word_t) 1 << j; +} + +/* Free the work area which are only used while compiling. */ + +static void +free_workarea_compile (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_storage_t *storage, *next; + for (storage = dfa->str_tree_storage; storage; storage = next) + { + next = storage->next; + re_free (storage); + } + dfa->str_tree_storage = NULL; + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + dfa->str_tree = NULL; + re_free (dfa->org_indices); + dfa->org_indices = NULL; +} + +/* Create initial states for all contexts. */ + +static reg_errcode_t +create_initial_state (re_dfa_t *dfa) +{ + Idx first, i; + reg_errcode_t err; + re_node_set init_nodes; + + /* Initial states have the epsilon closure of the node which is + the first node of the regular expression. */ + first = dfa->str_tree->first->node_idx; + dfa->init_node = first; + err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* The back-references which are in initial states can epsilon transit, + since in this case all of the subexpressions can be null. + Then we add epsilon closures of the nodes which are the next nodes of + the back-references. */ + if (dfa->nbackref > 0) + for (i = 0; i < init_nodes.nelem; ++i) + { + Idx node_idx = init_nodes.elems[i]; + re_token_type_t type = dfa->nodes[node_idx].type; + + Idx clexp_idx; + if (type != OP_BACK_REF) + continue; + for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) + { + re_token_t *clexp_node; + clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; + if (clexp_node->type == OP_CLOSE_SUBEXP + && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) + break; + } + if (clexp_idx == init_nodes.nelem) + continue; + + if (type == OP_BACK_REF) + { + Idx dest_idx = dfa->edests[node_idx].elems[0]; + if (!re_node_set_contains (&init_nodes, dest_idx)) + { + reg_errcode_t merge_err + = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); + if (merge_err != REG_NOERROR) + return merge_err; + i = 0; + } + } + } + + /* It must be the first time to invoke acquire_state. */ + dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); + /* We don't check ERR here, since the initial state must not be NULL. */ + if (__glibc_unlikely (dfa->init_state == NULL)) + return err; + if (dfa->init_state->has_constraint) + { + dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_WORD); + dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_NEWLINE); + dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, + &init_nodes, + CONTEXT_NEWLINE + | CONTEXT_BEGBUF); + if (__glibc_unlikely (dfa->init_state_word == NULL + || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL)) + return err; + } + else + dfa->init_state_word = dfa->init_state_nl + = dfa->init_state_begbuf = dfa->init_state; + + re_node_set_free (&init_nodes); + return REG_NOERROR; +} + +/* If it is possible to do searching in single byte encoding instead of UTF-8 + to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change + DFA nodes where needed. */ + +static void +optimize_utf8 (re_dfa_t *dfa) +{ + Idx node; + int i; + bool mb_chars = false; + bool has_period = false; + + for (node = 0; node < dfa->nodes_len; ++node) + switch (dfa->nodes[node].type) + { + case CHARACTER: + if (dfa->nodes[node].opr.c >= ASCII_CHARS) + mb_chars = true; + break; + case ANCHOR: + switch (dfa->nodes[node].opr.ctx_type) + { + case LINE_FIRST: + case LINE_LAST: + case BUF_FIRST: + case BUF_LAST: + break; + default: + /* Word anchors etc. cannot be handled. It's okay to test + opr.ctx_type since constraints (for all DFA nodes) are + created by ORing one or more opr.ctx_type values. */ + return; + } + break; + case OP_PERIOD: + has_period = true; + break; + case OP_BACK_REF: + case OP_ALT: + case END_OF_RE: + case OP_DUP_ASTERISK: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + break; + case COMPLEX_BRACKET: + return; + case SIMPLE_BRACKET: + /* Just double check. */ + { + int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 + ? 0 + : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); + for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) + { + if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) + return; + rshift = 0; + } + } + break; + default: + abort (); + } + + if (mb_chars || has_period) + for (node = 0; node < dfa->nodes_len; ++node) + { + if (dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].opr.c >= ASCII_CHARS) + dfa->nodes[node].mb_partial = 0; + else if (dfa->nodes[node].type == OP_PERIOD) + dfa->nodes[node].type = OP_UTF8_PERIOD; + } + + /* The search can be in single byte locale. */ + dfa->mb_cur_max = 1; + dfa->is_utf8 = 0; + dfa->has_mb_node = dfa->nbackref > 0 || has_period; +} + +/* Analyze the structure tree, and calculate "first", "next", "edest", + "eclosure", and "inveclosure". */ + +static reg_errcode_t +analyze (regex_t *preg) +{ + re_dfa_t *dfa = preg->buffer; + reg_errcode_t ret; + + /* Allocate arrays. */ + dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); + dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); + dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); + dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); + if (__glibc_unlikely (dfa->nexts == NULL || dfa->org_indices == NULL + || dfa->edests == NULL || dfa->eclosures == NULL)) + return REG_ESPACE; + + dfa->subexp_map = re_malloc (Idx, preg->re_nsub); + if (dfa->subexp_map != NULL) + { + Idx i; + for (i = 0; i < preg->re_nsub; i++) + dfa->subexp_map[i] = i; + preorder (dfa->str_tree, optimize_subexps, dfa); + for (i = 0; i < preg->re_nsub; i++) + if (dfa->subexp_map[i] != i) + break; + if (i == preg->re_nsub) + { + re_free (dfa->subexp_map); + dfa->subexp_map = NULL; + } + } + + ret = postorder (dfa->str_tree, lower_subexps, preg); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + ret = postorder (dfa->str_tree, calc_first, dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + preorder (dfa->str_tree, calc_next, dfa); + ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + ret = calc_eclosure (dfa); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + /* We only need this during the prune_impossible_nodes pass in regexec.c; + skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ + if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) + || dfa->nbackref) + { + dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); + if (__glibc_unlikely (dfa->inveclosures == NULL)) + return REG_ESPACE; + ret = calc_inveclosure (dfa); + } + + return ret; +} + +/* Our parse trees are very unbalanced, so we cannot use a stack to + implement parse tree visits. Instead, we use parent pointers and + some hairy code in these two functions. */ +static reg_errcode_t +postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node, *prev; + + for (node = root; ; ) + { + /* Descend down the tree, preferably to the left (or to the right + if that's the only child). */ + while (node->left || node->right) + if (node->left) + node = node->left; + else + node = node->right; + + do + { + reg_errcode_t err = fn (extra, node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + if (node->parent == NULL) + return REG_NOERROR; + prev = node; + node = node->parent; + } + /* Go up while we have a node that is reached from the right. */ + while (node->right == prev || node->right == NULL); + node = node->right; + } +} + +static reg_errcode_t +preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node; + + for (node = root; ; ) + { + reg_errcode_t err = fn (extra, node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* Go to the left node, or up and to the right. */ + if (node->left) + node = node->left; + else + { + bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + if (!node) + return REG_NOERROR; + } + node = node->right; + } + } +} + +/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell + re_search_internal to map the inner one's opr.idx to this one's. Adjust + backreferences as well. Requires a preorder visit. */ +static reg_errcode_t +optimize_subexps (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + + if (node->token.type == OP_BACK_REF && dfa->subexp_map) + { + int idx = node->token.opr.idx; + node->token.opr.idx = dfa->subexp_map[idx]; + dfa->used_bkref_map |= 1 << node->token.opr.idx; + } + + else if (node->token.type == SUBEXP + && node->left && node->left->token.type == SUBEXP) + { + Idx other_idx = node->left->token.opr.idx; + + node->left = node->left->left; + if (node->left) + node->left->parent = node; + + dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; + if (other_idx < BITSET_WORD_BITS) + dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); + } + + return REG_NOERROR; +} + +/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation + of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ +static reg_errcode_t +lower_subexps (void *extra, bin_tree_t *node) +{ + regex_t *preg = (regex_t *) extra; + reg_errcode_t err = REG_NOERROR; + + if (node->left && node->left->token.type == SUBEXP) + { + node->left = lower_subexp (&err, preg, node->left); + if (node->left) + node->left->parent = node; + } + if (node->right && node->right->token.type == SUBEXP) + { + node->right = lower_subexp (&err, preg, node->right); + if (node->right) + node->right->parent = node; + } + + return err; +} + +static bin_tree_t * +lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *body = node->left; + bin_tree_t *op, *cls, *tree1, *tree; + + if (preg->no_sub + /* We do not optimize empty subexpressions, because otherwise we may + have bad CONCAT nodes with NULL children. This is obviously not + very common, so we do not lose much. An example that triggers + this case is the sed "script" /\(\)/x. */ + && node->left != NULL + && (node->token.opr.idx >= BITSET_WORD_BITS + || !(dfa->used_bkref_map + & ((bitset_word_t) 1 << node->token.opr.idx)))) + return node->left; + + /* Convert the SUBEXP node to the concatenation of an + OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ + op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); + cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); + tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; + tree = create_tree (dfa, op, tree1, CONCAT); + if (__glibc_unlikely (tree == NULL || tree1 == NULL + || op == NULL || cls == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + + op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; + op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; + return tree; +} + +/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton + nodes. Requires a postorder visit. */ +static reg_errcode_t +calc_first (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + if (node->token.type == CONCAT) + { + node->first = node->left->first; + node->node_idx = node->left->node_idx; + } + else + { + node->first = node; + node->node_idx = re_dfa_add_node (dfa, node->token); + if (__glibc_unlikely (node->node_idx == -1)) + return REG_ESPACE; + if (node->token.type == ANCHOR) + dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; + } + return REG_NOERROR; +} + +/* Pass 2: compute NEXT on the tree. Preorder visit. */ +static reg_errcode_t +calc_next (void *extra, bin_tree_t *node) +{ + switch (node->token.type) + { + case OP_DUP_ASTERISK: + node->left->next = node; + break; + case CONCAT: + node->left->next = node->right->first; + node->right->next = node->next; + break; + default: + if (node->left) + node->left->next = node->next; + if (node->right) + node->right->next = node->next; + break; + } + return REG_NOERROR; +} + +/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ +static reg_errcode_t +link_nfa_nodes (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + Idx idx = node->node_idx; + reg_errcode_t err = REG_NOERROR; + + switch (node->token.type) + { + case CONCAT: + break; + + case END_OF_RE: + DEBUG_ASSERT (node->next == NULL); + break; + + case OP_DUP_ASTERISK: + case OP_ALT: + { + Idx left, right; + dfa->has_plural_match = 1; + if (node->left != NULL) + left = node->left->first->node_idx; + else + left = node->next->node_idx; + if (node->right != NULL) + right = node->right->first->node_idx; + else + right = node->next->node_idx; + DEBUG_ASSERT (left > -1); + DEBUG_ASSERT (right > -1); + err = re_node_set_init_2 (dfa->edests + idx, left, right); + } + break; + + case ANCHOR: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); + break; + + case OP_BACK_REF: + dfa->nexts[idx] = node->next->node_idx; + if (node->token.type == OP_BACK_REF) + err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); + break; + + default: + DEBUG_ASSERT (!IS_EPSILON_NODE (node->token.type)); + dfa->nexts[idx] = node->next->node_idx; + break; + } + + return err; +} + +/* Duplicate the epsilon closure of the node ROOT_NODE. + Note that duplicated nodes have constraint INIT_CONSTRAINT in addition + to their own constraint. */ + +static reg_errcode_t +duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, + Idx root_node, unsigned int init_constraint) +{ + Idx org_node, clone_node; + bool ok; + unsigned int constraint = init_constraint; + for (org_node = top_org_node, clone_node = top_clone_node;;) + { + Idx org_dest, clone_dest; + if (dfa->nodes[org_node].type == OP_BACK_REF) + { + /* If the back reference epsilon-transit, its destination must + also have the constraint. Then duplicate the epsilon closure + of the destination of the back reference, and store it in + edests of the back reference. */ + org_dest = dfa->nexts[org_node]; + re_node_set_empty (dfa->edests + clone_node); + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + dfa->nexts[clone_node] = dfa->nexts[org_node]; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + else if (dfa->edests[org_node].nelem == 0) + { + /* In case of the node can't epsilon-transit, don't duplicate the + destination and store the original destination as the + destination of the node. */ + dfa->nexts[clone_node] = dfa->nexts[org_node]; + break; + } + else if (dfa->edests[org_node].nelem == 1) + { + /* In case of the node can epsilon-transit, and it has only one + destination. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* If the node is root_node itself, it means the epsilon closure + has a loop. Then tie it to the destination of the root_node. */ + if (org_node == root_node && clone_node != org_node) + { + ok = re_node_set_insert (dfa->edests + clone_node, org_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + break; + } + /* In case the node has another constraint, append it. */ + constraint |= dfa->nodes[org_node].constraint; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + else /* dfa->edests[org_node].nelem == 2 */ + { + /* In case of the node can epsilon-transit, and it has two + destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* Search for a duplicated node which satisfies the constraint. */ + clone_dest = search_duplicated_node (dfa, org_dest, constraint); + if (clone_dest == -1) + { + /* There is no such duplicated node, create a new one. */ + reg_errcode_t err; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + err = duplicate_node_closure (dfa, org_dest, clone_dest, + root_node, constraint); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + { + /* There is a duplicated node which satisfies the constraint, + use it to avoid infinite loop. */ + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + + org_dest = dfa->edests[org_node].elems[1]; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (__glibc_unlikely (clone_dest == -1)) + return REG_ESPACE; + ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + org_node = org_dest; + clone_node = clone_dest; + } + return REG_NOERROR; +} + +/* Search for a node which is duplicated from the node ORG_NODE, and + satisfies the constraint CONSTRAINT. */ + +static Idx +search_duplicated_node (const re_dfa_t *dfa, Idx org_node, + unsigned int constraint) +{ + Idx idx; + for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) + { + if (org_node == dfa->org_indices[idx] + && constraint == dfa->nodes[idx].constraint) + return idx; /* Found. */ + } + return -1; /* Not found. */ +} + +/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. + Return the index of the new node, or -1 if insufficient storage is + available. */ + +static Idx +duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) +{ + Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); + if (__glibc_likely (dup_idx != -1)) + { + dfa->nodes[dup_idx].constraint = constraint; + dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint; + dfa->nodes[dup_idx].duplicated = 1; + + /* Store the index of the original node. */ + dfa->org_indices[dup_idx] = org_idx; + } + return dup_idx; +} + +static reg_errcode_t +calc_inveclosure (re_dfa_t *dfa) +{ + Idx src, idx; + bool ok; + for (idx = 0; idx < dfa->nodes_len; ++idx) + re_node_set_init_empty (dfa->inveclosures + idx); + + for (src = 0; src < dfa->nodes_len; ++src) + { + Idx *elems = dfa->eclosures[src].elems; + for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) + { + ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + } + + return REG_NOERROR; +} + +/* Calculate "eclosure" for all the node in DFA. */ + +static reg_errcode_t +calc_eclosure (re_dfa_t *dfa) +{ + Idx node_idx; + bool incomplete; + DEBUG_ASSERT (dfa->nodes_len > 0); + incomplete = false; + /* For each nodes, calculate epsilon closure. */ + for (node_idx = 0; ; ++node_idx) + { + reg_errcode_t err; + re_node_set eclosure_elem; + if (node_idx == dfa->nodes_len) + { + if (!incomplete) + break; + incomplete = false; + node_idx = 0; + } + + DEBUG_ASSERT (dfa->eclosures[node_idx].nelem != -1); + + /* If we have already calculated, skip it. */ + if (dfa->eclosures[node_idx].nelem != 0) + continue; + /* Calculate epsilon closure of 'node_idx'. */ + err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (dfa->eclosures[node_idx].nelem == 0) + { + incomplete = true; + re_node_set_free (&eclosure_elem); + } + } + return REG_NOERROR; +} + +/* Calculate epsilon closure of NODE. */ + +static reg_errcode_t +calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) +{ + reg_errcode_t err; + Idx i; + re_node_set eclosure; + bool incomplete = false; + err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* An epsilon closure includes itself. */ + eclosure.elems[eclosure.nelem++] = node; + + /* This indicates that we are calculating this node now. + We reference this value to avoid infinite loop. */ + dfa->eclosures[node].nelem = -1; + + /* If the current node has constraints, duplicate all nodes + since they must inherit the constraints. */ + if (dfa->nodes[node].constraint + && dfa->edests[node].nelem + && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) + { + err = duplicate_node_closure (dfa, node, node, node, + dfa->nodes[node].constraint); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + /* Expand each epsilon destination nodes. */ + if (IS_EPSILON_NODE(dfa->nodes[node].type)) + for (i = 0; i < dfa->edests[node].nelem; ++i) + { + re_node_set eclosure_elem; + Idx edest = dfa->edests[node].elems[i]; + /* If calculating the epsilon closure of 'edest' is in progress, + return intermediate result. */ + if (dfa->eclosures[edest].nelem == -1) + { + incomplete = true; + continue; + } + /* If we haven't calculated the epsilon closure of 'edest' yet, + calculate now. Otherwise use calculated epsilon closure. */ + if (dfa->eclosures[edest].nelem == 0) + { + err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + eclosure_elem = dfa->eclosures[edest]; + /* Merge the epsilon closure of 'edest'. */ + err = re_node_set_merge (&eclosure, &eclosure_elem); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + /* If the epsilon closure of 'edest' is incomplete, + the epsilon closure of this node is also incomplete. */ + if (dfa->eclosures[edest].nelem == 0) + { + incomplete = true; + re_node_set_free (&eclosure_elem); + } + } + + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + return REG_NOERROR; +} + +/* Functions for token which are used in the parser. */ + +/* Fetch a token from INPUT. + We must not use this function inside bracket expressions. */ + +static void +fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) +{ + re_string_skip_bytes (input, peek_token (result, input, syntax)); +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function inside bracket expressions. */ + +static int +peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + + c = re_string_peek_byte (input, 0); + token->opr.c = c; + + token->word_char = 0; + token->mb_partial = 0; + if (input->mb_cur_max > 1 + && !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + token->mb_partial = 1; + return 1; + } + if (c == '\\') + { + unsigned char c2; + if (re_string_cur_idx (input) + 1 >= re_string_length (input)) + { + token->type = BACK_SLASH; + return 1; + } + + c2 = re_string_peek_byte_case (input, 1); + token->opr.c = c2; + token->type = CHARACTER; + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, + re_string_cur_idx (input) + 1); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else + token->word_char = IS_WORD_CHAR (c2) != 0; + + switch (c2) + { + case '|': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (!(syntax & RE_NO_BK_REFS)) + { + token->type = OP_BACK_REF; + token->opr.idx = c2 - '1'; + } + break; + case '<': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_FIRST; + } + break; + case '>': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_LAST; + } + break; + case 'b': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_DELIM; + } + break; + case 'B': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = NOT_WORD_DELIM; + } + break; + case 'w': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_WORD; + break; + case 'W': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTWORD; + break; + case 's': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_SPACE; + break; + case 'S': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTSPACE; + break; + case '`': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_FIRST; + } + break; + case '\'': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_LAST; + } + break; + case '(': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_CLOSE_SUBEXP; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_CLOSE_DUP_NUM; + break; + default: + break; + } + return 2; + } + + token->type = CHARACTER; + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else + token->word_char = IS_WORD_CHAR (token->opr.c); + + switch (c) + { + case '\n': + if (syntax & RE_NEWLINE_ALT) + token->type = OP_ALT; + break; + case '|': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '*': + token->type = OP_DUP_ASTERISK; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_CLOSE_DUP_NUM; + break; + case '(': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_CLOSE_SUBEXP; + break; + case '[': + token->type = OP_OPEN_BRACKET; + break; + case '.': + token->type = OP_PERIOD; + break; + case '^': + if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) + && re_string_cur_idx (input) != 0) + { + char prev = re_string_peek_byte (input, -1); + if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_FIRST; + break; + case '$': + if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) + && re_string_cur_idx (input) + 1 != re_string_length (input)) + { + re_token_t next; + re_string_skip_bytes (input, 1); + peek_token (&next, input, syntax); + re_string_skip_bytes (input, -1); + if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_LAST; + break; + default: + break; + } + return 1; +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function out of bracket expressions. */ + +static int +peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + c = re_string_peek_byte (input, 0); + token->opr.c = c; + + if (input->mb_cur_max > 1 + && !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + return 1; + } + + if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) + && re_string_cur_idx (input) + 1 < re_string_length (input)) + { + /* In this case, '\' escape a character. */ + unsigned char c2; + re_string_skip_bytes (input, 1); + c2 = re_string_peek_byte (input, 0); + token->opr.c = c2; + token->type = CHARACTER; + return 1; + } + if (c == '[') /* '[' is a special char in a bracket exps. */ + { + unsigned char c2; + int token_len; + if (re_string_cur_idx (input) + 1 < re_string_length (input)) + c2 = re_string_peek_byte (input, 1); + else + c2 = 0; + token->opr.c = c2; + token_len = 2; + switch (c2) + { + case '.': + token->type = OP_OPEN_COLL_ELEM; + break; + + case '=': + token->type = OP_OPEN_EQUIV_CLASS; + break; + + case ':': + if (syntax & RE_CHAR_CLASSES) + { + token->type = OP_OPEN_CHAR_CLASS; + break; + } + FALLTHROUGH; + default: + token->type = CHARACTER; + token->opr.c = c; + token_len = 1; + break; + } + return token_len; + } + switch (c) + { + case ']': + token->type = OP_CLOSE_BRACKET; + break; + case '^': + token->type = OP_NON_MATCH_LIST; + break; + case '-': + /* In V7 Unix grep and Unix awk and mawk, [...---...] + (3 adjacent minus signs) stands for a single minus sign. + Support that without breaking anything else. */ + if (! (re_string_cur_idx (input) + 2 < re_string_length (input) + && re_string_peek_byte (input, 1) == '-' + && re_string_peek_byte (input, 2) == '-')) + { + token->type = OP_CHARSET_RANGE; + break; + } + re_string_skip_bytes (input, 2); + FALLTHROUGH; + default: + token->type = CHARACTER; + } + return 1; +} + +/* Functions for parser. */ + +/* Entry point of the parser. + Parse the regular expression REGEXP and return the structure tree. + If an error occurs, ERR is set by error code, and return NULL. + This function build the following tree, from regular expression : + CAT + / \ + / \ + EOR + + CAT means concatenation. + EOR means end of regular expression. */ + +static bin_tree_t * +parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, + reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree, *eor, *root; + re_token_t current_token; + dfa->syntax = syntax; + fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); + tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + eor = create_tree (dfa, NULL, NULL, END_OF_RE); + if (tree != NULL) + root = create_tree (dfa, tree, eor, CONCAT); + else + root = eor; + if (__glibc_unlikely (eor == NULL || root == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + return root; +} + +/* This function build the following tree, from regular expression + |: + ALT + / \ + / \ + + + ALT means alternative, which represents the operator '|'. */ + +static bin_tree_t * +parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree, *branch = NULL; + bitset_word_t initial_bkref_map = dfa->completed_bkref_map; + tree = parse_branch (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + + while (token->type == OP_ALT) + { + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + if (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map; + dfa->completed_bkref_map = initial_bkref_map; + branch = parse_branch (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && branch == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + dfa->completed_bkref_map |= accumulated_bkref_map; + } + else + branch = NULL; + tree = create_tree (dfa, tree, branch, OP_ALT); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + return tree; +} + +/* This function build the following tree, from regular expression + : + CAT + / \ + / \ + + + CAT means concatenation. */ + +static bin_tree_t * +parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + bin_tree_t *tree, *expr; + re_dfa_t *dfa = preg->buffer; + tree = parse_expression (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + + while (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + expr = parse_expression (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err != REG_NOERROR && expr == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + if (tree != NULL && expr != NULL) + { + bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT); + if (newtree == NULL) + { + postorder (expr, free_tree, NULL); + postorder (tree, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } + tree = newtree; + } + else if (tree == NULL) + tree = expr; + /* Otherwise expr == NULL, we don't need to create new tree. */ + } + return tree; +} + +/* This function build the following tree, from regular expression a*: + * + | + a +*/ + +static bin_tree_t * +parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree; + switch (token->type) + { + case CHARACTER: + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + if (dfa->mb_cur_max > 1) + { + while (!re_string_eoi (regexp) + && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) + { + bin_tree_t *mbc_remain; + fetch_token (token, regexp, syntax); + mbc_remain = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree, mbc_remain, CONCAT); + if (__glibc_unlikely (mbc_remain == NULL || tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + } + break; + + case OP_OPEN_SUBEXP: + tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_OPEN_BRACKET: + tree = parse_bracket_exp (regexp, dfa, token, syntax, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_BACK_REF: + if (!__glibc_likely (dfa->completed_bkref_map & (1 << token->opr.idx))) + { + *err = REG_ESUBREG; + return NULL; + } + dfa->used_bkref_map |= 1 << token->opr.idx; + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + ++dfa->nbackref; + dfa->has_mb_node = 1; + break; + + case OP_OPEN_DUP_NUM: + if (syntax & RE_CONTEXT_INVALID_DUP) + { + *err = REG_BADRPT; + return NULL; + } + FALLTHROUGH; + case OP_DUP_ASTERISK: + case OP_DUP_PLUS: + case OP_DUP_QUESTION: + if (syntax & RE_CONTEXT_INVALID_OPS) + { + *err = REG_BADRPT; + return NULL; + } + else if (syntax & RE_CONTEXT_INDEP_OPS) + { + fetch_token (token, regexp, syntax); + return parse_expression (regexp, preg, token, syntax, nest, err); + } + FALLTHROUGH; + case OP_CLOSE_SUBEXP: + if ((token->type == OP_CLOSE_SUBEXP) + && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) + { + *err = REG_ERPAREN; + return NULL; + } + FALLTHROUGH; + case OP_CLOSE_DUP_NUM: + /* We treat it as a normal character. */ + + /* Then we can these characters as normal characters. */ + token->type = CHARACTER; + /* mb_partial and word_char bits should be initialized already + by peek_token. */ + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + break; + + case ANCHOR: + if ((token->opr.ctx_type + & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) + && dfa->word_ops_used == 0) + init_word_char (dfa); + if (token->opr.ctx_type == WORD_DELIM + || token->opr.ctx_type == NOT_WORD_DELIM) + { + bin_tree_t *tree_first, *tree_last; + if (token->opr.ctx_type == WORD_DELIM) + { + token->opr.ctx_type = WORD_FIRST; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = WORD_LAST; + } + else + { + token->opr.ctx_type = INSIDE_WORD; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = INSIDE_NOTWORD; + } + tree_last = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree_first, tree_last, OP_ALT); + if (__glibc_unlikely (tree_first == NULL || tree_last == NULL + || tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + else + { + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + } + /* We must return here, since ANCHORs can't be followed + by repetition operators. + eg. RE"^*" is invalid or "", + it must not be "". */ + fetch_token (token, regexp, syntax); + return tree; + + case OP_PERIOD: + tree = create_token_tree (dfa, NULL, NULL, token); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + if (dfa->mb_cur_max > 1) + dfa->has_mb_node = 1; + break; + + case OP_WORD: + case OP_NOTWORD: + tree = build_charclass_op (dfa, regexp->trans, + "alnum", + "_", + token->type == OP_NOTWORD, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_SPACE: + case OP_NOTSPACE: + tree = build_charclass_op (dfa, regexp->trans, + "space", + "", + token->type == OP_NOTSPACE, err); + if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) + return NULL; + break; + + case OP_ALT: + case END_OF_RE: + return NULL; + + case BACK_SLASH: + *err = REG_EESCAPE; + return NULL; + + default: + /* Must not happen? */ + DEBUG_ASSERT (false); + return NULL; + } + fetch_token (token, regexp, syntax); + + while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS + || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) + { + bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, + syntax, err); + if (__glibc_unlikely (*err != REG_NOERROR && dup_tree == NULL)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + return NULL; + } + tree = dup_tree; + /* In BRE consecutive duplications are not allowed. */ + if ((syntax & RE_CONTEXT_INVALID_DUP) + && (token->type == OP_DUP_ASTERISK + || token->type == OP_OPEN_DUP_NUM)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_BADRPT; + return NULL; + } + } + + return tree; +} + +/* This function build the following tree, from regular expression + (): + SUBEXP + | + +*/ + +static bin_tree_t * +parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, Idx nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = preg->buffer; + bin_tree_t *tree; + size_t cur_nsub; + cur_nsub = preg->re_nsub++; + + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + + /* The subexpression may be a null string. */ + if (token->type == OP_CLOSE_SUBEXP) + tree = NULL; + else + { + tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); + if (__glibc_unlikely (*err == REG_NOERROR + && token->type != OP_CLOSE_SUBEXP)) + { + if (tree != NULL) + postorder (tree, free_tree, NULL); + *err = REG_EPAREN; + } + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } + + if (cur_nsub <= '9' - '1') + dfa->completed_bkref_map |= 1 << cur_nsub; + + tree = create_tree (dfa, tree, NULL, SUBEXP); + if (__glibc_unlikely (tree == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + tree->token.opr.idx = cur_nsub; + return tree; +} + +/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ + +static bin_tree_t * +parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) +{ + bin_tree_t *tree = NULL, *old_tree = NULL; + Idx i, start, end, start_idx = re_string_cur_idx (regexp); + re_token_t start_token = *token; + + if (token->type == OP_OPEN_DUP_NUM) + { + end = 0; + start = fetch_number (regexp, token, syntax); + if (start == -1) + { + if (token->type == CHARACTER && token->opr.c == ',') + start = 0; /* We treat "{,m}" as "{0,m}". */ + else + { + *err = REG_BADBR; /* {} is invalid. */ + return NULL; + } + } + if (__glibc_likely (start != -2)) + { + /* We treat "{n}" as "{n,n}". */ + end = ((token->type == OP_CLOSE_DUP_NUM) ? start + : ((token->type == CHARACTER && token->opr.c == ',') + ? fetch_number (regexp, token, syntax) : -2)); + } + if (__glibc_unlikely (start == -2 || end == -2)) + { + /* Invalid sequence. */ + if (__glibc_unlikely (!(syntax & RE_INVALID_INTERVAL_ORD))) + { + if (token->type == END_OF_RE) + *err = REG_EBRACE; + else + *err = REG_BADBR; + + return NULL; + } + + /* If the syntax bit is set, rollback. */ + re_string_set_index (regexp, start_idx); + *token = start_token; + token->type = CHARACTER; + /* mb_partial and word_char bits should be already initialized by + peek_token. */ + return elem; + } + + if (__glibc_unlikely ((end != -1 && start > end) + || token->type != OP_CLOSE_DUP_NUM)) + { + /* First number greater than second. */ + *err = REG_BADBR; + return NULL; + } + + if (__glibc_unlikely (RE_DUP_MAX < (end == -1 ? start : end))) + { + *err = REG_ESIZE; + return NULL; + } + } + else + { + start = (token->type == OP_DUP_PLUS) ? 1 : 0; + end = (token->type == OP_DUP_QUESTION) ? 1 : -1; + } + + fetch_token (token, regexp, syntax); + + if (__glibc_unlikely (elem == NULL)) + return NULL; + if (__glibc_unlikely (start == 0 && end == 0)) + { + postorder (elem, free_tree, NULL); + return NULL; + } + + /* Extract "{n,m}" to "...{0,}". */ + if (__glibc_unlikely (start > 0)) + { + tree = elem; + for (i = 2; i <= start; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (__glibc_unlikely (elem == NULL || tree == NULL)) + goto parse_dup_op_espace; + } + + if (start == end) + return tree; + + /* Duplicate ELEM before it is marked optional. */ + elem = duplicate_tree (elem, dfa); + if (__glibc_unlikely (elem == NULL)) + goto parse_dup_op_espace; + old_tree = tree; + } + else + old_tree = NULL; + + if (elem->token.type == SUBEXP) + { + uintptr_t subidx = elem->token.opr.idx; + postorder (elem, mark_opt_subexp, (void *) subidx); + } + + tree = create_tree (dfa, elem, NULL, + (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); + if (__glibc_unlikely (tree == NULL)) + goto parse_dup_op_espace; + + /* This loop is actually executed only when end != -1, + to rewrite {0,n} as ((...?)?)?... We have + already created the start+1-th copy. */ + if (TYPE_SIGNED (Idx) || end != -1) + for (i = start + 2; i <= end; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (__glibc_unlikely (elem == NULL || tree == NULL)) + goto parse_dup_op_espace; + + tree = create_tree (dfa, tree, NULL, OP_ALT); + if (__glibc_unlikely (tree == NULL)) + goto parse_dup_op_espace; + } + + if (old_tree) + tree = create_tree (dfa, old_tree, tree, CONCAT); + + return tree; + + parse_dup_op_espace: + *err = REG_ESPACE; + return NULL; +} + +/* Size of the names for collating symbol/equivalence_class/character_class. + I'm not sure, but maybe enough. */ +#define BRACKET_NAME_BUF_SIZE 32 + +#ifndef _LIBC + +/* Convert the byte B to the corresponding wide character. In a + unibyte locale, treat B as itself. In a multibyte locale, return + WEOF if B is an encoding error. */ +static wint_t +parse_byte (unsigned char b, re_dfa_t const *dfa) +{ + return dfa->mb_cur_max > 1 ? __btowc (b) : b; +} + +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ + +static reg_errcode_t +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem, + re_dfa_t *dfa, reg_syntax_t syntax, uint_fast32_t nrules, + const unsigned char *collseqmb, const char *collseqwc, + int_fast32_t table_size, const void *symb_table, + const unsigned char *extra) +{ + /* Equivalence Classes and Character Classes can't be a range start/end. */ + if (__glibc_unlikely (start_elem->type == EQUIV_CLASS + || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS + || end_elem->type == CHAR_CLASS)) + return REG_ERANGE; + + /* We can handle no multi character collating elements without libc + support. */ + if (__glibc_unlikely ((start_elem->type == COLL_SYM + && strlen ((char *) start_elem->opr.name) > 1) + || (end_elem->type == COLL_SYM + && strlen ((char *) end_elem->opr.name) > 1))) + return REG_ECOLLATE; + + unsigned int + start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)), + end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + wint_t + start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) + ? parse_byte (start_ch, dfa) : start_elem->opr.wch), + end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) + ? parse_byte (end_ch, dfa) : end_elem->opr.wch); + + if (start_wc == WEOF || end_wc == WEOF) + return REG_ECOLLATE; + else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_wc > end_wc)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, for !_LIBC we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes + no MBCSET if dfa->mb_cur_max == 1. */ + if (dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) + { + /* There is not enough space, need realloc. */ + wchar_t *new_array_start, *new_array_end; + Idx new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + /* Use realloc since mbcset->range_starts and mbcset->range_ends + are NULL if *range_alloc == 0. */ + new_array_start = re_realloc (mbcset->range_starts, wchar_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, wchar_t, + new_nranges); + + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + { + re_free (new_array_start); + re_free (new_array_end); + return REG_ESPACE; + } + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_wc; + mbcset->range_ends[mbcset->nranges++] = end_wc; + } + + /* Build the table for single byte characters. */ + for (wchar_t wc = 0; wc < SBC_MAX; ++wc) + { + if (start_wc <= wc && wc <= end_wc) + bitset_set (sbcset, wc); + } + + return REG_NOERROR; +} +#endif /* not _LIBC */ + +#ifndef _LIBC +/* Helper function for parse_bracket_exp only used in case of NOT _LIBC. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static reg_errcode_t +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name, + uint_fast32_t nrules, int_fast32_t table_size, + const void *symb_table, const unsigned char *extra) +{ + size_t name_len = strlen ((const char *) name); + if (__glibc_unlikely (name_len != 1)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } +} +#endif /* not _LIBC */ + +#ifdef _LIBC +/* Local function for parse_bracket_exp used in _LIBC environment. + Seek the collating symbol entry corresponding to NAME. + Return the index of the symbol in the SYMB_TABLE, + or -1 if not found. */ + +static __always_inline int32_t +seek_collating_symbol_entry (const unsigned char *name, size_t name_len, + const int32_t *symb_table, + int_fast32_t table_size, + const unsigned char *extra) +{ + int_fast32_t elem; + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + int32_t idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + if (/* Compare the length of the name. */ + name_len == extra[idx] + /* Compare the name. */ + && memcmp (name, &extra[idx + 1], name_len) == 0) + /* Yep, this is the entry. */ + return elem; + } + return -1; +} + +/* Local function for parse_bracket_exp used in _LIBC environment. + Look up the collation sequence value of BR_ELEM. + Return the value if succeeded, UINT_MAX otherwise. */ + +static __always_inline unsigned int +lookup_collation_sequence_value (bracket_elem_t *br_elem, uint32_t nrules, + const unsigned char *collseqmb, + const char *collseqwc, + int_fast32_t table_size, + const int32_t *symb_table, + const unsigned char *extra) +{ + if (br_elem->type == SB_CHAR) + { + /* if (MB_CUR_MAX == 1) */ + if (nrules == 0) + return collseqmb[br_elem->opr.ch]; + else + { + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); + } + } + else if (br_elem->type == MB_CHAR) + { + if (nrules != 0) + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); + if (nrules != 0) + { + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len, + symb_table, table_size, + extra); + if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + /* Skip the byte sequence of the collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the multibyte collation sequence value. */ + idx += sizeof (unsigned int); + /* Skip the wide char sequence of the collating element. */ + idx += sizeof (unsigned int) * + (1 + *(unsigned int *) (extra + idx)); + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); + } + else if (sym_name_len == 1) + { + /* No valid character. Match it as a single byte + character. */ + return collseqmb[br_elem->opr.name[0]]; + } + } + else if (sym_name_len == 1) + return collseqmb[br_elem->opr.name[0]]; + } + return UINT_MAX; +} + +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ + +static __always_inline reg_errcode_t +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem, + re_dfa_t *dfa, reg_syntax_t syntax, uint32_t nrules, + const unsigned char *collseqmb, const char *collseqwc, + int_fast32_t table_size, const int32_t *symb_table, + const unsigned char *extra) +{ + unsigned int ch; + uint32_t start_collseq; + uint32_t end_collseq; + + /* Equivalence Classes and Character Classes can't be a range + start/end. */ + if (__glibc_unlikely (start_elem->type == EQUIV_CLASS + || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS + || end_elem->type == CHAR_CLASS)) + return REG_ERANGE; + + /* FIXME: Implement rational ranges here, too. */ + start_collseq = lookup_collation_sequence_value (start_elem, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); + end_collseq = lookup_collation_sequence_value (end_elem, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); + /* Check start/end collation sequence values. */ + if (__glibc_unlikely (start_collseq == UINT_MAX + || end_collseq == UINT_MAX)) + return REG_ECOLLATE; + if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_collseq > end_collseq)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ + if (nrules > 0 || dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) + { + /* There is not enough space, need realloc. */ + uint32_t *new_array_start; + uint32_t *new_array_end; + int new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + new_array_start = re_realloc (mbcset->range_starts, uint32_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, uint32_t, + new_nranges); + + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_collseq; + mbcset->range_ends[mbcset->nranges++] = end_collseq; + } + + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ch++) + { + uint32_t ch_collseq; + /* if (MB_CUR_MAX == 1) */ + if (nrules == 0) + ch_collseq = collseqmb[ch]; + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) + bitset_set (sbcset, ch); + } + return REG_NOERROR; +} + +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static __always_inline reg_errcode_t +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name, + uint_fast32_t nrules, int_fast32_t table_size, + const int32_t *symb_table, const unsigned char *extra) +{ + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) + { + elem = seek_collating_symbol_entry (name, name_len, symb_table, + table_size, extra); + if (elem != -1) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } + else if (name_len == 1) + { + /* No valid character, treat it as a normal + character. */ + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + else + return REG_ECOLLATE; + + /* Got valid collation sequence, add it as a new entry. */ + /* Check the space of the arrays. */ + if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->ncoll_syms is 0. */ + int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + /* Use realloc since mbcset->coll_syms is NULL + if *alloc == 0. */ + int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, + new_coll_sym_alloc); + if (__glibc_unlikely (new_coll_syms == NULL)) + return REG_ESPACE; + mbcset->coll_syms = new_coll_syms; + *coll_sym_alloc = new_coll_sym_alloc; + } + mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + return REG_NOERROR; + } + else + { + if (__glibc_unlikely (name_len != 1)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + } +} +#endif /* _LIBC */ + +/* This function parse bracket expression like "[abc]", "[a-c]", + "[[.a-a.]]" etc. */ + +static bin_tree_t * +parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) +{ + const unsigned char *collseqmb = NULL; + const char *collseqwc = NULL; + uint_fast32_t nrules = 0; + int_fast32_t table_size = 0; + const void *symb_table = NULL; + const unsigned char *extra = NULL; + + re_token_t br_token; + re_bitset_ptr_t sbcset; + re_charset_t *mbcset; + Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; + Idx equiv_class_alloc = 0, char_class_alloc = 0; + bool non_match = false; + bin_tree_t *work_tree; + int token_len; + bool first_round = true; +#ifdef _LIBC + collseqmb = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules) + { + /* + if (MB_CUR_MAX > 1) + */ + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + } +#endif + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); + if (__glibc_unlikely (sbcset == NULL || mbcset == NULL)) + { + re_free (sbcset); + re_free (mbcset); + *err = REG_ESPACE; + return NULL; + } + + token_len = peek_token_bracket (token, regexp, syntax); + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_NON_MATCH_LIST) + { + mbcset->non_match = 1; + non_match = true; + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set (sbcset, '\n'); + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + token_len = peek_token_bracket (token, regexp, syntax); + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + } + + /* We treat the first ']' as a normal character. */ + if (token->type == OP_CLOSE_BRACKET) + token->type = CHARACTER; + + while (1) + { + bracket_elem_t start_elem, end_elem; + unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; + unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; + reg_errcode_t ret; + int token_len2 = 0; + bool is_range_exp = false; + re_token_t token2; + + start_elem.opr.name = start_name_buf; + start_elem.type = COLL_SYM; + ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, + syntax, first_round); + if (__glibc_unlikely (ret != REG_NOERROR)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + first_round = false; + + /* Get information about the next token. We need it in any case. */ + token_len = peek_token_bracket (token, regexp, syntax); + + /* Do not check for ranges if we know they are not allowed. */ + if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) + { + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CHARSET_RANGE) + { + re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ + token_len2 = peek_token_bracket (&token2, regexp, syntax); + if (__glibc_unlikely (token2.type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token2.type == OP_CLOSE_BRACKET) + { + /* We treat the last '-' as a normal character. */ + re_string_skip_bytes (regexp, -token_len); + token->type = CHARACTER; + } + else + is_range_exp = true; + } + } + + if (is_range_exp == true) + { + end_elem.opr.name = end_name_buf; + end_elem.type = COLL_SYM; + ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, + dfa, syntax, true); + if (__glibc_unlikely (ret != REG_NOERROR)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + + token_len = peek_token_bracket (token, regexp, syntax); + + *err = build_range_exp (sbcset, mbcset, &range_alloc, + &start_elem, &end_elem, + dfa, syntax, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + } + else + { + switch (start_elem.type) + { + case SB_CHAR: + bitset_set (sbcset, start_elem.opr.ch); + break; + case MB_CHAR: + /* Check whether the array has enough space. */ + if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars)) + { + wchar_t *new_mbchars; + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nmbchars is 0. */ + mbchar_alloc = 2 * mbcset->nmbchars + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + new_mbchars = re_realloc (mbcset->mbchars, wchar_t, + mbchar_alloc); + if (__glibc_unlikely (new_mbchars == NULL)) + goto parse_bracket_exp_espace; + mbcset->mbchars = new_mbchars; + } + mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; + break; + case EQUIV_CLASS: + *err = build_equiv_class (sbcset, + mbcset, &equiv_class_alloc, + start_elem.opr.name); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + case COLL_SYM: + *err = build_collating_symbol (sbcset, + mbcset, &coll_sym_alloc, + start_elem.opr.name, + nrules, table_size, symb_table, extra); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + case CHAR_CLASS: + *err = build_charclass (regexp->trans, sbcset, + mbcset, &char_class_alloc, + (const char *) start_elem.opr.name, + syntax); + if (__glibc_unlikely (*err != REG_NOERROR)) + goto parse_bracket_exp_free_return; + break; + default: + DEBUG_ASSERT (false); + break; + } + } + if (__glibc_unlikely (token->type == END_OF_RE)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CLOSE_BRACKET) + break; + } + + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); + + if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes + || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes + || mbcset->non_match))) + { + bin_tree_t *mbc_tree; + int sbc_idx; + /* Build a tree for complex bracket. */ + dfa->has_mb_node = 1; + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (mbc_tree == NULL)) + goto parse_bracket_exp_espace; + for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) + if (sbcset[sbc_idx]) + break; + /* If there are no bits set in sbcset, there is no point + of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ + if (sbc_idx < BITSET_WORDS) + { + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + + /* Then join them by ALT node. */ + work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + } + else + { + re_free (sbcset); + work_tree = mbc_tree; + } + } + else + { + free_charset (mbcset); + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (work_tree == NULL)) + goto parse_bracket_exp_espace; + } + return work_tree; + + parse_bracket_exp_espace: + *err = REG_ESPACE; + parse_bracket_exp_free_return: + re_free (sbcset); + free_charset (mbcset); + return NULL; +} + +/* Parse an element in the bracket expression. */ + +static reg_errcode_t +parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token, int token_len, re_dfa_t *dfa, + reg_syntax_t syntax, bool accept_hyphen) +{ + int cur_char_size; + cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); + if (cur_char_size > 1) + { + elem->type = MB_CHAR; + elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); + re_string_skip_bytes (regexp, cur_char_size); + return REG_NOERROR; + } + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS + || token->type == OP_OPEN_EQUIV_CLASS) + return parse_bracket_symbol (elem, regexp, token); + if (__glibc_unlikely (token->type == OP_CHARSET_RANGE) && !accept_hyphen) + { + /* A '-' must only appear as anything but a range indicator before + the closing bracket. Everything else is an error. */ + re_token_t token2; + (void) peek_token_bracket (&token2, regexp, syntax); + if (token2.type != OP_CLOSE_BRACKET) + /* The actual error value is not standardized since this whole + case is undefined. But ERANGE makes good sense. */ + return REG_ERANGE; + } + elem->type = SB_CHAR; + elem->opr.ch = token->opr.c; + return REG_NOERROR; +} + +/* Parse a bracket symbol in the bracket expression. Bracket symbols are + such as [::], [..], and + [==]. */ + +static reg_errcode_t +parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token) +{ + unsigned char ch, delim = token->opr.c; + int i = 0; + if (re_string_eoi(regexp)) + return REG_EBRACK; + for (;; ++i) + { + if (i >= BRACKET_NAME_BUF_SIZE) + return REG_EBRACK; + if (token->type == OP_OPEN_CHAR_CLASS) + ch = re_string_fetch_byte_case (regexp); + else + ch = re_string_fetch_byte (regexp); + if (re_string_eoi(regexp)) + return REG_EBRACK; + if (ch == delim && re_string_peek_byte (regexp, 0) == ']') + break; + elem->opr.name[i] = ch; + } + re_string_skip_bytes (regexp, 1); + elem->opr.name[i] = '\0'; + switch (token->type) + { + case OP_OPEN_COLL_ELEM: + elem->type = COLL_SYM; + break; + case OP_OPEN_EQUIV_CLASS: + elem->type = EQUIV_CLASS; + break; + case OP_OPEN_CHAR_CLASS: + elem->type = CHAR_CLASS; + break; + default: + break; + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the equivalence class which is represented by NAME. + The result are written to MBCSET and SBCSET. + EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, + is a pointer argument since we may update it. */ + +static reg_errcode_t +build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, + Idx *equiv_class_alloc, const unsigned char *name) +{ +#ifdef _LIBC + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const int32_t *table, *indirect; + const unsigned char *weights, *extra, *cp; + unsigned char char_buf[2]; + int32_t idx1, idx2; + unsigned int ch; + size_t len; + /* Calculate the index for equivalence class. */ + cp = name; + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + idx1 = findidx (table, indirect, extra, &cp, -1); + if (__glibc_unlikely (idx1 == 0 || *cp != '\0')) + /* This isn't a valid character. */ + return REG_ECOLLATE; + + /* Build single byte matching table for this equivalence class. */ + len = weights[idx1 & 0xffffff]; + for (ch = 0; ch < SBC_MAX; ++ch) + { + char_buf[0] = ch; + cp = char_buf; + idx2 = findidx (table, indirect, extra, &cp, 1); +/* + idx2 = table[ch]; +*/ + if (idx2 == 0) + /* This isn't a valid character. */ + continue; + /* Compare only if the length matches and the collation rule + index is the same. */ + if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24) + && memcmp (weights + (idx1 & 0xffffff) + 1, + weights + (idx2 & 0xffffff) + 1, len) == 0) + bitset_set (sbcset, ch); + } + /* Check whether the array has enough space. */ + if (__glibc_unlikely (*equiv_class_alloc == mbcset->nequiv_classes)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nequiv_classes is 0. */ + Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; + /* Use realloc since the array is NULL if *alloc == 0. */ + int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, + int32_t, + new_equiv_class_alloc); + if (__glibc_unlikely (new_equiv_classes == NULL)) + return REG_ESPACE; + mbcset->equiv_classes = new_equiv_classes; + *equiv_class_alloc = new_equiv_class_alloc; + } + mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; + } + else +#endif /* _LIBC */ + { + if (__glibc_unlikely (strlen ((const char *) name) != 1)) + return REG_ECOLLATE; + bitset_set (sbcset, *name); + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the character class which is represented by NAME. + The result are written to MBCSET and SBCSET. + CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, + is a pointer argument since we may update it. */ + +static reg_errcode_t +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + re_charset_t *mbcset, Idx *char_class_alloc, + const char *class_name, reg_syntax_t syntax) +{ + int i; + const char *name = class_name; + + /* In case of REG_ICASE "upper" and "lower" match the both of + upper and lower cases. */ + if ((syntax & RE_ICASE) + && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) + name = "alpha"; + + /* Check the space of the arrays. */ + if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nchar_classes is 0. */ + Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, + new_char_class_alloc); + if (__glibc_unlikely (new_char_classes == NULL)) + return REG_ESPACE; + mbcset->char_classes = new_char_classes; + *char_class_alloc = new_char_class_alloc; + } + mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); + +#define BUILD_CHARCLASS_LOOP(ctype_func) \ + do { \ + if (__glibc_unlikely (trans != NULL)) \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, trans[i]); \ + } \ + else \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, i); \ + } \ + } while (0) + + if (strcmp (name, "alnum") == 0) + BUILD_CHARCLASS_LOOP (isalnum); + else if (strcmp (name, "cntrl") == 0) + BUILD_CHARCLASS_LOOP (iscntrl); + else if (strcmp (name, "lower") == 0) + BUILD_CHARCLASS_LOOP (islower); + else if (strcmp (name, "space") == 0) + BUILD_CHARCLASS_LOOP (isspace); + else if (strcmp (name, "alpha") == 0) + BUILD_CHARCLASS_LOOP (isalpha); + else if (strcmp (name, "digit") == 0) + BUILD_CHARCLASS_LOOP (isdigit); + else if (strcmp (name, "print") == 0) + BUILD_CHARCLASS_LOOP (isprint); + else if (strcmp (name, "upper") == 0) + BUILD_CHARCLASS_LOOP (isupper); + else if (strcmp (name, "blank") == 0) + BUILD_CHARCLASS_LOOP (isblank); + else if (strcmp (name, "graph") == 0) + BUILD_CHARCLASS_LOOP (isgraph); + else if (strcmp (name, "punct") == 0) + BUILD_CHARCLASS_LOOP (ispunct); + else if (strcmp (name, "xdigit") == 0) + BUILD_CHARCLASS_LOOP (isxdigit); + else + return REG_ECTYPE; + + return REG_NOERROR; +} + +static bin_tree_t * +build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + const char *class_name, + const char *extra, bool non_match, + reg_errcode_t *err) +{ + re_bitset_ptr_t sbcset; + re_charset_t *mbcset; + Idx alloc = 0; + reg_errcode_t ret; + bin_tree_t *tree; + + sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); + if (__glibc_unlikely (sbcset == NULL)) + { + *err = REG_ESPACE; + return NULL; + } + mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); + if (__glibc_unlikely (mbcset == NULL)) + { + re_free (sbcset); + *err = REG_ESPACE; + return NULL; + } + mbcset->non_match = non_match; + + /* We don't care the syntax in this case. */ + ret = build_charclass (trans, sbcset, mbcset, &alloc, class_name, 0); + + if (__glibc_unlikely (ret != REG_NOERROR)) + { + re_free (sbcset); + free_charset (mbcset); + *err = ret; + return NULL; + } + /* \w match '_' also. */ + for (; *extra; extra++) + bitset_set (sbcset, *extra); + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); + + /* Build a tree for simple bracket. */ + re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset }; + tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (tree == NULL)) + goto build_word_op_espace; + + if (dfa->mb_cur_max > 1) + { + bin_tree_t *mbc_tree; + /* Build a tree for complex bracket. */ + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + dfa->has_mb_node = 1; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (__glibc_unlikely (mbc_tree == NULL)) + goto build_word_op_espace; + /* Then join them by ALT node. */ + tree = create_tree (dfa, tree, mbc_tree, OP_ALT); + if (__glibc_likely (mbc_tree != NULL)) + return tree; + } + else + { + free_charset (mbcset); + return tree; + } + + build_word_op_espace: + re_free (sbcset); + free_charset (mbcset); + *err = REG_ESPACE; + return NULL; +} + +/* This is intended for the expressions like "a{1,3}". + Fetch a number from 'input', and return the number. + Return -1 if the number field is empty like "{,1}". + Return RE_DUP_MAX + 1 if the number field is too large. + Return -2 if an error occurred. */ + +static Idx +fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) +{ + Idx num = -1; + unsigned char c; + while (1) + { + fetch_token (token, input, syntax); + c = token->opr.c; + if (__glibc_unlikely (token->type == END_OF_RE)) + return -2; + if (token->type == OP_CLOSE_DUP_NUM || c == ',') + break; + num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) + ? -2 + : num == -1 + ? c - '0' + : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); + } + return num; +} + +static void +free_charset (re_charset_t *cset) +{ + re_free (cset->mbchars); +#ifdef _LIBC + re_free (cset->coll_syms); + re_free (cset->equiv_classes); +#endif + re_free (cset->range_starts); + re_free (cset->range_ends); + re_free (cset->char_classes); + re_free (cset); +} + +/* Functions for binary tree operation. */ + +/* Create a tree node. */ + +static bin_tree_t * +create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + re_token_type_t type) +{ + re_token_t t = { .type = type }; + return create_token_tree (dfa, left, right, &t); +} + +static bin_tree_t * +create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + const re_token_t *token) +{ + bin_tree_t *tree; + if (__glibc_unlikely (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE)) + { + bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); + + if (storage == NULL) + return NULL; + storage->next = dfa->str_tree_storage; + dfa->str_tree_storage = storage; + dfa->str_tree_storage_idx = 0; + } + tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; + + tree->parent = NULL; + tree->left = left; + tree->right = right; + tree->token = *token; + tree->token.duplicated = 0; + tree->token.opt_subexp = 0; + tree->first = NULL; + tree->next = NULL; + tree->node_idx = -1; + + if (left != NULL) + left->parent = tree; + if (right != NULL) + right->parent = tree; + return tree; +} + +/* Mark the tree SRC as an optional subexpression. + To be called from preorder or postorder. */ + +static reg_errcode_t +mark_opt_subexp (void *extra, bin_tree_t *node) +{ + Idx idx = (uintptr_t) extra; + if (node->token.type == SUBEXP && node->token.opr.idx == idx) + node->token.opt_subexp = 1; + + return REG_NOERROR; +} + +/* Free the allocated memory inside NODE. */ + +static void +free_token (re_token_t *node) +{ + if (node->type == COMPLEX_BRACKET && node->duplicated == 0) + free_charset (node->opr.mbcset); + else if (node->type == SIMPLE_BRACKET && node->duplicated == 0) + re_free (node->opr.sbcset); +} + +/* Worker function for tree walking. Free the allocated memory inside NODE + and its children. */ + +static reg_errcode_t +free_tree (void *extra, bin_tree_t *node) +{ + free_token (&node->token); + return REG_NOERROR; +} + + +/* Duplicate the node SRC, and return new node. This is a preorder + visit similar to the one implemented by the generic visitor, but + we need more infrastructure to maintain two parallel trees --- so, + it's easier to duplicate. */ + +static bin_tree_t * +duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) +{ + const bin_tree_t *node; + bin_tree_t *dup_root; + bin_tree_t **p_new = &dup_root, *dup_node = root->parent; + + for (node = root; ; ) + { + /* Create a new tree and link it back to the current parent. */ + *p_new = create_token_tree (dfa, NULL, NULL, &node->token); + if (*p_new == NULL) + return NULL; + (*p_new)->parent = dup_node; + (*p_new)->token.duplicated = 1; + dup_node = *p_new; + + /* Go to the left node, or up and to the right. */ + if (node->left) + { + node = node->left; + p_new = &dup_node->left; + } + else + { + const bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + dup_node = dup_node->parent; + if (!node) + return dup_root; + } + node = node->right; + p_new = &dup_node->right; + } + } +} diff --git a/cross/lib/regex.c b/cross/lib/regex.c new file mode 100644 index 00000000000..3beb0deb987 --- /dev/null +++ b/cross/lib/regex.c @@ -0,0 +1,84 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#define __STDC_WANT_IEC_60559_BFP_EXT__ + +#ifndef _LIBC +# include + +# if __GNUC_PREREQ (4, 6) +# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" +# pragma GCC diagnostic ignored "-Wvla" +# endif +# if __GNUC_PREREQ (4, 3) +# pragma GCC diagnostic ignored "-Wold-style-definition" +# pragma GCC diagnostic ignored "-Wtype-limits" +# endif +#endif + +/* Make sure no one compiles this code with a C++ compiler. */ +#if defined __cplusplus && defined _LIBC +# error "This is C code, use a C compiler" +#endif + +#ifdef _LIBC +/* We have to keep the namespace clean. */ +# define regfree(preg) __regfree (preg) +# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) +# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) +# define regerror(errcode, preg, errbuf, errbuf_size) \ + __regerror(errcode, preg, errbuf, errbuf_size) +# define re_set_registers(bu, re, nu, st, en) \ + __re_set_registers (bu, re, nu, st, en) +# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ + __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) +# define re_match(bufp, string, size, pos, regs) \ + __re_match (bufp, string, size, pos, regs) +# define re_search(bufp, string, size, startpos, range, regs) \ + __re_search (bufp, string, size, startpos, range, regs) +# define re_compile_pattern(pattern, length, bufp) \ + __re_compile_pattern (pattern, length, bufp) +# define re_set_syntax(syntax) __re_set_syntax (syntax) +# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ + __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) +# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) + +# include "../locale/localeinfo.h" +#endif + +/* On some systems, limits.h sets RE_DUP_MAX to a lower value than + GNU regex allows. Include it before , which correctly + #undefs RE_DUP_MAX and sets it to the right value. */ +#include + +#include +#include "regex_internal.h" + +#include "regex_internal.c" +#include "regcomp.c" +#include "regexec.c" + +/* Binary backward compatibility. */ +#if _LIBC +# include +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) +link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") +int re_max_failures = 2000; +# endif +#endif diff --git a/cross/lib/regex.h b/cross/lib/regex.h new file mode 100644 index 00000000000..9ef0252ffff --- /dev/null +++ b/cross/lib/regex.h @@ -0,0 +1,699 @@ +/* Definitions for data structures and routines for the regular + expression library. + Copyright (C) 1985, 1989-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +#include + +/* Allow the use in C++ code. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Define __USE_GNU to declare GNU extensions that violate the + POSIX name space rules. */ +#ifdef _GNU_SOURCE +# define __USE_GNU 1 +#endif + +#ifdef _REGEX_LARGE_OFFSETS + +/* Use types and values that are wide enough to represent signed and + unsigned byte offsets in memory. This currently works only when + the regex code is used outside of the GNU C library; it is not yet + supported within glibc itself, and glibc users should not define + _REGEX_LARGE_OFFSETS. */ + +/* The type of object sizes. */ +typedef size_t __re_size_t; + +/* The type of object sizes, in places where the traditional code + uses unsigned long int. */ +typedef size_t __re_long_size_t; + +#else + +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef unsigned int __re_size_t; +typedef unsigned long int __re_long_size_t; + +#endif + +/* The following two types have to be signed and unsigned integer type + wide enough to hold a value of a pointer. For most ANSI compilers + ptrdiff_t and size_t should be likely OK. Still size of these two + types is 2 for Microsoft C. Ugh... */ +typedef long int s_reg_t; +typedef unsigned long int active_reg_t; + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned long int reg_syntax_t; + +#ifdef __USE_GNU +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +# define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then '{...}' defines an interval, and \{ and \} + are literals. + If not set, then '\{...\}' defines an interval. */ +# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \ matches . + If not set, then \ is a back-reference. */ +# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* If this bit is set, succeed as soon as we match the whole pattern, + without further backtracking. */ +# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) + +/* If this bit is set, do not process the GNU regex operators. + If not set, then the GNU regex operators are recognized. */ +# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) + +/* If this bit is set, turn on internal regex debugging. + If not set, and debugging was on, turn it off. + This only works if regex.c is compiled -DDEBUG. + We define this bit always, so that all that's needed to turn on + debugging is to recompile regex.c; the calling code can always have + this bit set, and it won't affect anything in the normal case. */ +# define RE_DEBUG (RE_NO_GNU_OPS << 1) + +/* If this bit is set, a syntactically invalid interval is treated as + a string of ordinary characters. For example, the ERE 'a{1' is + treated as 'a\{1'. */ +# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) + +/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only + for ^, because it is difficult to scan the regex backwards to find + whether ^ should be special. */ +# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) + +/* If this bit is set, then \{ cannot be first in a regex or + immediately after an alternation, open-group or \} operator. */ +# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) + +/* If this bit is set, then no_sub will be set to 1 during + re_compile_pattern. */ +# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) +#endif + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +#ifdef __USE_GNU +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +# define RE_SYNTAX_EMACS 0 + +# define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CHAR_CLASSES \ + | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) + +# define RE_SYNTAX_GNU_AWK \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INVALID_INTERVAL_ORD) \ + & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) + +# define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INTERVALS | RE_NO_GNU_OPS \ + | RE_INVALID_INTERVAL_ORD) + +# define RE_SYNTAX_GREP \ + ((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \ + & ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL)) + +# define RE_SYNTAX_EGREP \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \ + & ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL)) + +/* POSIX grep -E behavior is no longer incompatible with GNU. */ +# define RE_SYNTAX_POSIX_EGREP \ + RE_SYNTAX_EGREP + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +# define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +# define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +# define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is + removed and RE_NO_BK_REFS is added. */ +# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. POSIX-conforming + systems might define this in , but we want our + value, so remove any previous define. */ +# ifdef _REGEX_INCLUDE_LIMITS_H +# include +# endif +# ifdef RE_DUP_MAX +# undef RE_DUP_MAX +# endif + +/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored + the counter as a 2-byte signed integer. This is no longer true, so + RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to + ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined. + However, there would be a huge performance problem if someone + actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains + its historical value. */ +# define RE_DUP_MAX (0x7fff) +#endif + + +/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (1 << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (1 << 2) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (1 << 3) + + +/* POSIX 'eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + +/* Use PMATCH[0] to delimit the start and end of the search in the + buffer. */ +#define REG_STARTEND (1 << 2) + + +/* If any error codes are removed, changed, or added, update the + '__re_error_msgid' table in regcomp.c. */ + +typedef enum +{ + _REG_ENOSYS = -1, /* This will never happen for this implementation. */ + _REG_NOERROR = 0, /* Success. */ + _REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + _REG_BADPAT, /* Invalid pattern. */ + _REG_ECOLLATE, /* Invalid collating element. */ + _REG_ECTYPE, /* Invalid character class name. */ + _REG_EESCAPE, /* Trailing backslash. */ + _REG_ESUBREG, /* Invalid back reference. */ + _REG_EBRACK, /* Unmatched left bracket. */ + _REG_EPAREN, /* Parenthesis imbalance. */ + _REG_EBRACE, /* Unmatched \{. */ + _REG_BADBR, /* Invalid contents of \{\}. */ + _REG_ERANGE, /* Invalid range end. */ + _REG_ESPACE, /* Ran out of memory. */ + _REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + _REG_EEND, /* Premature end. */ + _REG_ESIZE, /* Too large (e.g., repeat count too large). */ + _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K +# define REG_ENOSYS _REG_ENOSYS +#endif +#define REG_NOERROR _REG_NOERROR +#define REG_NOMATCH _REG_NOMATCH +#define REG_BADPAT _REG_BADPAT +#define REG_ECOLLATE _REG_ECOLLATE +#define REG_ECTYPE _REG_ECTYPE +#define REG_EESCAPE _REG_EESCAPE +#define REG_ESUBREG _REG_ESUBREG +#define REG_EBRACK _REG_EBRACK +#define REG_EPAREN _REG_EPAREN +#define REG_EBRACE _REG_EBRACE +#define REG_BADBR _REG_BADBR +#define REG_ERANGE _REG_ERANGE +#define REG_ESPACE _REG_ESPACE +#define REG_BADRPT _REG_BADRPT +#define REG_EEND _REG_EEND +#define REG_ESIZE _REG_ESIZE +#define REG_ERPAREN _REG_ERPAREN + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields 'buffer', 'allocated', 'fastmap', + and 'translate' can be set. After the pattern has been compiled, + the fields 're_nsub', 'not_bol' and 'not_eol' are available. All + other fields are private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define __RE_TRANSLATE_TYPE unsigned char * +# ifdef __USE_GNU +# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE +# endif +#endif + +#ifdef __USE_GNU +# define __REPB_PREFIX(name) name +#else +# define __REPB_PREFIX(name) __##name +#endif + +struct re_pattern_buffer +{ + /* Space that holds the compiled pattern. The type + 'struct re_dfa_t' is private and is not declared here. */ + struct re_dfa_t *__REPB_PREFIX(buffer); + + /* Number of bytes to which 'buffer' points. */ + __re_long_size_t __REPB_PREFIX(allocated); + + /* Number of bytes actually used in 'buffer'. */ + __re_long_size_t __REPB_PREFIX(used); + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t __REPB_PREFIX(syntax); + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses the + fastmap, if there is one, to skip over impossible starting points + for matches. */ + char *__REPB_PREFIX(fastmap); + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation is + applied to a pattern when it is compiled and to a string when it + is matched. */ + __RE_TRANSLATE_TYPE __REPB_PREFIX(translate); + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in 're_search_2', to see whether or + not we should use the fastmap, so we don't set this absolutely + perfectly; see 're_compile_fastmap' (the "duplicate" case). */ + unsigned __REPB_PREFIX(can_be_null) : 1; + + /* If REGS_UNALLOCATED, allocate space in the 'regs' structure + for 'max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#ifdef __USE_GNU +# define REGS_UNALLOCATED 0 +# define REGS_REALLOCATE 1 +# define REGS_FIXED 2 +#endif + unsigned __REPB_PREFIX(regs_allocated) : 2; + + /* Set to zero when 're_compile_pattern' compiles a pattern; set to + one by 're_compile_fastmap' if it updates the fastmap. */ + unsigned __REPB_PREFIX(fastmap_accurate) : 1; + + /* If set, 're_match_2' does not return information about + subexpressions. */ + unsigned __REPB_PREFIX(no_sub) : 1; + + /* If set, a beginning-of-line anchor doesn't match at the beginning + of the string. */ + unsigned __REPB_PREFIX(not_bol) : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned __REPB_PREFIX(not_eol) : 1; + + /* If true, an anchor at a newline matches. */ + unsigned __REPB_PREFIX(newline_anchor) : 1; +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +#ifdef _REGEX_LARGE_OFFSETS +/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as + ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t + is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not + visible here, so use ssize_t. */ +typedef ssize_t regoff_t; +#else +/* The traditional GNU regex implementation mishandles strings longer + than INT_MAX. */ +typedef int regoff_t; +#endif + + +#ifdef __USE_GNU +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + __re_size_t num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + 're_match_2' returns information about at least this many registers + the first time a 'regs' structure is passed. */ +# ifndef RE_NREGS +# define RE_NREGS 30 +# endif +#endif + + +/* POSIX specification for registers. Aside from the different names than + 're_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + +#ifndef _REGEX_NELTS +# if (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ + && !defined __STDC_NO_VLA__) +# define _REGEX_NELTS(n) n +# else +# define _REGEX_NELTS(n) +# endif +#endif + +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wvla" +#endif + +#ifndef _Attr_access_ +# ifdef __attr_access +# define _Attr_access_(arg) __attr_access (arg) +# elif defined __GNUC__ && 10 <= __GNUC__ +# define _Attr_access_(x) __attribute__ ((__access__ x)) +# else +# define _Attr_access_(x) +# endif +#endif + +#ifdef __USE_GNU +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the 're_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global 're_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. + + To free the allocated storage, you must call 'regfree' on BUFFER. + Note that the translate table must either have been initialized by + 'regcomp', with a malloc'ed value, or set to NULL before calling + 'regfree'. */ +extern const char *re_compile_pattern (const char *__pattern, size_t __length, + struct re_pattern_buffer *__buffer) + _Attr_access_ ((__read_only__, 1, 2)); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern regoff_t re_search (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, regoff_t __range, + struct re_registers *__regs) + _Attr_access_ ((__read_only__, 2, 3)); + + +/* Like 're_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, + const char *__string1, regoff_t __length1, + const char *__string2, regoff_t __length2, + regoff_t __start, regoff_t __range, + struct re_registers *__regs, + regoff_t __stop) + _Attr_access_ ((__read_only__, 2, 3)) + _Attr_access_ ((__read_only__, 4, 5)); + + +/* Like 're_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern regoff_t re_match (struct re_pattern_buffer *__buffer, + const char *__String, regoff_t __length, + regoff_t __start, struct re_registers *__regs) + _Attr_access_ ((__read_only__, 2, 3)); + + +/* Relates to 're_match' as 're_search_2' relates to 're_search'. */ +extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, + const char *__string1, regoff_t __length1, + const char *__string2, regoff_t __length2, + regoff_t __start, struct re_registers *__regs, + regoff_t __stop) + _Attr_access_ ((__read_only__, 2, 3)) + _Attr_access_ ((__read_only__, 4, 5)); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least 'NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers (struct re_pattern_buffer *__buffer, + struct re_registers *__regs, + __re_size_t __num_regs, + regoff_t *__starts, regoff_t *__ends); +#endif /* Use GNU */ + +#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC) +/* 4.2 bsd compatibility. */ +extern char *re_comp (const char *); +extern int re_exec (const char *); +#endif + +/* For plain 'restrict', use glibc's __restrict if defined. + Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". + Other compilers use __restrict, __restrict__, and _Restrict, and + 'configure' might #define 'restrict' to those words, so pick a + different name. */ +#ifndef _Restrict_ +# if defined __restrict \ + || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \ + || __clang_major__ >= 3 +# define _Restrict_ __restrict +# elif 199901L <= __STDC_VERSION__ || defined restrict +# define _Restrict_ restrict +# else +# define _Restrict_ +# endif +#endif +/* For the ISO C99 syntax + array_name[restrict] + use glibc's __restrict_arr if available. + Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode). + Other ISO C99 compilers support it as well. */ +#ifndef _Restrict_arr_ +# ifdef __restrict_arr +# define _Restrict_arr_ __restrict_arr +# elif ((199901L <= __STDC_VERSION__ \ + || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \ + || __clang_major__ >= 3) \ + && !defined __cplusplus) +# define _Restrict_arr_ _Restrict_ +# else +# define _Restrict_arr_ +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp (regex_t *_Restrict_ __preg, + const char *_Restrict_ __pattern, + int __cflags); + +extern int regexec (const regex_t *_Restrict_ __preg, + const char *_Restrict_ __String, size_t __nmatch, + regmatch_t __pmatch[_Restrict_arr_ + _REGEX_NELTS (__nmatch)], + int __eflags); + +extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, + char *_Restrict_ __errbuf, size_t __errbuf_size) + _Attr_access_ ((__write_only__, 3, 4)); + +extern void regfree (regex_t *__preg); + +#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic pop +#endif + +#ifdef __cplusplus +} +#endif /* C++ */ + +#endif /* regex.h */ diff --git a/cross/lib/regex_internal.c b/cross/lib/regex_internal.c new file mode 100644 index 00000000000..998a19b7241 --- /dev/null +++ b/cross/lib/regex_internal.c @@ -0,0 +1,1711 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +static void re_string_construct_common (const char *str, Idx len, + re_string_t *pstr, + RE_TRANSLATE_TYPE trans, bool icase, + const re_dfa_t *dfa); +static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + re_hashval_t hash); +static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int context, + re_hashval_t hash); +static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, + Idx new_buf_len); +static void build_wcs_buffer (re_string_t *pstr); +static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr); +static void build_upper_buffer (re_string_t *pstr); +static void re_string_translate_buffer (re_string_t *pstr); +static unsigned int re_string_context_at (const re_string_t *input, Idx idx, + int eflags) __attribute__ ((pure)); + +/* Functions for string operation. */ + +/* This function allocate the buffers. It is necessary to call + re_string_reconstruct before using the object. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, + RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + Idx init_buf_len; + + /* Ensure at least one character fits into the buffers. */ + if (init_len < dfa->mb_cur_max) + init_len = dfa->mb_cur_max; + init_buf_len = (len + 1 < init_len) ? len + 1: init_len; + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + ret = re_string_realloc_buffers (pstr, init_buf_len); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + pstr->word_char = dfa->word_char; + pstr->word_ops_used = dfa->word_ops_used; + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; + pstr->valid_raw_len = pstr->valid_len; + return REG_NOERROR; +} + +/* This function allocate the buffers, and initialize them. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_construct (re_string_t *pstr, const char *str, Idx len, + RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + memset (pstr, '\0', sizeof (re_string_t)); + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + if (len > 0) + { + ret = re_string_realloc_buffers (pstr, len + 1); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + + if (icase) + { + if (dfa->mb_cur_max > 1) + { + while (1) + { + ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + if (pstr->valid_raw_len >= len) + break; + if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) + break; + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + } + else + build_upper_buffer (pstr); + } + else + { + if (dfa->mb_cur_max > 1) + build_wcs_buffer (pstr); + else + { + if (trans != NULL) + re_string_translate_buffer (pstr); + else + { + pstr->valid_len = pstr->bufs_len; + pstr->valid_raw_len = pstr->bufs_len; + } + } + } + + return REG_NOERROR; +} + +/* Helper functions for re_string_allocate, and re_string_construct. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) +{ + if (pstr->mb_cur_max > 1) + { + wint_t *new_wcs; + + /* Avoid overflow in realloc. */ + const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) + < new_buf_len)) + return REG_ESPACE; + + new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); + if (__glibc_unlikely (new_wcs == NULL)) + return REG_ESPACE; + pstr->wcs = new_wcs; + if (pstr->offsets != NULL) + { + Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); + if (__glibc_unlikely (new_offsets == NULL)) + return REG_ESPACE; + pstr->offsets = new_offsets; + } + } + if (pstr->mbs_allocated) + { + unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, + new_buf_len); + if (__glibc_unlikely (new_mbs == NULL)) + return REG_ESPACE; + pstr->mbs = new_mbs; + } + pstr->bufs_len = new_buf_len; + return REG_NOERROR; +} + + +static void +re_string_construct_common (const char *str, Idx len, re_string_t *pstr, + RE_TRANSLATE_TYPE trans, bool icase, + const re_dfa_t *dfa) +{ + pstr->raw_mbs = (const unsigned char *) str; + pstr->len = len; + pstr->raw_len = len; + pstr->trans = trans; + pstr->icase = icase; + pstr->mbs_allocated = (trans != NULL || icase); + pstr->mb_cur_max = dfa->mb_cur_max; + pstr->is_utf8 = dfa->is_utf8; + pstr->map_notascii = dfa->map_notascii; + pstr->stop = pstr->len; + pstr->raw_stop = pstr->stop; +} + + +/* Build wide character buffer PSTR->WCS. + If the byte sequence of the string are: + (0), (1), (0), (1), + Then wide character buffer will be: + , WEOF , , WEOF , + We use WEOF for padding, they indicate that the position isn't + a first byte of a multibyte character. + + Note that this function assumes PSTR->VALID_LEN elements are already + built and starts from PSTR->VALID_LEN. */ + +static void +build_wcs_buffer (re_string_t *pstr) +{ +#ifdef _LIBC + unsigned char buf[MB_LEN_MAX]; + DEBUG_ASSERT (MB_LEN_MAX >= pstr->mb_cur_max); +#else + unsigned char buf[64]; +#endif + mbstate_t prev_st; + Idx byte_idx, end_idx, remain_len; + size_t mbclen; + + /* Build the buffers from pstr->valid_len to either pstr->len or + pstr->bufs_len. */ + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + for (byte_idx = pstr->valid_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + /* Apply the translation if we need. */ + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; + buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (__glibc_unlikely (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 + && pstr->bufs_len >= pstr->len))) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + if (__glibc_unlikely (pstr->trans != NULL)) + wc = pstr->trans[wc]; + pstr->cur_state = prev_st; + } + else if (__glibc_unlikely (mbclen == (size_t) -2)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + + /* Write wide character and padding. */ + pstr->wcs[byte_idx++] = wc; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; +} + +/* Build wide character buffer PSTR->WCS like build_wcs_buffer, + but for REG_ICASE. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +build_wcs_upper_buffer (re_string_t *pstr) +{ + mbstate_t prev_st; + Idx src_idx, byte_idx, end_idx, remain_len; + size_t mbclen; +#ifdef _LIBC + char buf[MB_LEN_MAX]; + DEBUG_ASSERT (pstr->mb_cur_max <= MB_LEN_MAX); +#else + char buf[64]; +#endif + + byte_idx = pstr->valid_len; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + /* The following optimization assumes that ASCII characters can be + mapped to wide characters with a simple cast. */ + if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) + { + while (byte_idx < end_idx) + { + wchar_t wc; + unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + + if (isascii (ch) && mbsinit (&pstr->cur_state)) + { + /* The next step uses the assumption that wchar_t is encoded + ASCII-safe: all ASCII values can be converted like this. */ + wchar_t wcu = __towupper (ch); + if (isascii (wcu)) + { + pstr->mbs[byte_idx] = wcu; + pstr->wcs[byte_idx] = wcu; + byte_idx++; + continue; + } + } + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + mbclen = __mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); + if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) + { + size_t mbcdlen; + + mbcdlen = __wcrtomb (buf, wcu, &prev_st); + if (__glibc_likely (mbclen == mbcdlen)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else + { + src_idx = byte_idx; + goto offsets_needed; + } + } + else + memcpy (pstr->mbs + byte_idx, + pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) + { + /* It is an invalid character, an incomplete character + at the end of the string, or '\0'. Just use the byte. */ + pstr->mbs[byte_idx] = ch; + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (__glibc_unlikely (mbclen == (size_t) -1)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; + return REG_NOERROR; + } + else + for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + offsets_needed: + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; + buf[i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) + { + size_t mbcdlen; + + mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st); + if (__glibc_likely (mbclen == mbcdlen)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else if (mbcdlen != (size_t) -1) + { + size_t i; + + if (byte_idx + mbcdlen > pstr->bufs_len) + { + pstr->cur_state = prev_st; + break; + } + + if (pstr->offsets == NULL) + { + pstr->offsets = re_malloc (Idx, pstr->bufs_len); + + if (pstr->offsets == NULL) + return REG_ESPACE; + } + if (!pstr->offsets_needed) + { + for (i = 0; i < (size_t) byte_idx; ++i) + pstr->offsets[i] = i; + pstr->offsets_needed = 1; + } + + memcpy (pstr->mbs + byte_idx, buf, mbcdlen); + pstr->wcs[byte_idx] = wcu; + pstr->offsets[byte_idx] = src_idx; + for (i = 1; i < mbcdlen; ++i) + { + pstr->offsets[byte_idx + i] + = src_idx + (i < mbclen ? i : mbclen - 1); + pstr->wcs[byte_idx + i] = WEOF; + } + pstr->len += mbcdlen - mbclen; + if (pstr->raw_stop > src_idx) + pstr->stop += mbcdlen - mbclen; + end_idx = (pstr->bufs_len > pstr->len) + ? pstr->len : pstr->bufs_len; + byte_idx += mbcdlen; + src_idx += mbclen; + continue; + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + + if (__glibc_unlikely (pstr->offsets_needed != 0)) + { + size_t i; + for (i = 0; i < mbclen; ++i) + pstr->offsets[byte_idx + i] = src_idx + i; + } + src_idx += mbclen; + + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; + + if (__glibc_unlikely (pstr->trans != NULL)) + ch = pstr->trans [ch]; + pstr->mbs[byte_idx] = ch; + + if (__glibc_unlikely (pstr->offsets_needed != 0)) + pstr->offsets[byte_idx] = src_idx; + ++src_idx; + + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (__glibc_unlikely (mbclen == (size_t) -1)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = src_idx; + return REG_NOERROR; +} + +/* Skip characters until the index becomes greater than NEW_RAW_IDX. + Return the index. */ + +static Idx +re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) +{ + mbstate_t prev_st; + Idx rawbuf_idx; + size_t mbclen; + wint_t wc = WEOF; + + /* Skip the characters which are not necessary to check. */ + for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; + rawbuf_idx < new_raw_idx;) + { + wchar_t wc2; + Idx remain_len = pstr->raw_len - rawbuf_idx; + prev_st = pstr->cur_state; + mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, + remain_len, &pstr->cur_state); + if (__glibc_unlikely (mbclen == (size_t) -2 || mbclen == (size_t) -1 + || mbclen == 0)) + { + /* We treat these cases as a single byte character. */ + if (mbclen == 0 || remain_len == 0) + wc = L'\0'; + else + wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); + mbclen = 1; + pstr->cur_state = prev_st; + } + else + wc = wc2; + /* Then proceed the next character. */ + rawbuf_idx += mbclen; + } + *last_wc = wc; + return rawbuf_idx; +} + +/* Build the buffer PSTR->MBS, and apply the translation if we need. + This function is used in case of REG_ICASE. */ + +static void +build_upper_buffer (re_string_t *pstr) +{ + Idx char_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; + if (__glibc_unlikely (pstr->trans != NULL)) + ch = pstr->trans[ch]; + pstr->mbs[char_idx] = toupper (ch); + } + pstr->valid_len = char_idx; + pstr->valid_raw_len = char_idx; +} + +/* Apply TRANS to the buffer in PSTR. */ + +static void +re_string_translate_buffer (re_string_t *pstr) +{ + Idx buf_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; + pstr->mbs[buf_idx] = pstr->trans[ch]; + } + + pstr->valid_len = buf_idx; + pstr->valid_raw_len = buf_idx; +} + +/* This function re-construct the buffers. + Concretely, convert to wide character in case of pstr->mb_cur_max > 1, + convert to upper case in case of REG_ICASE, apply translation. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) +{ + Idx offset; + + if (__glibc_unlikely (pstr->raw_mbs_idx <= idx)) + offset = idx - pstr->raw_mbs_idx; + else + { + /* Reset buffer. */ + if (pstr->mb_cur_max > 1) + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + pstr->len = pstr->raw_len; + pstr->stop = pstr->raw_stop; + pstr->valid_len = 0; + pstr->raw_mbs_idx = 0; + pstr->valid_raw_len = 0; + pstr->offsets_needed = 0; + pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF); + if (!pstr->mbs_allocated) + pstr->mbs = (unsigned char *) pstr->raw_mbs; + offset = idx; + } + + if (__glibc_likely (offset != 0)) + { + /* Should the already checked characters be kept? */ + if (__glibc_likely (offset < pstr->valid_raw_len)) + { + /* Yes, move them to the front of the buffer. */ + if (__glibc_unlikely (pstr->offsets_needed)) + { + Idx low = 0, high = pstr->valid_len, mid; + do + { + mid = (high + low) / 2; + if (pstr->offsets[mid] > offset) + high = mid; + else if (pstr->offsets[mid] < offset) + low = mid + 1; + else + break; + } + while (low < high); + if (pstr->offsets[mid] < offset) + ++mid; + pstr->tip_context = re_string_context_at (pstr, mid - 1, + eflags); + /* This can be quite complicated, so handle specially + only the common and easy case where the character with + different length representation of lower and upper + case is present at or after offset. */ + if (pstr->valid_len > offset + && mid == offset && pstr->offsets[mid] == offset) + { + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); + memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; + for (low = 0; low < pstr->valid_len; low++) + pstr->offsets[low] = pstr->offsets[low + offset] - offset; + } + else + { + /* Otherwise, just find out how long the partial multibyte + character at offset is and fill it with WEOF/255. */ + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + while (mid > 0 && pstr->offsets[mid - 1] == offset) + --mid; + while (mid < pstr->valid_len) + if (pstr->wcs[mid] != WEOF) + break; + else + ++mid; + if (mid == pstr->valid_len) + pstr->valid_len = 0; + else + { + pstr->valid_len = pstr->offsets[mid] - offset; + if (pstr->valid_len) + { + for (low = 0; low < pstr->valid_len; ++low) + pstr->wcs[low] = WEOF; + memset (pstr->mbs, 255, pstr->valid_len); + } + } + pstr->valid_raw_len = pstr->valid_len; + } + } + else + { + pstr->tip_context = re_string_context_at (pstr, offset - 1, + eflags); + if (pstr->mb_cur_max > 1) + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); + if (__glibc_unlikely (pstr->mbs_allocated)) + memmove (pstr->mbs, pstr->mbs + offset, + pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; + DEBUG_ASSERT (pstr->valid_len > 0); + } + } + else + { + /* No, skip all characters until IDX. */ + Idx prev_valid_len = pstr->valid_len; + + if (__glibc_unlikely (pstr->offsets_needed)) + { + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + } + pstr->valid_len = 0; + if (pstr->mb_cur_max > 1) + { + Idx wcs_idx; + wint_t wc = WEOF; + + if (pstr->is_utf8) + { + const unsigned char *raw, *p, *end; + + /* Special case UTF-8. Multi-byte chars start with any + byte other than 0x80 - 0xbf. */ + raw = pstr->raw_mbs + pstr->raw_mbs_idx; + end = raw + (offset - pstr->mb_cur_max); + if (end < pstr->raw_mbs) + end = pstr->raw_mbs; + p = raw + offset - 1; +#ifdef _LIBC + /* We know the wchar_t encoding is UCS4, so for the simple + case, ASCII characters, skip the conversion step. */ + if (isascii (*p) && __glibc_likely (pstr->trans == NULL)) + { + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + /* pstr->valid_len = 0; */ + wc = (wchar_t) *p; + } + else +#endif + for (; p >= end; --p) + if ((*p & 0xc0) != 0x80) + { + mbstate_t cur_state; + wchar_t wc2; + Idx mlen = raw + pstr->len - p; + unsigned char buf[6]; + size_t mbclen; + + const unsigned char *pp = p; + if (__glibc_unlikely (pstr->trans != NULL)) + { + int i = mlen < 6 ? mlen : 6; + while (--i >= 0) + buf[i] = pstr->trans[p[i]]; + pp = buf; + } + /* XXX Don't use mbrtowc, we know which conversion + to use (UTF-8 -> UCS4). */ + memset (&cur_state, 0, sizeof (cur_state)); + mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, + &cur_state); + if (raw + offset - p <= mbclen + && mbclen < (size_t) -2) + { + memset (&pstr->cur_state, '\0', + sizeof (mbstate_t)); + pstr->valid_len = mbclen - (raw + offset - p); + wc = wc2; + } + break; + } + } + + if (wc == WEOF) + pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; + if (wc == WEOF) + pstr->tip_context + = re_string_context_at (pstr, prev_valid_len - 1, eflags); + else + pstr->tip_context = ((__glibc_unlikely (pstr->word_ops_used != 0) + && IS_WIDE_WORD_CHAR (wc)) + ? CONTEXT_WORD + : ((IS_WIDE_NEWLINE (wc) + && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + if (__glibc_unlikely (pstr->valid_len)) + { + for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) + pstr->wcs[wcs_idx] = WEOF; + if (pstr->mbs_allocated) + memset (pstr->mbs, 255, pstr->valid_len); + } + pstr->valid_raw_len = pstr->valid_len; + } + else + { + int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; + pstr->valid_raw_len = 0; + if (pstr->trans) + c = pstr->trans[c]; + pstr->tip_context = (bitset_contain (pstr->word_char, c) + ? CONTEXT_WORD + : ((IS_NEWLINE (c) && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + } + if (!__glibc_unlikely (pstr->mbs_allocated)) + pstr->mbs += offset; + } + pstr->raw_mbs_idx = idx; + pstr->len -= offset; + pstr->stop -= offset; + + /* Then build the buffers. */ + if (pstr->mb_cur_max > 1) + { + if (pstr->icase) + { + reg_errcode_t ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + else + build_wcs_buffer (pstr); + } + else + if (__glibc_unlikely (pstr->mbs_allocated)) + { + if (pstr->icase) + build_upper_buffer (pstr); + else if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + else + pstr->valid_len = pstr->len; + + pstr->cur_idx = 0; + return REG_NOERROR; +} + +static unsigned char +__attribute__ ((pure)) +re_string_peek_byte_case (const re_string_t *pstr, Idx idx) +{ + int ch; + Idx off; + + /* Handle the common (easiest) cases first. */ + if (__glibc_likely (!pstr->mbs_allocated)) + return re_string_peek_byte (pstr, idx); + + if (pstr->mb_cur_max > 1 + && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) + return re_string_peek_byte (pstr, idx); + + off = pstr->cur_idx + idx; + if (pstr->offsets_needed) + off = pstr->offsets[off]; + + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + + /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I + this function returns CAPITAL LETTER I instead of first byte of + DOTLESS SMALL LETTER I. The latter would confuse the parser, + since peek_byte_case doesn't advance cur_idx in any way. */ + if (pstr->offsets_needed && !isascii (ch)) + return re_string_peek_byte (pstr, idx); + + return ch; +} + +static unsigned char +re_string_fetch_byte_case (re_string_t *pstr) +{ + if (__glibc_likely (!pstr->mbs_allocated)) + return re_string_fetch_byte (pstr); + + if (pstr->offsets_needed) + { + Idx off; + int ch; + + /* For tr_TR.UTF-8 [[:islower:]] there is + [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip + in that case the whole multi-byte character and return + the original letter. On the other side, with + [[: DOTLESS SMALL LETTER I return [[:I, as doing + anything else would complicate things too much. */ + + if (!re_string_first_byte (pstr, pstr->cur_idx)) + return re_string_fetch_byte (pstr); + + off = pstr->offsets[pstr->cur_idx]; + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + + if (! isascii (ch)) + return re_string_fetch_byte (pstr); + + re_string_skip_bytes (pstr, + re_string_char_size_at (pstr, pstr->cur_idx)); + return ch; + } + + return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; +} + +static void +re_string_destruct (re_string_t *pstr) +{ + re_free (pstr->wcs); + re_free (pstr->offsets); + if (pstr->mbs_allocated) + re_free (pstr->mbs); +} + +/* Return the context at IDX in INPUT. */ + +static unsigned int +re_string_context_at (const re_string_t *input, Idx idx, int eflags) +{ + int c; + if (__glibc_unlikely (idx < 0)) + /* In this case, we use the value stored in input->tip_context, + since we can't know the character in input->mbs[-1] here. */ + return input->tip_context; + if (__glibc_unlikely (idx == input->len)) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); + if (input->mb_cur_max > 1) + { + wint_t wc; + Idx wc_idx = idx; + while(input->wcs[wc_idx] == WEOF) + { + DEBUG_ASSERT (wc_idx >= 0); + --wc_idx; + if (wc_idx < 0) + return input->tip_context; + } + wc = input->wcs[wc_idx]; + if (__glibc_unlikely (input->word_ops_used != 0) + && IS_WIDE_WORD_CHAR (wc)) + return CONTEXT_WORD; + return (IS_WIDE_NEWLINE (wc) && input->newline_anchor + ? CONTEXT_NEWLINE : 0); + } + else + { + c = re_string_byte_at (input, idx); + if (bitset_contain (input->word_char, c)) + return CONTEXT_WORD; + return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; + } +} + +/* Functions for set operation. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_alloc (re_node_set *set, Idx size) +{ + set->alloc = size; + set->nelem = 0; + set->elems = re_malloc (Idx, size); + if (__glibc_unlikely (set->elems == NULL) + && (MALLOC_0_IS_NONNULL || size != 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_1 (re_node_set *set, Idx elem) +{ + set->alloc = 1; + set->nelem = 1; + set->elems = re_malloc (Idx, 1); + if (__glibc_unlikely (set->elems == NULL)) + { + set->alloc = set->nelem = 0; + return REG_ESPACE; + } + set->elems[0] = elem; + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) +{ + set->alloc = 2; + set->elems = re_malloc (Idx, 2); + if (__glibc_unlikely (set->elems == NULL)) + return REG_ESPACE; + if (elem1 == elem2) + { + set->nelem = 1; + set->elems[0] = elem1; + } + else + { + set->nelem = 2; + if (elem1 < elem2) + { + set->elems[0] = elem1; + set->elems[1] = elem2; + } + else + { + set->elems[0] = elem2; + set->elems[1] = elem1; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_copy (re_node_set *dest, const re_node_set *src) +{ + dest->nelem = src->nelem; + if (src->nelem > 0) + { + dest->alloc = dest->nelem; + dest->elems = re_malloc (Idx, dest->alloc); + if (__glibc_unlikely (dest->elems == NULL)) + { + dest->alloc = dest->nelem = 0; + return REG_ESPACE; + } + memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); + } + else + re_node_set_init_empty (dest); + return REG_NOERROR; +} + +/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. + Note: We assume dest->elems is NULL, when dest->alloc is 0. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + Idx i1, i2, is, id, delta, sbase; + if (src1->nelem == 0 || src2->nelem == 0) + return REG_NOERROR; + + /* We need dest->nelem + 2 * elems_in_intersection; this is a + conservative estimate. */ + if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) + { + Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; + Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); + if (__glibc_unlikely (new_elems == NULL)) + return REG_ESPACE; + dest->elems = new_elems; + dest->alloc = new_alloc; + } + + /* Find the items in the intersection of SRC1 and SRC2, and copy + into the top of DEST those that are not already in DEST itself. */ + sbase = dest->nelem + src1->nelem + src2->nelem; + i1 = src1->nelem - 1; + i2 = src2->nelem - 1; + id = dest->nelem - 1; + for (;;) + { + if (src1->elems[i1] == src2->elems[i2]) + { + /* Try to find the item in DEST. Maybe we could binary search? */ + while (id >= 0 && dest->elems[id] > src1->elems[i1]) + --id; + + if (id < 0 || dest->elems[id] != src1->elems[i1]) + dest->elems[--sbase] = src1->elems[i1]; + + if (--i1 < 0 || --i2 < 0) + break; + } + + /* Lower the highest of the two items. */ + else if (src1->elems[i1] < src2->elems[i2]) + { + if (--i2 < 0) + break; + } + else + { + if (--i1 < 0) + break; + } + } + + id = dest->nelem - 1; + is = dest->nelem + src1->nelem + src2->nelem - 1; + delta = is - sbase + 1; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place; this is more or + less the same loop that is in re_node_set_merge. */ + dest->nelem += delta; + if (delta > 0 && id >= 0) + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + break; + } + } + + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); + + return REG_NOERROR; +} + +/* Calculate the union set of the sets SRC1 and SRC2. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_init_union (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + Idx i1, i2, id; + if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) + { + dest->alloc = src1->nelem + src2->nelem; + dest->elems = re_malloc (Idx, dest->alloc); + if (__glibc_unlikely (dest->elems == NULL)) + return REG_ESPACE; + } + else + { + if (src1 != NULL && src1->nelem > 0) + return re_node_set_init_copy (dest, src1); + else if (src2 != NULL && src2->nelem > 0) + return re_node_set_init_copy (dest, src2); + else + re_node_set_init_empty (dest); + return REG_NOERROR; + } + for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) + { + if (src1->elems[i1] > src2->elems[i2]) + { + dest->elems[id++] = src2->elems[i2++]; + continue; + } + if (src1->elems[i1] == src2->elems[i2]) + ++i2; + dest->elems[id++] = src1->elems[i1++]; + } + if (i1 < src1->nelem) + { + memcpy (dest->elems + id, src1->elems + i1, + (src1->nelem - i1) * sizeof (Idx)); + id += src1->nelem - i1; + } + else if (i2 < src2->nelem) + { + memcpy (dest->elems + id, src2->elems + i2, + (src2->nelem - i2) * sizeof (Idx)); + id += src2->nelem - i2; + } + dest->nelem = id; + return REG_NOERROR; +} + +/* Calculate the union set of the sets DEST and SRC. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_node_set_merge (re_node_set *dest, const re_node_set *src) +{ + Idx is, id, sbase, delta; + if (src == NULL || src->nelem == 0) + return REG_NOERROR; + if (dest->alloc < 2 * src->nelem + dest->nelem) + { + Idx new_alloc = 2 * (src->nelem + dest->alloc); + Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); + if (__glibc_unlikely (new_buffer == NULL)) + return REG_ESPACE; + dest->elems = new_buffer; + dest->alloc = new_alloc; + } + + if (__glibc_unlikely (dest->nelem == 0)) + { + /* Although we already guaranteed above that dest->alloc != 0 and + therefore dest->elems != NULL, add a debug assertion to pacify + GCC 11.2.1's -fanalyzer. */ + DEBUG_ASSERT (dest->elems); + dest->nelem = src->nelem; + memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); + return REG_NOERROR; + } + + /* Copy into the top of DEST the items of SRC that are not + found in DEST. Maybe we could binary search in DEST? */ + for (sbase = dest->nelem + 2 * src->nelem, + is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) + { + if (dest->elems[id] == src->elems[is]) + is--, id--; + else if (dest->elems[id] < src->elems[is]) + dest->elems[--sbase] = src->elems[is--]; + else /* if (dest->elems[id] > src->elems[is]) */ + --id; + } + + if (is >= 0) + { + /* If DEST is exhausted, the remaining items of SRC must be unique. */ + sbase -= is + 1; + memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); + } + + id = dest->nelem - 1; + is = dest->nelem + 2 * src->nelem - 1; + delta = is - sbase + 1; + if (delta == 0) + return REG_NOERROR; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place. */ + dest->nelem += delta; + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + { + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, + delta * sizeof (Idx)); + break; + } + } + } + + return REG_NOERROR; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have ELEM. + Return true if successful. */ + +static bool +__attribute_warn_unused_result__ +re_node_set_insert (re_node_set *set, Idx elem) +{ + Idx idx; + /* In case the set is empty. */ + if (set->alloc == 0) + return __glibc_likely (re_node_set_init_1 (set, elem) == REG_NOERROR); + + if (__glibc_unlikely (set->nelem) == 0) + { + /* Although we already guaranteed above that set->alloc != 0 and + therefore set->elems != NULL, add a debug assertion to pacify + GCC 11.2 -fanalyzer. */ + DEBUG_ASSERT (set->elems); + set->elems[0] = elem; + ++set->nelem; + return true; + } + + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + Idx *new_elems; + set->alloc = set->alloc * 2; + new_elems = re_realloc (set->elems, Idx, set->alloc); + if (__glibc_unlikely (new_elems == NULL)) + return false; + set->elems = new_elems; + } + + /* Move the elements which follows the new element. Test the + first element separately to skip a check in the inner loop. */ + if (elem < set->elems[0]) + { + for (idx = set->nelem; idx > 0; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + else + { + for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) + set->elems[idx] = set->elems[idx - 1]; + DEBUG_ASSERT (set->elems[idx - 1] < elem); + } + + /* Insert the new element. */ + set->elems[idx] = elem; + ++set->nelem; + return true; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have any element greater than or equal to ELEM. + Return true if successful. */ + +static bool +__attribute_warn_unused_result__ +re_node_set_insert_last (re_node_set *set, Idx elem) +{ + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + Idx *new_elems; + set->alloc = (set->alloc + 1) * 2; + new_elems = re_realloc (set->elems, Idx, set->alloc); + if (__glibc_unlikely (new_elems == NULL)) + return false; + set->elems = new_elems; + } + + /* Insert the new element. */ + set->elems[set->nelem++] = elem; + return true; +} + +/* Compare two node sets SET1 and SET2. + Return true if SET1 and SET2 are equivalent. */ + +static bool +__attribute__ ((pure)) +re_node_set_compare (const re_node_set *set1, const re_node_set *set2) +{ + Idx i; + if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) + return false; + for (i = set1->nelem ; --i >= 0 ; ) + if (set1->elems[i] != set2->elems[i]) + return false; + return true; +} + +/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ + +static Idx +__attribute__ ((pure)) +re_node_set_contains (const re_node_set *set, Idx elem) +{ + __re_size_t idx, right, mid; + if (set->nelem <= 0) + return 0; + + /* Binary search the element. */ + idx = 0; + right = set->nelem - 1; + while (idx < right) + { + mid = (idx + right) / 2; + if (set->elems[mid] < elem) + idx = mid + 1; + else + right = mid; + } + return set->elems[idx] == elem ? idx + 1 : 0; +} + +static void +re_node_set_remove_at (re_node_set *set, Idx idx) +{ + if (idx < 0 || idx >= set->nelem) + return; + --set->nelem; + for (; idx < set->nelem; idx++) + set->elems[idx] = set->elems[idx + 1]; +} + + +/* Add the token TOKEN to dfa->nodes, and return the index of the token. + Or return -1 if an error occurred. */ + +static Idx +re_dfa_add_node (re_dfa_t *dfa, re_token_t token) +{ + if (__glibc_unlikely (dfa->nodes_len >= dfa->nodes_alloc)) + { + size_t new_nodes_alloc = dfa->nodes_alloc * 2; + Idx *new_nexts, *new_indices; + re_node_set *new_edests, *new_eclosures; + re_token_t *new_nodes; + + /* Avoid overflows in realloc. */ + const size_t max_object_size = MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + sizeof (Idx))); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) + < new_nodes_alloc)) + return -1; + + new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); + if (__glibc_unlikely (new_nodes == NULL)) + return -1; + dfa->nodes = new_nodes; + dfa->nodes_alloc = new_nodes_alloc; + new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); + if (new_nexts != NULL) + dfa->nexts = new_nexts; + new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); + if (new_indices != NULL) + dfa->org_indices = new_indices; + new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); + if (new_edests != NULL) + dfa->edests = new_edests; + new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); + if (new_eclosures != NULL) + dfa->eclosures = new_eclosures; + if (__glibc_unlikely (new_nexts == NULL || new_indices == NULL + || new_edests == NULL || new_eclosures == NULL)) + return -1; + } + dfa->nodes[dfa->nodes_len] = token; + dfa->nodes[dfa->nodes_len].constraint = 0; + dfa->nodes[dfa->nodes_len].accept_mb = + ((token.type == OP_PERIOD && dfa->mb_cur_max > 1) + || token.type == COMPLEX_BRACKET); + dfa->nexts[dfa->nodes_len] = -1; + re_node_set_init_empty (dfa->edests + dfa->nodes_len); + re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); + return dfa->nodes_len++; +} + +static re_hashval_t +calc_state_hash (const re_node_set *nodes, unsigned int context) +{ + re_hashval_t hash = nodes->nelem + context; + Idx i; + for (i = 0 ; i < nodes->nelem ; i++) + hash += nodes->elems[i]; + return hash; +} + +/* Search for the state whose node_set is equivalent to NODES. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes) +{ + re_hashval_t hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + Idx i; +#if defined GCC_LINT || defined lint + /* Suppress bogus uninitialized-variable warnings. */ + *err = REG_NOERROR; +#endif + if (__glibc_unlikely (nodes->nelem == 0)) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, 0); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (hash != state->hash) + continue; + if (re_node_set_compare (&state->nodes, nodes)) + return state; + } + + /* There are no appropriate state in the dfa, create the new one. */ + new_state = create_ci_newstate (dfa, nodes, hash); + if (__glibc_unlikely (new_state == NULL)) + *err = REG_ESPACE; + + return new_state; +} + +/* Search for the state whose node_set is equivalent to NODES and + whose context is equivalent to CONTEXT. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes, unsigned int context) +{ + re_hashval_t hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + Idx i; +#if defined GCC_LINT || defined lint + /* Suppress bogus uninitialized-variable warnings. */ + *err = REG_NOERROR; +#endif + if (nodes->nelem == 0) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, context); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (state->hash == hash + && state->context == context + && re_node_set_compare (state->entrance_nodes, nodes)) + return state; + } + /* There are no appropriate state in 'dfa', create the new one. */ + new_state = create_cd_newstate (dfa, nodes, context, hash); + if (__glibc_unlikely (new_state == NULL)) + *err = REG_ESPACE; + + return new_state; +} + +/* Finish initialization of the new state NEWSTATE, and using its hash value + HASH put in the appropriate bucket of DFA's state table. Return value + indicates the error code if failed. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, + re_hashval_t hash) +{ + struct re_state_table_entry *spot; + reg_errcode_t err; + Idx i; + + newstate->hash = hash; + err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + for (i = 0; i < newstate->nodes.nelem; i++) + { + Idx elem = newstate->nodes.elems[i]; + if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) + if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) + return REG_ESPACE; + } + + spot = dfa->state_table + (hash & dfa->state_hash_mask); + if (__glibc_unlikely (spot->alloc <= spot->num)) + { + Idx new_alloc = 2 * spot->num + 2; + re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, + new_alloc); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + spot->array = new_array; + spot->alloc = new_alloc; + } + spot->array[spot->num++] = newstate; + return REG_NOERROR; +} + +static void +free_state (re_dfastate_t *state) +{ + re_node_set_free (&state->non_eps_nodes); + re_node_set_free (&state->inveclosure); + if (state->entrance_nodes != &state->nodes) + { + re_node_set_free (state->entrance_nodes); + re_free (state->entrance_nodes); + } + re_node_set_free (&state->nodes); + re_free (state->word_trtable); + re_free (state->trtable); + re_free (state); +} + +/* Create the new state which is independent of contexts. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + re_hashval_t hash) +{ + Idx i; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (__glibc_unlikely (newstate == NULL)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_free (newstate); + return NULL; + } + + newstate->entrance_nodes = &newstate->nodes; + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + if (type == CHARACTER && !node->constraint) + continue; + newstate->accept_mb |= node->accept_mb; + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR || node->constraint) + newstate->has_constraint = 1; + } + err = register_state (dfa, newstate, hash); + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} + +/* Create the new state which is depend on the context CONTEXT. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int context, re_hashval_t hash) +{ + Idx i, nctx_nodes = 0; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); + if (__glibc_unlikely (newstate == NULL)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_free (newstate); + return NULL; + } + + newstate->context = context; + newstate->entrance_nodes = &newstate->nodes; + + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + if (type == CHARACTER && !constraint) + continue; + newstate->accept_mb |= node->accept_mb; + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + + if (constraint) + { + if (newstate->entrance_nodes == &newstate->nodes) + { + re_node_set *entrance_nodes = re_malloc (re_node_set, 1); + if (__glibc_unlikely (entrance_nodes == NULL)) + { + free_state (newstate); + return NULL; + } + newstate->entrance_nodes = entrance_nodes; + if (re_node_set_init_copy (newstate->entrance_nodes, nodes) + != REG_NOERROR) + { + free_state (newstate); + return NULL; + } + nctx_nodes = 0; + newstate->has_constraint = 1; + } + + if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) + { + re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); + ++nctx_nodes; + } + } + } + err = register_state (dfa, newstate, hash); + if (__glibc_unlikely (err != REG_NOERROR)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} diff --git a/cross/lib/regex_internal.h b/cross/lib/regex_internal.h new file mode 100644 index 00000000000..149ec2e868a --- /dev/null +++ b/cross/lib/regex_internal.h @@ -0,0 +1,834 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _REGEX_INTERNAL_H +#define _REGEX_INTERNAL_H 1 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifndef _LIBC +# include +#endif + +#include +#include + +#if defined DEBUG && DEBUG != 0 +# include +# define DEBUG_ASSERT(x) assert (x) +#else +# define DEBUG_ASSERT(x) assume (x) +#endif + +#ifdef _LIBC +# include +# define lock_define(name) __libc_lock_define (, name) +# define lock_init(lock) (__libc_lock_init (lock), 0) +# define lock_fini(lock) ((void) 0) +# define lock_lock(lock) __libc_lock_lock (lock) +# define lock_unlock(lock) __libc_lock_unlock (lock) +#elif defined GNULIB_LOCK && !defined GNULIB_REGEX_SINGLE_THREAD +# include "glthread/lock.h" +# define lock_define(name) gl_lock_define (, name) +# define lock_init(lock) glthread_lock_init (&(lock)) +# define lock_fini(lock) glthread_lock_destroy (&(lock)) +# define lock_lock(lock) glthread_lock_lock (&(lock)) +# define lock_unlock(lock) glthread_lock_unlock (&(lock)) +#elif defined GNULIB_PTHREAD && !defined GNULIB_REGEX_SINGLE_THREAD +# include +# define lock_define(name) pthread_mutex_t name; +# define lock_init(lock) pthread_mutex_init (&(lock), 0) +# define lock_fini(lock) pthread_mutex_destroy (&(lock)) +# define lock_lock(lock) pthread_mutex_lock (&(lock)) +# define lock_unlock(lock) pthread_mutex_unlock (&(lock)) +#else +# define lock_define(name) +# define lock_init(lock) 0 +# define lock_fini(lock) ((void) 0) + /* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */ +# define lock_lock(lock) ((void) dfa) +# define lock_unlock(lock) ((void) 0) +#endif + +/* In case that the system doesn't have isblank(). */ +#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) +# define isblank(ch) ((ch) == ' ' || (ch) == '\t') +#endif + +/* regex code assumes isascii has its usual numeric meaning, + even if the portable character set uses EBCDIC encoding, + and even if wint_t is wider than int. */ +#ifndef _LIBC +# undef isascii +# define isascii(c) (((c) & ~0x7f) == 0) +#endif + +#ifdef _LIBC +# ifndef _RE_DEFINE_LOCALE_FUNCTIONS +# define _RE_DEFINE_LOCALE_FUNCTIONS 1 +# include +# include +# endif +#endif + +/* This is for other GNU distributions with internationalized messages. */ +#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC +# include +# ifdef _LIBC +# undef gettext +# define gettext(msgid) \ + __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES) +# endif +#else +# undef gettext +# define gettext(msgid) (msgid) +#endif + +#ifndef gettext_noop +/* This define is so xgettext can find the internationalizable + strings. */ +# define gettext_noop(String) String +#endif + +/* Number of ASCII characters. */ +#define ASCII_CHARS 0x80 + +/* Number of single byte characters. */ +#define SBC_MAX (UCHAR_MAX + 1) + +#define COLL_ELEM_LEN_MAX 8 + +/* The character which represents newline. */ +#define NEWLINE_CHAR '\n' +#define WIDE_NEWLINE_CHAR L'\n' + +/* Rename to standard API for using out of glibc. */ +#ifndef _LIBC +# undef __wctype +# undef __iswalnum +# undef __iswctype +# undef __towlower +# undef __towupper +# define __wctype wctype +# define __iswalnum iswalnum +# define __iswctype iswctype +# define __towlower towlower +# define __towupper towupper +# define __btowc btowc +# define __mbrtowc mbrtowc +# define __wcrtomb wcrtomb +# define __regfree regfree +#endif /* not _LIBC */ + +/* Types related to integers. Unless protected by #ifdef _LIBC, the + regex code should avoid exact-width types like int32_t and uint64_t + as some non-GCC platforms lack them, an issue when this code is + used in Gnulib. */ + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif +#ifndef ULONG_WIDTH +# define ULONG_WIDTH REGEX_UINTEGER_WIDTH (ULONG_MAX) +/* The number of usable bits in an unsigned integer type with maximum + value MAX, as an int expression suitable in #if. Cover all known + practical hosts. This implementation exploits the fact that MAX is + 1 less than a power of 2, and merely counts the number of 1 bits in + MAX; "COBn" means "count the number of 1 bits in the low-order n bits". */ +# define REGEX_UINTEGER_WIDTH(max) REGEX_COB128 (max) +# define REGEX_COB128(n) (REGEX_COB64 ((n) >> 31 >> 31 >> 2) + REGEX_COB64 (n)) +# define REGEX_COB64(n) (REGEX_COB32 ((n) >> 31 >> 1) + REGEX_COB32 (n)) +# define REGEX_COB32(n) (REGEX_COB16 ((n) >> 16) + REGEX_COB16 (n)) +# define REGEX_COB16(n) (REGEX_COB8 ((n) >> 8) + REGEX_COB8 (n)) +# define REGEX_COB8(n) (REGEX_COB4 ((n) >> 4) + REGEX_COB4 (n)) +# define REGEX_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + ((n) & 1)) +# if ULONG_MAX / 2 + 1 != 1ul << (ULONG_WIDTH - 1) +# error "ULONG_MAX out of range" +# endif +#endif + +/* The type of indexes into strings. This is signed, not size_t, + since the API requires indexes to fit in regoff_t anyway, and using + signed integers makes the code a bit smaller and presumably faster. + The traditional GNU regex implementation uses int for indexes. + The POSIX-compatible implementation uses a possibly-wider type. + The name 'Idx' is three letters to minimize the hassle of + reindenting a lot of regex code that formerly used 'int'. */ +typedef regoff_t Idx; +#ifdef _REGEX_LARGE_OFFSETS +# define IDX_MAX SSIZE_MAX +#else +# define IDX_MAX INT_MAX +#endif + +/* A hash value, suitable for computing hash tables. */ +typedef __re_size_t re_hashval_t; + +/* An integer used to represent a set of bits. It must be unsigned, + and must be at least as wide as unsigned int. */ +typedef unsigned long int bitset_word_t; +/* All bits set in a bitset_word_t. */ +#define BITSET_WORD_MAX ULONG_MAX +/* Number of bits in a bitset_word_t. */ +#define BITSET_WORD_BITS ULONG_WIDTH + +/* Number of bitset_word_t values in a bitset_t. */ +#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) + +typedef bitset_word_t bitset_t[BITSET_WORDS]; +typedef bitset_word_t *re_bitset_ptr_t; +typedef const bitset_word_t *re_const_bitset_ptr_t; + +#define PREV_WORD_CONSTRAINT 0x0001 +#define PREV_NOTWORD_CONSTRAINT 0x0002 +#define NEXT_WORD_CONSTRAINT 0x0004 +#define NEXT_NOTWORD_CONSTRAINT 0x0008 +#define PREV_NEWLINE_CONSTRAINT 0x0010 +#define NEXT_NEWLINE_CONSTRAINT 0x0020 +#define PREV_BEGBUF_CONSTRAINT 0x0040 +#define NEXT_ENDBUF_CONSTRAINT 0x0080 +#define WORD_DELIM_CONSTRAINT 0x0100 +#define NOT_WORD_DELIM_CONSTRAINT 0x0200 + +typedef enum +{ + INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + LINE_FIRST = PREV_NEWLINE_CONSTRAINT, + LINE_LAST = NEXT_NEWLINE_CONSTRAINT, + BUF_FIRST = PREV_BEGBUF_CONSTRAINT, + BUF_LAST = NEXT_ENDBUF_CONSTRAINT, + WORD_DELIM = WORD_DELIM_CONSTRAINT, + NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT +} re_context_type; + +typedef struct +{ + Idx alloc; + Idx nelem; + Idx *elems; +} re_node_set; + +typedef enum +{ + NON_TYPE = 0, + + /* Node type, These are used by token, node, tree. */ + CHARACTER = 1, + END_OF_RE = 2, + SIMPLE_BRACKET = 3, + OP_BACK_REF = 4, + OP_PERIOD = 5, + COMPLEX_BRACKET = 6, + OP_UTF8_PERIOD = 7, + + /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used + when the debugger shows values of this enum type. */ +#define EPSILON_BIT 8 + OP_OPEN_SUBEXP = EPSILON_BIT | 0, + OP_CLOSE_SUBEXP = EPSILON_BIT | 1, + OP_ALT = EPSILON_BIT | 2, + OP_DUP_ASTERISK = EPSILON_BIT | 3, + ANCHOR = EPSILON_BIT | 4, + + /* Tree type, these are used only by tree. */ + CONCAT = 16, + SUBEXP = 17, + + /* Token type, these are used only by token. */ + OP_DUP_PLUS = 18, + OP_DUP_QUESTION, + OP_OPEN_BRACKET, + OP_CLOSE_BRACKET, + OP_CHARSET_RANGE, + OP_OPEN_DUP_NUM, + OP_CLOSE_DUP_NUM, + OP_NON_MATCH_LIST, + OP_OPEN_COLL_ELEM, + OP_CLOSE_COLL_ELEM, + OP_OPEN_EQUIV_CLASS, + OP_CLOSE_EQUIV_CLASS, + OP_OPEN_CHAR_CLASS, + OP_CLOSE_CHAR_CLASS, + OP_WORD, + OP_NOTWORD, + OP_SPACE, + OP_NOTSPACE, + BACK_SLASH + +} re_token_type_t; + +typedef struct +{ + /* Multibyte characters. */ + wchar_t *mbchars; + +#ifdef _LIBC + /* Collating symbols. */ + int32_t *coll_syms; +#endif + +#ifdef _LIBC + /* Equivalence classes. */ + int32_t *equiv_classes; +#endif + + /* Range expressions. */ +#ifdef _LIBC + uint32_t *range_starts; + uint32_t *range_ends; +#else + wchar_t *range_starts; + wchar_t *range_ends; +#endif + + /* Character classes. */ + wctype_t *char_classes; + + /* If this character set is the non-matching list. */ + unsigned int non_match : 1; + + /* # of multibyte characters. */ + Idx nmbchars; + + /* # of collating symbols. */ + Idx ncoll_syms; + + /* # of equivalence classes. */ + Idx nequiv_classes; + + /* # of range expressions. */ + Idx nranges; + + /* # of character classes. */ + Idx nchar_classes; +} re_charset_t; + +typedef struct +{ + union + { + unsigned char c; /* for CHARACTER */ + re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ + re_charset_t *mbcset; /* for COMPLEX_BRACKET */ + Idx idx; /* for BACK_REF */ + re_context_type ctx_type; /* for ANCHOR */ + } opr; +#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__ + re_token_type_t type : 8; +#else + re_token_type_t type; +#endif + unsigned int constraint : 10; /* context constraint */ + unsigned int duplicated : 1; + unsigned int opt_subexp : 1; + unsigned int accept_mb : 1; + /* These 2 bits can be moved into the union if needed (e.g. if running out + of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ + unsigned int mb_partial : 1; + unsigned int word_char : 1; +} re_token_t; + +#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) + +struct re_string_t +{ + /* Indicate the raw buffer which is the original string passed as an + argument of regexec(), re_search(), etc.. */ + const unsigned char *raw_mbs; + /* Store the multibyte string. In case of "case insensitive mode" like + REG_ICASE, upper cases of the string are stored, otherwise MBS points + the same address that RAW_MBS points. */ + unsigned char *mbs; + /* Store the wide character string which is corresponding to MBS. */ + wint_t *wcs; + Idx *offsets; + mbstate_t cur_state; + /* Index in RAW_MBS. Each character mbs[i] corresponds to + raw_mbs[raw_mbs_idx + i]. */ + Idx raw_mbs_idx; + /* The length of the valid characters in the buffers. */ + Idx valid_len; + /* The corresponding number of bytes in raw_mbs array. */ + Idx valid_raw_len; + /* The length of the buffers MBS and WCS. */ + Idx bufs_len; + /* The index in MBS, which is updated by re_string_fetch_byte. */ + Idx cur_idx; + /* length of RAW_MBS array. */ + Idx raw_len; + /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ + Idx len; + /* End of the buffer may be shorter than its length in the cases such + as re_match_2, re_search_2. Then, we use STOP for end of the buffer + instead of LEN. */ + Idx raw_stop; + /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ + Idx stop; + + /* The context of mbs[0]. We store the context independently, since + the context of mbs[0] may be different from raw_mbs[0], which is + the beginning of the input string. */ + unsigned int tip_context; + /* The translation passed as a part of an argument of re_compile_pattern. */ + RE_TRANSLATE_TYPE trans; + /* Copy of re_dfa_t's word_char. */ + re_const_bitset_ptr_t word_char; + /* true if REG_ICASE. */ + unsigned char icase; + unsigned char is_utf8; + unsigned char map_notascii; + unsigned char mbs_allocated; + unsigned char offsets_needed; + unsigned char newline_anchor; + unsigned char word_ops_used; + int mb_cur_max; +}; +typedef struct re_string_t re_string_t; + + +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + +#ifndef _LIBC +# define IS_IN(libc) false +#endif + +#define re_string_peek_byte(pstr, offset) \ + ((pstr)->mbs[(pstr)->cur_idx + offset]) +#define re_string_fetch_byte(pstr) \ + ((pstr)->mbs[(pstr)->cur_idx++]) +#define re_string_first_byte(pstr, idx) \ + ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) +#define re_string_is_single_byte_char(pstr, idx) \ + ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ + || (pstr)->wcs[(idx) + 1] != WEOF)) +#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) +#define re_string_cur_idx(pstr) ((pstr)->cur_idx) +#define re_string_get_buffer(pstr) ((pstr)->mbs) +#define re_string_length(pstr) ((pstr)->len) +#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) +#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) +#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) + +#ifdef _LIBC +# define MALLOC_0_IS_NONNULL 1 +#elif !defined MALLOC_0_IS_NONNULL +# define MALLOC_0_IS_NONNULL 0 +#endif + +#ifndef MAX +# define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +#define re_free(p) free (p) + +struct bin_tree_t +{ + struct bin_tree_t *parent; + struct bin_tree_t *left; + struct bin_tree_t *right; + struct bin_tree_t *first; + struct bin_tree_t *next; + + re_token_t token; + + /* 'node_idx' is the index in dfa->nodes, if 'type' == 0. + Otherwise 'type' indicate the type of this node. */ + Idx node_idx; +}; +typedef struct bin_tree_t bin_tree_t; + +#define BIN_TREE_STORAGE_SIZE \ + ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) + +struct bin_tree_storage_t +{ + struct bin_tree_storage_t *next; + bin_tree_t data[BIN_TREE_STORAGE_SIZE]; +}; +typedef struct bin_tree_storage_t bin_tree_storage_t; + +#define CONTEXT_WORD 1 +#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) +#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) +#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) + +#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) +#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) +#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) +#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) +#define IS_ORDINARY_CONTEXT(c) ((c) == 0) + +#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') +#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) +#define IS_WIDE_WORD_CHAR(ch) (__iswalnum (ch) || (ch) == L'_') +#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) + +#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ + ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ + || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) + +#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ + ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ + || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) + +struct re_dfastate_t +{ + re_hashval_t hash; + re_node_set nodes; + re_node_set non_eps_nodes; + re_node_set inveclosure; + re_node_set *entrance_nodes; + struct re_dfastate_t **trtable, **word_trtable; + unsigned int context : 4; + unsigned int halt : 1; + /* If this state can accept "multi byte". + Note that we refer to multibyte characters, and multi character + collating elements as "multi byte". */ + unsigned int accept_mb : 1; + /* If this state has backreference node(s). */ + unsigned int has_backref : 1; + unsigned int has_constraint : 1; +}; +typedef struct re_dfastate_t re_dfastate_t; + +struct re_state_table_entry +{ + Idx num; + Idx alloc; + re_dfastate_t **array; +}; + +/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ + +typedef struct +{ + Idx next_idx; + Idx alloc; + re_dfastate_t **array; +} state_array_t; + +/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ + +typedef struct +{ + Idx node; + Idx str_idx; /* The position NODE match at. */ + state_array_t path; +} re_sub_match_last_t; + +/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. + And information about the node, whose type is OP_CLOSE_SUBEXP, + corresponding to NODE is stored in LASTS. */ + +typedef struct +{ + Idx str_idx; + Idx node; + state_array_t *path; + Idx alasts; /* Allocation size of LASTS. */ + Idx nlasts; /* The number of LASTS. */ + re_sub_match_last_t **lasts; +} re_sub_match_top_t; + +struct re_backref_cache_entry +{ + Idx node; + Idx str_idx; + Idx subexp_from; + Idx subexp_to; + bitset_word_t eps_reachable_subexps_map; + char more; +}; + +typedef struct +{ + /* The string object corresponding to the input string. */ + re_string_t input; + const re_dfa_t *const dfa; + /* EFLAGS of the argument of regexec. */ + int eflags; + /* Where the matching ends. */ + Idx match_last; + Idx last_node; + /* The state log used by the matcher. */ + re_dfastate_t **state_log; + Idx state_log_top; + /* Back reference cache. */ + Idx nbkref_ents; + Idx abkref_ents; + struct re_backref_cache_entry *bkref_ents; + int max_mb_elem_len; + Idx nsub_tops; + Idx asub_tops; + re_sub_match_top_t **sub_tops; +} re_match_context_t; + +typedef struct +{ + re_dfastate_t **sifted_states; + re_dfastate_t **limited_states; + Idx last_node; + Idx last_str_idx; + re_node_set limits; +} re_sift_context_t; + +struct re_fail_stack_ent_t +{ + Idx idx; + Idx node; + regmatch_t *regs; + re_node_set eps_via_nodes; +}; + +struct re_fail_stack_t +{ + Idx num; + Idx alloc; + struct re_fail_stack_ent_t *stack; +}; + +struct re_dfa_t +{ + re_token_t *nodes; + size_t nodes_alloc; + size_t nodes_len; + Idx *nexts; + Idx *org_indices; + re_node_set *edests; + re_node_set *eclosures; + re_node_set *inveclosures; + struct re_state_table_entry *state_table; + re_dfastate_t *init_state; + re_dfastate_t *init_state_word; + re_dfastate_t *init_state_nl; + re_dfastate_t *init_state_begbuf; + bin_tree_t *str_tree; + bin_tree_storage_t *str_tree_storage; + re_bitset_ptr_t sb_char; + int str_tree_storage_idx; + + /* number of subexpressions 're_nsub' is in regex_t. */ + re_hashval_t state_hash_mask; + Idx init_node; + Idx nbackref; /* The number of backreference in this dfa. */ + + /* Bitmap expressing which backreference is used. */ + bitset_word_t used_bkref_map; + bitset_word_t completed_bkref_map; + + unsigned int has_plural_match : 1; + /* If this dfa has "multibyte node", which is a backreference or + a node which can accept multibyte character or multi character + collating element. */ + unsigned int has_mb_node : 1; + unsigned int is_utf8 : 1; + unsigned int map_notascii : 1; + unsigned int word_ops_used : 1; + int mb_cur_max; + bitset_t word_char; + reg_syntax_t syntax; + Idx *subexp_map; +#ifdef DEBUG + char* re_str; +#endif + lock_define (lock) +}; + +#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) +#define re_node_set_remove(set,id) \ + (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) +#define re_node_set_empty(p) ((p)->nelem = 0) +#define re_node_set_free(set) re_free ((set)->elems) + + +typedef enum +{ + SB_CHAR, + MB_CHAR, + EQUIV_CLASS, + COLL_SYM, + CHAR_CLASS +} bracket_elem_type; + +typedef struct +{ + bracket_elem_type type; + union + { + unsigned char ch; + unsigned char *name; + wchar_t wch; + } opr; +} bracket_elem_t; + + +/* Functions for bitset_t operation. */ + +static inline void +bitset_set (bitset_t set, Idx i) +{ + set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; +} + +static inline void +bitset_clear (bitset_t set, Idx i) +{ + set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); +} + +static inline bool +bitset_contain (const bitset_t set, Idx i) +{ + return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; +} + +static inline void +bitset_empty (bitset_t set) +{ + memset (set, '\0', sizeof (bitset_t)); +} + +static inline void +bitset_set_all (bitset_t set) +{ + memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); + if (SBC_MAX % BITSET_WORD_BITS != 0) + set[BITSET_WORDS - 1] = + ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; +} + +static inline void +bitset_copy (bitset_t dest, const bitset_t src) +{ + memcpy (dest, src, sizeof (bitset_t)); +} + +static inline void +bitset_not (bitset_t set) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) + set[bitset_i] = ~set[bitset_i]; + if (SBC_MAX % BITSET_WORD_BITS != 0) + set[BITSET_WORDS - 1] = + ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) + & ~set[BITSET_WORDS - 1]); +} + +static inline void +bitset_merge (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] |= src[bitset_i]; +} + +static inline void +bitset_mask (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] &= src[bitset_i]; +} + +/* Functions for re_string. */ +static int +__attribute__ ((pure, unused)) +re_string_char_size_at (const re_string_t *pstr, Idx idx) +{ + int byte_idx; + if (pstr->mb_cur_max == 1) + return 1; + for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) + if (pstr->wcs[idx + byte_idx] != WEOF) + break; + return byte_idx; +} + +static wint_t +__attribute__ ((pure, unused)) +re_string_wchar_at (const re_string_t *pstr, Idx idx) +{ + if (pstr->mb_cur_max == 1) + return (wint_t) pstr->mbs[idx]; + return (wint_t) pstr->wcs[idx]; +} + +#ifdef _LIBC +# include +#endif + +static int +__attribute__ ((pure, unused)) +re_string_elem_size_at (const re_string_t *pstr, Idx idx) +{ +#ifdef _LIBC + const unsigned char *p, *extra; + const int32_t *table, *indirect; + uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + + if (nrules != 0) + { + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + p = pstr->mbs + idx; + findidx (table, indirect, extra, &p, pstr->len - idx); + return p - pstr->mbs - idx; + } +#endif /* _LIBC */ + + return 1; +} + +#ifdef _LIBC +# if __GNUC__ >= 7 +# define FALLTHROUGH __attribute__ ((__fallthrough__)) +# else +# define FALLTHROUGH ((void) 0) +# endif +#else +# include "attribute.h" +#endif + +#endif /* _REGEX_INTERNAL_H */ diff --git a/cross/lib/regexec.c b/cross/lib/regexec.c new file mode 100644 index 00000000000..13e0349e727 --- /dev/null +++ b/cross/lib/regexec.c @@ -0,0 +1,4221 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, + Idx n); +static void match_ctx_clean (re_match_context_t *mctx); +static void match_ctx_free (re_match_context_t *cache); +static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, + Idx str_idx, Idx from, Idx to); +static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx); +static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, + Idx str_idx); +static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, + Idx node, Idx str_idx); +static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, Idx last_node, + Idx last_str_idx); +static reg_errcode_t re_search_internal (const regex_t *preg, + const char *string, Idx length, + Idx start, Idx last_start, Idx stop, + size_t nmatch, regmatch_t pmatch[], + int eflags); +static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, + const char *string1, Idx length1, + const char *string2, Idx length2, + Idx start, regoff_t range, + struct re_registers *regs, + Idx stop, bool ret_len); +static regoff_t re_search_stub (struct re_pattern_buffer *bufp, + const char *string, Idx length, Idx start, + regoff_t range, Idx stop, + struct re_registers *regs, + bool ret_len); +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + Idx nregs, int regs_allocated); +static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx); +static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, + Idx *p_match_first); +static Idx check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, Idx idx); +static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, Idx cur_node, + Idx cur_idx, Idx nmatch); +static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, + Idx str_idx, Idx dest_node, Idx nregs, + regmatch_t *regs, regmatch_t *prevregs, + re_node_set *eps_via_nodes); +static reg_errcode_t set_regs (const regex_t *preg, + const re_match_context_t *mctx, + size_t nmatch, regmatch_t *pmatch, + bool fl_backtrack); +static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs); + +static int sift_states_iter_mb (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx node_idx, Idx str_idx, Idx max_str_idx); +static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, + re_sift_context_t *sctx); +static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, + re_sift_context_t *sctx, Idx str_idx, + re_node_set *cur_dest); +static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx str_idx, + re_node_set *dest_nodes); +static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates); +static bool check_dst_limits (const re_match_context_t *mctx, + const re_node_set *limits, + Idx dst_node, Idx dst_idx, Idx src_node, + Idx src_idx); +static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, + int boundaries, Idx subexp_idx, + Idx from_node, Idx bkref_idx); +static int check_dst_limits_calc_pos (const re_match_context_t *mctx, + Idx limit, Idx subexp_idx, + Idx node, Idx str_idx, + Idx bkref_idx); +static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates, + re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, + Idx str_idx); +static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, + re_sift_context_t *sctx, + Idx str_idx, const re_node_set *candidates); +static reg_errcode_t merge_state_array (const re_dfa_t *dfa, + re_dfastate_t **dst, + re_dfastate_t **src, Idx num); +static re_dfastate_t *find_recover_state (reg_errcode_t *err, + re_match_context_t *mctx); +static re_dfastate_t *transit_state (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *state); +static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *next_state); +static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, + re_node_set *cur_nodes, + Idx str_idx); +#if 0 +static re_dfastate_t *transit_state_sb (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *pstate); +#endif +static reg_errcode_t transit_state_mb (re_match_context_t *mctx, + re_dfastate_t *pstate); +static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, + const re_node_set *nodes); +static reg_errcode_t get_subexp (re_match_context_t *mctx, + Idx bkref_node, Idx bkref_str_idx); +static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, + const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, + Idx bkref_node, Idx bkref_str); +static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + Idx subexp_idx, int type); +static reg_errcode_t check_arrival (re_match_context_t *mctx, + state_array_t *path, Idx top_node, + Idx top_str, Idx last_node, Idx last_str, + int type); +static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, + Idx str_idx, + re_node_set *cur_nodes, + re_node_set *next_nodes); +static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, + re_node_set *cur_nodes, + Idx ex_subexp, int type); +static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, + re_node_set *dst_nodes, + Idx target, Idx ex_subexp, + int type); +static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, + re_node_set *cur_nodes, Idx cur_str, + Idx subexp_num, int type); +static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state); +static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, + const re_string_t *input, Idx idx); +#ifdef _LIBC +static unsigned int find_collation_sequence_value (const unsigned char *mbs, + size_t name_len); +#endif +static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, + const re_dfastate_t *state, + re_node_set *states_node, + bitset_t *states_ch); +static bool check_node_accept (const re_match_context_t *mctx, + const re_token_t *node, Idx idx); +static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len); + +/* Entry point for POSIX code. */ + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies "execution flags" which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if + EFLAGS is invalid. */ + +int +regexec (const regex_t *__restrict preg, const char *__restrict string, + size_t nmatch, regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) +{ + reg_errcode_t err; + Idx start, length; + re_dfa_t *dfa = preg->buffer; + + if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) + return REG_BADPAT; + + if (eflags & REG_STARTEND) + { + start = pmatch[0].rm_so; + length = pmatch[0].rm_eo; + } + else + { + start = 0; + length = strlen (string); + } + + lock_lock (dfa->lock); + if (preg->no_sub) + err = re_search_internal (preg, string, length, start, length, + length, 0, NULL, eflags); + else + err = re_search_internal (preg, string, length, start, length, + length, nmatch, pmatch, eflags); + lock_unlock (dfa->lock); + return err != REG_NOERROR; +} + +#ifdef _LIBC +libc_hidden_def (__regexec) + +# include +versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +__typeof__ (__regexec) __compat_regexec; + +int +attribute_compat_text_section +__compat_regexec (const regex_t *__restrict preg, + const char *__restrict string, size_t nmatch, + regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) +{ + return regexec (preg, string, nmatch, pmatch, + eflags & (REG_NOTBOL | REG_NOTEOL)); +} +compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); +# endif +#endif + +/* Entry points for GNU code. */ + +/* re_match, re_search, re_match_2, re_search_2 + + The former two functions operate on STRING with length LENGTH, + while the later two operate on concatenation of STRING1 and STRING2 + with lengths LENGTH1 and LENGTH2, respectively. + + re_match() matches the compiled pattern in BUFP against the string, + starting at index START. + + re_search() first tries matching at index START, then it tries to match + starting from index START + 1, and so on. The last start position tried + is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same + way as re_match().) + + The parameter STOP of re_{match,search}_2 specifies that no match exceeding + the first STOP characters of the concatenation of the strings should be + concerned. + + If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match + and all groups is stored in REGS. (For the "_2" variants, the offsets are + computed relative to the concatenation, not relative to the individual + strings.) + + On success, re_match* functions return the length of the match, re_search* + return the position of the start of the match. They return -1 on + match failure, -2 on error. */ + +regoff_t +re_match (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, 0, length, regs, true); +} +#ifdef _LIBC +weak_alias (__re_match, re_match) +#endif + +regoff_t +re_search (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, regoff_t range, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, range, length, regs, + false); +} +#ifdef _LIBC +weak_alias (__re_search, re_search) +#endif + +regoff_t +re_match_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, + const char *string2, Idx length2, Idx start, + struct re_registers *regs, Idx stop) +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, 0, regs, stop, true); +} +#ifdef _LIBC +weak_alias (__re_match_2, re_match_2) +#endif + +regoff_t +re_search_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, + const char *string2, Idx length2, Idx start, regoff_t range, + struct re_registers *regs, Idx stop) +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, range, regs, stop, false); +} +#ifdef _LIBC +weak_alias (__re_search_2, re_search_2) +#endif + +static regoff_t +re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, + Idx length1, const char *string2, Idx length2, Idx start, + regoff_t range, struct re_registers *regs, + Idx stop, bool ret_len) +{ + const char *str; + regoff_t rval; + Idx len; + char *s = NULL; + + if (__glibc_unlikely ((length1 < 0 || length2 < 0 || stop < 0 + || INT_ADD_WRAPV (length1, length2, &len)))) + return -2; + + /* Concatenate the strings. */ + if (length2 > 0) + if (length1 > 0) + { + s = re_malloc (char, len); + + if (__glibc_unlikely (s == NULL)) + return -2; +#ifdef _LIBC + memcpy (__mempcpy (s, string1, length1), string2, length2); +#else + memcpy (s, string1, length1); + memcpy (s + length1, string2, length2); +#endif + str = s; + } + else + str = string2; + else + str = string1; + + rval = re_search_stub (bufp, str, len, start, range, stop, regs, + ret_len); + re_free (s); + return rval; +} + +/* The parameters have the same meaning as those of re_search. + Additional parameters: + If RET_LEN is true the length of the match is returned (re_match style); + otherwise the position of the match is returned. */ + +static regoff_t +re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, + Idx start, regoff_t range, Idx stop, struct re_registers *regs, + bool ret_len) +{ + reg_errcode_t result; + regmatch_t *pmatch; + Idx nregs; + regoff_t rval; + int eflags = 0; + re_dfa_t *dfa = bufp->buffer; + Idx last_start = start + range; + + /* Check for out-of-range. */ + if (__glibc_unlikely (start < 0 || start > length)) + return -1; + if (__glibc_unlikely (length < last_start + || (0 <= range && last_start < start))) + last_start = length; + else if (__glibc_unlikely (last_start < 0 + || (range < 0 && start <= last_start))) + last_start = 0; + + lock_lock (dfa->lock); + + eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; + eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; + + /* Compile fastmap if we haven't yet. */ + if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) + re_compile_fastmap (bufp); + + if (__glibc_unlikely (bufp->no_sub)) + regs = NULL; + + /* We need at least 1 register. */ + if (regs == NULL) + nregs = 1; + else if (__glibc_unlikely (bufp->regs_allocated == REGS_FIXED + && regs->num_regs <= bufp->re_nsub)) + { + nregs = regs->num_regs; + if (__glibc_unlikely (nregs < 1)) + { + /* Nothing can be copied to regs. */ + regs = NULL; + nregs = 1; + } + } + else + nregs = bufp->re_nsub + 1; + pmatch = re_malloc (regmatch_t, nregs); + if (__glibc_unlikely (pmatch == NULL)) + { + rval = -2; + goto out; + } + + result = re_search_internal (bufp, string, length, start, last_start, stop, + nregs, pmatch, eflags); + + rval = 0; + + /* I hope we needn't fill their regs with -1's when no match was found. */ + if (result != REG_NOERROR) + rval = result == REG_NOMATCH ? -1 : -2; + else if (regs != NULL) + { + /* If caller wants register contents data back, copy them. */ + bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, + bufp->regs_allocated); + if (__glibc_unlikely (bufp->regs_allocated == REGS_UNALLOCATED)) + rval = -2; + } + + if (__glibc_likely (rval == 0)) + { + if (ret_len) + { + DEBUG_ASSERT (pmatch[0].rm_so == start); + rval = pmatch[0].rm_eo - start; + } + else + rval = pmatch[0].rm_so; + } + re_free (pmatch); + out: + lock_unlock (dfa->lock); + return rval; +} + +static unsigned +re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, + int regs_allocated) +{ + int rval = REGS_REALLOCATE; + Idx i; + Idx need_regs = nregs + 1; + /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code + uses. */ + + /* Have the register data arrays been allocated? */ + if (regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. */ + regs->start = re_malloc (regoff_t, need_regs); + if (__glibc_unlikely (regs->start == NULL)) + return REGS_UNALLOCATED; + regs->end = re_malloc (regoff_t, need_regs); + if (__glibc_unlikely (regs->end == NULL)) + { + re_free (regs->start); + return REGS_UNALLOCATED; + } + regs->num_regs = need_regs; + } + else if (regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (__glibc_unlikely (need_regs > regs->num_regs)) + { + regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); + regoff_t *new_end; + if (__glibc_unlikely (new_start == NULL)) + return REGS_UNALLOCATED; + new_end = re_realloc (regs->end, regoff_t, need_regs); + if (__glibc_unlikely (new_end == NULL)) + { + re_free (new_start); + return REGS_UNALLOCATED; + } + regs->start = new_start; + regs->end = new_end; + regs->num_regs = need_regs; + } + } + else + { + DEBUG_ASSERT (regs_allocated == REGS_FIXED); + /* This function may not be called with REGS_FIXED and nregs too big. */ + DEBUG_ASSERT (nregs <= regs->num_regs); + rval = REGS_FIXED; + } + + /* Copy the regs. */ + for (i = 0; i < nregs; ++i) + { + regs->start[i] = pmatch[i].rm_so; + regs->end[i] = pmatch[i].rm_eo; + } + for ( ; i < regs->num_regs; ++i) + regs->start[i] = regs->end[i] = -1; + + return rval; +} + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, + __re_size_t num_regs, regoff_t *starts, regoff_t *ends) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = NULL; + } +} +#ifdef _LIBC +weak_alias (__re_set_registers, re_set_registers) +#endif + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC +int +# ifdef _LIBC +weak_function +# endif +re_exec (const char *s) +{ + return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); +} +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. */ + +/* Searches for a compiled pattern PREG in the string STRING, whose + length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same + meaning as with regexec. LAST_START is START + RANGE, where + START and RANGE have the same meaning as with re_search. + Return REG_NOERROR if we find a match, and REG_NOMATCH if not, + otherwise return the error code. + Note: We assume front end functions already check ranges. + (0 <= LAST_START && LAST_START <= LENGTH) */ + +static reg_errcode_t +__attribute_warn_unused_result__ +re_search_internal (const regex_t *preg, const char *string, Idx length, + Idx start, Idx last_start, Idx stop, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ + reg_errcode_t err; + const re_dfa_t *dfa = preg->buffer; + Idx left_lim, right_lim; + int incr; + bool fl_longest_match; + int match_kind; + Idx match_first; + Idx match_last = -1; + Idx extra_nmatch; + bool sb; + int ch; + re_match_context_t mctx = { .dfa = dfa }; + char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate + && start != last_start && !preg->can_be_null) + ? preg->fastmap : NULL); + RE_TRANSLATE_TYPE t = preg->translate; + + extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; + nmatch -= extra_nmatch; + + /* Check if the DFA haven't been compiled. */ + if (__glibc_unlikely (preg->used == 0 || dfa->init_state == NULL + || dfa->init_state_word == NULL + || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL)) + return REG_NOMATCH; + + /* We assume front-end functions already check them. */ + DEBUG_ASSERT (0 <= last_start && last_start <= length); + + /* If initial states with non-begbuf contexts have no elements, + the regex must be anchored. If preg->newline_anchor is set, + we'll never use init_state_nl, so do not check it. */ + if (dfa->init_state->nodes.nelem == 0 + && dfa->init_state_word->nodes.nelem == 0 + && (dfa->init_state_nl->nodes.nelem == 0 + || !preg->newline_anchor)) + { + if (start != 0 && last_start != 0) + return REG_NOMATCH; + start = last_start = 0; + } + + /* We must check the longest matching, if nmatch > 0. */ + fl_longest_match = (nmatch != 0 || dfa->nbackref); + + err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, + preg->translate, (preg->syntax & RE_ICASE) != 0, + dfa); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + mctx.input.stop = stop; + mctx.input.raw_stop = stop; + mctx.input.newline_anchor = preg->newline_anchor; + + err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* We will log all the DFA states through which the dfa pass, + if nmatch > 1, or this dfa has "multibyte node", which is a + back-reference or a node which can accept multibyte character or + multi character collating element. */ + if (nmatch > 1 || dfa->has_mb_node) + { + /* Avoid overflow. */ + if (__glibc_unlikely ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= mctx.input.bufs_len))) + { + err = REG_ESPACE; + goto free_return; + } + + mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); + if (__glibc_unlikely (mctx.state_log == NULL)) + { + err = REG_ESPACE; + goto free_return; + } + } + + match_first = start; + mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF; + + /* Check incrementally whether the input string matches. */ + incr = (last_start < start) ? -1 : 1; + left_lim = (last_start < start) ? last_start : start; + right_lim = (last_start < start) ? start : last_start; + sb = dfa->mb_cur_max == 1; + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) + | (start <= last_start ? 2 : 0) + | (t != NULL ? 1 : 0)) + : 8); + + for (;; match_first += incr) + { + err = REG_NOMATCH; + if (match_first < left_lim || right_lim < match_first) + goto free_return; + + /* Advance as rapidly as possible through the string, until we + find a plausible place to start matching. This may be done + with varying efficiency, so there are various possibilities: + only the most common of them are specialized, in order to + save on code size. We use a switch statement for speed. */ + switch (match_kind) + { + case 8: + /* No fastmap. */ + break; + + case 7: + /* Fastmap with single-byte translation, match forward. */ + while (__glibc_likely (match_first < right_lim) + && !fastmap[t[(unsigned char) string[match_first]]]) + ++match_first; + goto forward_match_found_start_or_reached_end; + + case 6: + /* Fastmap without translation, match forward. */ + while (__glibc_likely (match_first < right_lim) + && !fastmap[(unsigned char) string[match_first]]) + ++match_first; + + forward_match_found_start_or_reached_end: + if (__glibc_unlikely (match_first == right_lim)) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (!fastmap[t ? t[ch] : ch]) + goto free_return; + } + break; + + case 4: + case 5: + /* Fastmap without multi-byte translation, match backwards. */ + while (match_first >= left_lim) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (fastmap[t ? t[ch] : ch]) + break; + --match_first; + } + if (match_first < left_lim) + goto free_return; + break; + + default: + /* In this case, we can't determine easily the current byte, + since it might be a component byte of a multibyte + character. Then we use the constructed buffer instead. */ + for (;;) + { + /* If MATCH_FIRST is out of the valid range, reconstruct the + buffers. */ + __re_size_t offset = match_first - mctx.input.raw_mbs_idx; + if (__glibc_unlikely (offset + >= (__re_size_t) mctx.input.valid_raw_len)) + { + err = re_string_reconstruct (&mctx.input, match_first, + eflags); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + offset = match_first - mctx.input.raw_mbs_idx; + } + /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */ + ch = (offset < mctx.input.valid_len + ? re_string_byte_at (&mctx.input, offset) : 0); + if (fastmap[ch]) + break; + match_first += incr; + if (match_first < left_lim || match_first > right_lim) + { + err = REG_NOMATCH; + goto free_return; + } + } + break; + } + + /* Reconstruct the buffers so that the matcher can assume that + the matching starts from the beginning of the buffer. */ + err = re_string_reconstruct (&mctx.input, match_first, eflags); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ + if (!sb && !re_string_first_byte (&mctx.input, 0)) + continue; + + /* It seems to be appropriate one, then use the matcher. */ + /* We assume that the matching starts from 0. */ + mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; + match_last = check_matching (&mctx, fl_longest_match, + start <= last_start ? &match_first : NULL); + if (match_last != -1) + { + if (__glibc_unlikely (match_last == -2)) + { + err = REG_ESPACE; + goto free_return; + } + else + { + mctx.match_last = match_last; + if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) + { + re_dfastate_t *pstate = mctx.state_log[match_last]; + mctx.last_node = check_halt_state_context (&mctx, pstate, + match_last); + } + if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) + || dfa->nbackref) + { + err = prune_impossible_nodes (&mctx); + if (err == REG_NOERROR) + break; + if (__glibc_unlikely (err != REG_NOMATCH)) + goto free_return; + match_last = -1; + } + else + break; /* We found a match. */ + } + } + + match_ctx_clean (&mctx); + } + + DEBUG_ASSERT (match_last != -1); + DEBUG_ASSERT (err == REG_NOERROR); + + /* Set pmatch[] if we need. */ + if (nmatch > 0) + { + Idx reg_idx; + + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + + /* Set the points where matching start/end. */ + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; + /* FIXME: This function should fail if mctx.match_last exceeds + the maximum possible regoff_t value. We need a new error + code REG_OVERFLOW. */ + + if (!preg->no_sub && nmatch > 1) + { + err = set_regs (preg, &mctx, nmatch, pmatch, + dfa->has_plural_match && dfa->nbackref > 0); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + + /* At last, add the offset to each register, since we slid + the buffers so that we could assume that the matching starts + from 0. */ + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so != -1) + { + if (__glibc_unlikely (mctx.input.offsets_needed != 0)) + { + pmatch[reg_idx].rm_so = + (pmatch[reg_idx].rm_so == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_so]); + pmatch[reg_idx].rm_eo = + (pmatch[reg_idx].rm_eo == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_eo]); + } + pmatch[reg_idx].rm_so += match_first; + pmatch[reg_idx].rm_eo += match_first; + } + for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) + { + pmatch[nmatch + reg_idx].rm_so = -1; + pmatch[nmatch + reg_idx].rm_eo = -1; + } + + if (dfa->subexp_map) + for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) + if (dfa->subexp_map[reg_idx] != reg_idx) + { + pmatch[reg_idx + 1].rm_so + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; + pmatch[reg_idx + 1].rm_eo + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; + } + } + + free_return: + re_free (mctx.state_log); + if (dfa->nbackref) + match_ctx_free (&mctx); + re_string_destruct (&mctx.input); + return err; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +prune_impossible_nodes (re_match_context_t *mctx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx halt_node, match_last; + reg_errcode_t ret; + re_dfastate_t **sifted_states; + re_dfastate_t **lim_states = NULL; + re_sift_context_t sctx; + DEBUG_ASSERT (mctx->state_log != NULL); + match_last = mctx->match_last; + halt_node = mctx->last_node; + + /* Avoid overflow. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) + <= match_last)) + return REG_ESPACE; + + sifted_states = re_malloc (re_dfastate_t *, match_last + 1); + if (__glibc_unlikely (sifted_states == NULL)) + { + ret = REG_ESPACE; + goto free_return; + } + if (dfa->nbackref) + { + lim_states = re_malloc (re_dfastate_t *, match_last + 1); + if (__glibc_unlikely (lim_states == NULL)) + { + ret = REG_ESPACE; + goto free_return; + } + while (1) + { + memset (lim_states, '\0', + sizeof (re_dfastate_t *) * (match_last + 1)); + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, + match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + if (sifted_states[0] != NULL || lim_states[0] != NULL) + break; + do + { + --match_last; + if (match_last < 0) + { + ret = REG_NOMATCH; + goto free_return; + } + } while (mctx->state_log[match_last] == NULL + || !mctx->state_log[match_last]->halt); + halt_node = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + } + ret = merge_state_array (dfa, sifted_states, lim_states, + match_last + 1); + re_free (lim_states); + lim_states = NULL; + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + } + else + { + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (__glibc_unlikely (ret != REG_NOERROR)) + goto free_return; + if (sifted_states[0] == NULL) + { + ret = REG_NOMATCH; + goto free_return; + } + } + re_free (mctx->state_log); + mctx->state_log = sifted_states; + sifted_states = NULL; + mctx->last_node = halt_node; + mctx->match_last = match_last; + ret = REG_NOERROR; + free_return: + re_free (sifted_states); + re_free (lim_states); + return ret; +} + +/* Acquire an initial state and return it. + We must select appropriate initial state depending on the context, + since initial states may have constraints like "\<", "^", etc.. */ + +static __always_inline re_dfastate_t * +acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, + Idx idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + if (dfa->init_state->has_constraint) + { + unsigned int context; + context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return dfa->init_state_word; + else if (IS_ORDINARY_CONTEXT (context)) + return dfa->init_state; + else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_begbuf; + else if (IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_nl; + else if (IS_BEGBUF_CONTEXT (context)) + { + /* It is relatively rare case, then calculate on demand. */ + return re_acquire_state_context (err, dfa, + dfa->init_state->entrance_nodes, + context); + } + else + /* Must not happen? */ + return dfa->init_state; + } + else + return dfa->init_state; +} + +/* Check whether the regular expression match input string INPUT or not, + and return the index where the matching end. Return -1 if + there is no match, and return -2 in case of an error. + FL_LONGEST_MATCH means we want the POSIX longest matching. + If P_MATCH_FIRST is not NULL, and the match fails, it is set to the + next place where we may want to try matching. + Note that the matcher assumes that the matching starts from the current + index of the buffer. */ + +static Idx +__attribute_warn_unused_result__ +check_matching (re_match_context_t *mctx, bool fl_longest_match, + Idx *p_match_first) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx match = 0; + Idx match_last = -1; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + re_dfastate_t *cur_state; + bool at_init_state = p_match_first != NULL; + Idx next_start_idx = cur_str_idx; + + err = REG_NOERROR; + cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); + /* An initial state must not be NULL (invalid). */ + if (__glibc_unlikely (cur_state == NULL)) + { + DEBUG_ASSERT (err == REG_ESPACE); + return -2; + } + + if (mctx->state_log != NULL) + { + mctx->state_log[cur_str_idx] = cur_state; + + /* Check OP_OPEN_SUBEXP in the initial state in case that we use them + later. E.g. Processing back references. */ + if (__glibc_unlikely (dfa->nbackref)) + { + at_init_state = false; + err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (cur_state->has_backref) + { + err = transit_state_bkref (mctx, &cur_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + } + + /* If the RE accepts NULL string. */ + if (__glibc_unlikely (cur_state->halt)) + { + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, cur_str_idx)) + { + if (!fl_longest_match) + return cur_str_idx; + else + { + match_last = cur_str_idx; + match = 1; + } + } + } + + while (!re_string_eoi (&mctx->input)) + { + re_dfastate_t *old_state = cur_state; + Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; + + if ((__glibc_unlikely (next_char_idx >= mctx->input.bufs_len) + && mctx->input.bufs_len < mctx->input.len) + || (__glibc_unlikely (next_char_idx >= mctx->input.valid_len) + && mctx->input.valid_len < mctx->input.len)) + { + err = extend_buffers (mctx, next_char_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + { + DEBUG_ASSERT (err == REG_ESPACE); + return -2; + } + } + + cur_state = transit_state (&err, mctx, cur_state); + if (mctx->state_log != NULL) + cur_state = merge_state_with_log (&err, mctx, cur_state); + + if (cur_state == NULL) + { + /* Reached the invalid state or an error. Try to recover a valid + state using the state log, if available and if we have not + already found a valid (even if not the longest) match. */ + if (__glibc_unlikely (err != REG_NOERROR)) + return -2; + + if (mctx->state_log == NULL + || (match && !fl_longest_match) + || (cur_state = find_recover_state (&err, mctx)) == NULL) + break; + } + + if (__glibc_unlikely (at_init_state)) + { + if (old_state == cur_state) + next_start_idx = next_char_idx; + else + at_init_state = false; + } + + if (cur_state->halt) + { + /* Reached a halt state. + Check the halt state can satisfy the current context. */ + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, + re_string_cur_idx (&mctx->input))) + { + /* We found an appropriate halt state. */ + match_last = re_string_cur_idx (&mctx->input); + match = 1; + + /* We found a match, do not modify match_first below. */ + p_match_first = NULL; + if (!fl_longest_match) + break; + } + } + } + + if (p_match_first) + *p_match_first += next_start_idx; + + return match_last; +} + +/* Check NODE match the current context. */ + +static bool +check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) +{ + re_token_type_t type = dfa->nodes[node].type; + unsigned int constraint = dfa->nodes[node].constraint; + if (type != END_OF_RE) + return false; + if (!constraint) + return true; + if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) + return false; + return true; +} + +/* Check the halt state STATE match the current context. + Return 0 if not match, if the node, STATE has, is a halt node and + match the context, return the node. */ + +static Idx +check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, Idx idx) +{ + Idx i; + unsigned int context; + DEBUG_ASSERT (state->halt); + context = re_string_context_at (&mctx->input, idx, mctx->eflags); + for (i = 0; i < state->nodes.nelem; ++i) + if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) + return state->nodes.elems[i]; + return 0; +} + +/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA + corresponding to the DFA). + Return the destination node, and update EPS_VIA_NODES; + return -1 on match failure, -2 on error. */ + +static Idx +proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, + regmatch_t *prevregs, + Idx *pidx, Idx node, re_node_set *eps_via_nodes, + struct re_fail_stack_t *fs) +{ + const re_dfa_t *const dfa = mctx->dfa; + if (IS_EPSILON_NODE (dfa->nodes[node].type)) + { + re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; + re_node_set *edests = &dfa->edests[node]; + + if (! re_node_set_contains (eps_via_nodes, node)) + { + bool ok = re_node_set_insert (eps_via_nodes, node); + if (__glibc_unlikely (! ok)) + return -2; + } + + /* Pick a valid destination, or return -1 if none is found. */ + Idx dest_node = -1; + for (Idx i = 0; i < edests->nelem; i++) + { + Idx candidate = edests->elems[i]; + if (!re_node_set_contains (cur_nodes, candidate)) + continue; + if (dest_node == -1) + dest_node = candidate; + + else + { + /* In order to avoid infinite loop like "(a*)*", return the second + epsilon-transition if the first was already considered. */ + if (re_node_set_contains (eps_via_nodes, dest_node)) + return candidate; + + /* Otherwise, push the second epsilon-transition on the fail stack. */ + else if (fs != NULL + && push_fail_stack (fs, *pidx, candidate, nregs, regs, + prevregs, eps_via_nodes)) + return -2; + + /* We know we are going to exit. */ + break; + } + } + return dest_node; + } + else + { + Idx naccepted = 0; + re_token_type_t type = dfa->nodes[node].type; + + if (dfa->nodes[node].accept_mb) + naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); + else if (type == OP_BACK_REF) + { + Idx subexp_idx = dfa->nodes[node].opr.idx + 1; + if (subexp_idx < nregs) + naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; + if (fs != NULL) + { + if (subexp_idx >= nregs + || regs[subexp_idx].rm_so == -1 + || regs[subexp_idx].rm_eo == -1) + return -1; + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); + if (mctx->input.valid_len - *pidx < naccepted + || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, + naccepted) + != 0)) + return -1; + } + } + + if (naccepted == 0) + { + Idx dest_node; + bool ok = re_node_set_insert (eps_via_nodes, node); + if (__glibc_unlikely (! ok)) + return -2; + dest_node = dfa->edests[node].elems[0]; + if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node)) + return dest_node; + } + } + + if (naccepted != 0 + || check_node_accept (mctx, dfa->nodes + node, *pidx)) + { + Idx dest_node = dfa->nexts[node]; + *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; + if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL + || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node))) + return -1; + re_node_set_empty (eps_via_nodes); + return dest_node; + } + } + return -1; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, + Idx nregs, regmatch_t *regs, regmatch_t *prevregs, + re_node_set *eps_via_nodes) +{ + reg_errcode_t err; + Idx num = fs->num; + if (num == fs->alloc) + { + struct re_fail_stack_ent_t *new_array; + new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t, + fs->alloc * 2); + if (new_array == NULL) + return REG_ESPACE; + fs->alloc *= 2; + fs->stack = new_array; + } + fs->stack[num].idx = str_idx; + fs->stack[num].node = dest_node; + fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs); + if (fs->stack[num].regs == NULL) + return REG_ESPACE; + fs->num = num + 1; + memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); + memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs); + err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); + return err; +} + +static Idx +pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, + regmatch_t *regs, regmatch_t *prevregs, + re_node_set *eps_via_nodes) +{ + if (fs == NULL || fs->num == 0) + return -1; + Idx num = --fs->num; + *pidx = fs->stack[num].idx; + memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); + memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs); + re_node_set_free (eps_via_nodes); + re_free (fs->stack[num].regs); + *eps_via_nodes = fs->stack[num].eps_via_nodes; + DEBUG_ASSERT (0 <= fs->stack[num].node); + return fs->stack[num].node; +} + + +#define DYNARRAY_STRUCT regmatch_list +#define DYNARRAY_ELEMENT regmatch_t +#define DYNARRAY_PREFIX regmatch_list_ +#include + +/* Set the positions where the subexpressions are starts/ends to registers + PMATCH. + Note: We assume that pmatch[0] is already set, and + pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + regmatch_t *pmatch, bool fl_backtrack) +{ + const re_dfa_t *dfa = preg->buffer; + Idx idx, cur_node; + re_node_set eps_via_nodes; + struct re_fail_stack_t *fs; + struct re_fail_stack_t fs_body = { 0, 2, NULL }; + struct regmatch_list prev_match; + regmatch_list_init (&prev_match); + + DEBUG_ASSERT (nmatch > 1); + DEBUG_ASSERT (mctx->state_log != NULL); + if (fl_backtrack) + { + fs = &fs_body; + fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); + if (fs->stack == NULL) + return REG_ESPACE; + } + else + fs = NULL; + + cur_node = dfa->init_node; + re_node_set_init_empty (&eps_via_nodes); + + if (!regmatch_list_resize (&prev_match, nmatch)) + { + regmatch_list_free (&prev_match); + free_fail_stack_return (fs); + return REG_ESPACE; + } + regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match); + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + + for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) + { + update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); + + if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node) + || (fs && re_node_set_contains (&eps_via_nodes, cur_node))) + { + Idx reg_idx; + cur_node = -1; + if (fs) + { + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) + { + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + prev_idx_match, &eps_via_nodes); + break; + } + } + if (cur_node < 0) + { + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); + return free_fail_stack_return (fs); + } + } + + /* Proceed to next node. */ + cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match, + &idx, cur_node, + &eps_via_nodes, fs); + + if (__glibc_unlikely (cur_node < 0)) + { + if (__glibc_unlikely (cur_node == -2)) + { + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); + free_fail_stack_return (fs); + return REG_ESPACE; + } + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + prev_idx_match, &eps_via_nodes); + if (cur_node < 0) + { + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); + free_fail_stack_return (fs); + return REG_NOMATCH; + } + } + } + re_node_set_free (&eps_via_nodes); + regmatch_list_free (&prev_match); + return free_fail_stack_return (fs); +} + +static reg_errcode_t +free_fail_stack_return (struct re_fail_stack_t *fs) +{ + if (fs) + { + Idx fs_idx; + for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) + { + re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); + re_free (fs->stack[fs_idx].regs); + } + re_free (fs->stack); + } + return REG_NOERROR; +} + +static void +update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) +{ + int type = dfa->nodes[cur_node].type; + if (type == OP_OPEN_SUBEXP) + { + Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; + + /* We are at the first node of this sub expression. */ + if (reg_num < nmatch) + { + pmatch[reg_num].rm_so = cur_idx; + pmatch[reg_num].rm_eo = -1; + } + } + else if (type == OP_CLOSE_SUBEXP) + { + /* We are at the last node of this sub expression. */ + Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; + if (reg_num < nmatch) + { + if (pmatch[reg_num].rm_so < cur_idx) + { + pmatch[reg_num].rm_eo = cur_idx; + /* This is a non-empty match or we are not inside an optional + subexpression. Accept this right away. */ + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + } + else + { + if (dfa->nodes[cur_node].opt_subexp + && prev_idx_match[reg_num].rm_so != -1) + /* We transited through an empty match for an optional + subexpression, like (a?)*, and this is not the subexp's + first match. Copy back the old content of the registers + so that matches of an inner subexpression are undone as + well, like in ((a?))*. */ + memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); + else + /* We completed a subexpression, but it may be part of + an optional one, so do not update PREV_IDX_MATCH. */ + pmatch[reg_num].rm_eo = cur_idx; + } + } + } +} + +/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 + and sift the nodes in each states according to the following rules. + Updated state_log will be wrote to STATE_LOG. + + Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if... + 1. When STR_IDX == MATCH_LAST(the last index in the state_log): + If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to + the LAST_NODE, we throw away the node 'a'. + 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts + string 's' and transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw + away the node 'a'. + ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is + thrown away, we throw away the node 'a'. + 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the + node 'a'. + ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, + we throw away the node 'a'. */ + +#define STATE_NODE_CONTAINS(state,node) \ + ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) + +static reg_errcode_t +sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) +{ + reg_errcode_t err; + int null_cnt = 0; + Idx str_idx = sctx->last_str_idx; + re_node_set cur_dest; + + DEBUG_ASSERT (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); + + /* Build sifted state_log[str_idx]. It has the nodes which can epsilon + transit to the last_node and the last_node itself. */ + err = re_node_set_init_1 (&cur_dest, sctx->last_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* Then check each states in the state_log. */ + while (str_idx > 0) + { + /* Update counters. */ + null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; + if (null_cnt > mctx->max_mb_elem_len) + { + memset (sctx->sifted_states, '\0', + sizeof (re_dfastate_t *) * str_idx); + re_node_set_free (&cur_dest); + return REG_NOERROR; + } + re_node_set_empty (&cur_dest); + --str_idx; + + if (mctx->state_log[str_idx]) + { + err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + + /* Add all the nodes which satisfy the following conditions: + - It can epsilon transit to a node in CUR_DEST. + - It is in CUR_SRC. + And update state_log. */ + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + err = REG_NOERROR; + free_return: + re_node_set_free (&cur_dest); + return err; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx str_idx, re_node_set *cur_dest) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; + Idx i; + + /* Then build the next sifted state. + We build the next sifted state on 'cur_dest', and update + 'sifted_states[str_idx]' with 'cur_dest'. + Note: + 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'. + 'cur_src' points the node_set of the old 'state_log[str_idx]' + (with the epsilon nodes pre-filtered out). */ + for (i = 0; i < cur_src->nelem; i++) + { + Idx prev_node = cur_src->elems[i]; + int naccepted = 0; + bool ok; + DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type)); + + /* If the node may accept "multi byte". */ + if (dfa->nodes[prev_node].accept_mb) + naccepted = sift_states_iter_mb (mctx, sctx, prev_node, + str_idx, sctx->last_str_idx); + + /* We don't check backreferences here. + See update_cur_sifted_state(). */ + if (!naccepted + && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) + && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], + dfa->nexts[prev_node])) + naccepted = 1; + + if (naccepted == 0) + continue; + + if (sctx->limits.nelem) + { + Idx to_idx = str_idx + naccepted; + if (check_dst_limits (mctx, &sctx->limits, + dfa->nexts[prev_node], to_idx, + prev_node, str_idx)) + continue; + } + ok = re_node_set_insert (cur_dest, prev_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + + return REG_NOERROR; +} + +/* Helper functions. */ + +static reg_errcode_t +clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) +{ + Idx top = mctx->state_log_top; + + if ((next_state_log_idx >= mctx->input.bufs_len + && mctx->input.bufs_len < mctx->input.len) + || (next_state_log_idx >= mctx->input.valid_len + && mctx->input.valid_len < mctx->input.len)) + { + reg_errcode_t err; + err = extend_buffers (mctx, next_state_log_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (top < next_state_log_idx) + { + DEBUG_ASSERT (mctx->state_log != NULL); + memset (mctx->state_log + top + 1, '\0', + sizeof (re_dfastate_t *) * (next_state_log_idx - top)); + mctx->state_log_top = next_state_log_idx; + } + return REG_NOERROR; +} + +static reg_errcode_t +merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, + re_dfastate_t **src, Idx num) +{ + Idx st_idx; + reg_errcode_t err; + for (st_idx = 0; st_idx < num; ++st_idx) + { + if (dst[st_idx] == NULL) + dst[st_idx] = src[st_idx]; + else if (src[st_idx] != NULL) + { + re_node_set merged_set; + err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, + &src[st_idx]->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); + re_node_set_free (&merged_set); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, Idx str_idx, + re_node_set *dest_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + const re_node_set *candidates; + candidates = ((mctx->state_log[str_idx] == NULL) ? NULL + : &mctx->state_log[str_idx]->nodes); + + if (dest_nodes->nelem == 0) + sctx->sifted_states[str_idx] = NULL; + else + { + if (candidates) + { + /* At first, add the nodes which can epsilon transit to a node in + DEST_NODE. */ + err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + /* Then, check the limitations in the current sift_context. */ + if (sctx->limits.nelem) + { + err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, + mctx->bkref_ents, str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + + sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (candidates && mctx->state_log[str_idx]->has_backref) + { + err = sift_states_bkref (mctx, sctx, str_idx, candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + reg_errcode_t err = REG_NOERROR; + Idx i; + + re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + if (!state->inveclosure.alloc) + { + err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + for (i = 0; i < dest_nodes->nelem; i++) + { + err = re_node_set_merge (&state->inveclosure, + dfa->inveclosures + dest_nodes->elems[i]); + if (__glibc_unlikely (err != REG_NOERROR)) + return REG_ESPACE; + } + } + return re_node_set_add_intersect (dest_nodes, candidates, + &state->inveclosure); +} + +static reg_errcode_t +sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + Idx ecl_idx; + reg_errcode_t err; + re_node_set *inv_eclosure = dfa->inveclosures + node; + re_node_set except_nodes; + re_node_set_init_empty (&except_nodes); + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + Idx cur_node = inv_eclosure->elems[ecl_idx]; + if (cur_node == node) + continue; + if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) + { + Idx edst1 = dfa->edests[cur_node].elems[0]; + Idx edst2 = ((dfa->edests[cur_node].nelem > 1) + ? dfa->edests[cur_node].elems[1] : -1); + if ((!re_node_set_contains (inv_eclosure, edst1) + && re_node_set_contains (dest_nodes, edst1)) + || (edst2 > 0 + && !re_node_set_contains (inv_eclosure, edst2) + && re_node_set_contains (dest_nodes, edst2))) + { + err = re_node_set_add_intersect (&except_nodes, candidates, + dfa->inveclosures + cur_node); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&except_nodes); + return err; + } + } + } + } + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + Idx cur_node = inv_eclosure->elems[ecl_idx]; + if (!re_node_set_contains (&except_nodes, cur_node)) + { + Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; + re_node_set_remove_at (dest_nodes, idx); + } + } + re_node_set_free (&except_nodes); + return REG_NOERROR; +} + +static bool +check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, + Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx lim_idx, src_pos, dst_pos; + + Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); + Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + Idx subexp_idx; + struct re_backref_cache_entry *ent; + ent = mctx->bkref_ents + limits->elems[lim_idx]; + subexp_idx = dfa->nodes[ent->node].opr.idx; + + dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, dst_node, dst_idx, + dst_bkref_idx); + src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, src_node, src_idx, + src_bkref_idx); + + /* In case of: + ( ) + ( ) + ( ) */ + if (src_pos == dst_pos) + continue; /* This is unrelated limitation. */ + else + return true; + } + return false; +} + +static int +check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, + Idx subexp_idx, Idx from_node, Idx bkref_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *eclosures = dfa->eclosures + from_node; + Idx node_idx; + + /* Else, we are on the boundary: examine the nodes on the epsilon + closure. */ + for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) + { + Idx node = eclosures->elems[node_idx]; + switch (dfa->nodes[node].type) + { + case OP_BACK_REF: + if (bkref_idx != -1) + { + struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; + do + { + Idx dst; + int cpos; + + if (ent->node != node) + continue; + + if (subexp_idx < BITSET_WORD_BITS + && !(ent->eps_reachable_subexps_map + & ((bitset_word_t) 1 << subexp_idx))) + continue; + + /* Recurse trying to reach the OP_OPEN_SUBEXP and + OP_CLOSE_SUBEXP cases below. But, if the + destination node is the same node as the source + node, don't recurse because it would cause an + infinite loop: a regex that exhibits this behavior + is ()\1*\1* */ + dst = dfa->edests[node].elems[0]; + if (dst == from_node) + { + if (boundaries & 1) + return -1; + else /* if (boundaries & 2) */ + return 0; + } + + cpos = + check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + dst, bkref_idx); + if (cpos == -1 /* && (boundaries & 1) */) + return -1; + if (cpos == 0 && (boundaries & 2)) + return 0; + + if (subexp_idx < BITSET_WORD_BITS) + ent->eps_reachable_subexps_map + &= ~((bitset_word_t) 1 << subexp_idx); + } + while (ent++->more); + } + break; + + case OP_OPEN_SUBEXP: + if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) + return -1; + break; + + case OP_CLOSE_SUBEXP: + if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) + return 0; + break; + + default: + break; + } + } + + return (boundaries & 2) ? 1 : 0; +} + +static int +check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, + Idx subexp_idx, Idx from_node, Idx str_idx, + Idx bkref_idx) +{ + struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + int boundaries; + + /* If we are outside the range of the subexpression, return -1 or 1. */ + if (str_idx < lim->subexp_from) + return -1; + + if (lim->subexp_to < str_idx) + return 1; + + /* If we are within the subexpression, return 0. */ + boundaries = (str_idx == lim->subexp_from); + boundaries |= (str_idx == lim->subexp_to) << 1; + if (boundaries == 0) + return 0; + + /* Else, examine epsilon closure. */ + return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + from_node, bkref_idx); +} + +/* Check the limitations of sub expressions LIMITS, and remove the nodes + which are against limitations from DEST_NODES. */ + +static reg_errcode_t +check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates, re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, Idx str_idx) +{ + reg_errcode_t err; + Idx node_idx, lim_idx; + + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + Idx subexp_idx; + struct re_backref_cache_entry *ent; + ent = bkref_ents + limits->elems[lim_idx]; + + if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) + continue; /* This is unrelated limitation. */ + + subexp_idx = dfa->nodes[ent->node].opr.idx; + if (ent->subexp_to == str_idx) + { + Idx ops_node = -1; + Idx cls_node = -1; + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_OPEN_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + ops_node = node; + else if (type == OP_CLOSE_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + cls_node = node; + } + + /* Check the limitation of the open subexpression. */ + /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ + if (ops_node >= 0) + { + err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + /* Check the limitation of the close subexpression. */ + if (cls_node >= 0) + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + if (!re_node_set_contains (dfa->inveclosures + node, + cls_node) + && !re_node_set_contains (dfa->eclosures + node, + cls_node)) + { + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + --node_idx; + } + } + } + else /* (ent->subexp_to != str_idx) */ + { + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + Idx node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) + { + if (subexp_idx != dfa->nodes[node].opr.idx) + continue; + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + } + } + return REG_NOERROR; +} + +static reg_errcode_t +__attribute_warn_unused_result__ +sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx str_idx, const re_node_set *candidates) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx node_idx, node; + re_sift_context_t local_sctx; + Idx first_idx = search_cur_bkref_entry (mctx, str_idx); + + if (first_idx == -1) + return REG_NOERROR; + + local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ + + for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) + { + Idx enabled_idx; + re_token_type_t type; + struct re_backref_cache_entry *entry; + node = candidates->elems[node_idx]; + type = dfa->nodes[node].type; + /* Avoid infinite loop for the REs like "()\1+". */ + if (node == sctx->last_node && str_idx == sctx->last_str_idx) + continue; + if (type != OP_BACK_REF) + continue; + + entry = mctx->bkref_ents + first_idx; + enabled_idx = first_idx; + do + { + Idx subexp_len; + Idx to_idx; + Idx dst_node; + bool ok; + re_dfastate_t *cur_state; + + if (entry->node != node) + continue; + subexp_len = entry->subexp_to - entry->subexp_from; + to_idx = str_idx + subexp_len; + dst_node = (subexp_len ? dfa->nexts[node] + : dfa->edests[node].elems[0]); + + if (to_idx > sctx->last_str_idx + || sctx->sifted_states[to_idx] == NULL + || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) + || check_dst_limits (mctx, &sctx->limits, node, + str_idx, dst_node, to_idx)) + continue; + + if (local_sctx.sifted_states == NULL) + { + local_sctx = *sctx; + err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + local_sctx.last_node = node; + local_sctx.last_str_idx = str_idx; + ok = re_node_set_insert (&local_sctx.limits, enabled_idx); + if (__glibc_unlikely (! ok)) + { + err = REG_ESPACE; + goto free_return; + } + cur_state = local_sctx.sifted_states[str_idx]; + err = sift_states_backward (mctx, &local_sctx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + if (sctx->limited_states != NULL) + { + err = merge_state_array (dfa, sctx->limited_states, + local_sctx.sifted_states, + str_idx + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + local_sctx.sifted_states[str_idx] = cur_state; + re_node_set_remove (&local_sctx.limits, enabled_idx); + + /* mctx->bkref_ents may have changed, reload the pointer. */ + entry = mctx->bkref_ents + enabled_idx; + } + while (enabled_idx++, entry++->more); + } + err = REG_NOERROR; + free_return: + if (local_sctx.sifted_states != NULL) + { + re_node_set_free (&local_sctx.limits); + } + + return err; +} + + +static int +sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, + Idx node_idx, Idx str_idx, Idx max_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int naccepted; + /* Check the node can accept "multi byte". */ + naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); + if (naccepted > 0 && str_idx + naccepted <= max_str_idx + && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], + dfa->nexts[node_idx])) + /* The node can't accept the "multi byte", or the + destination was already thrown away, then the node + couldn't accept the current input "multi byte". */ + naccepted = 0; + /* Otherwise, it is sure that the node could accept + 'naccepted' bytes input. */ + return naccepted; +} + +/* Functions for state transition. */ + +/* Return the next state to which the current state STATE will transit by + accepting the current input byte, and update STATE_LOG if necessary. + Return NULL on failure. + If STATE can accept a multibyte char/collating element/back reference + update the destination of STATE_LOG. */ + +static re_dfastate_t * +__attribute_warn_unused_result__ +transit_state (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + re_dfastate_t **trtable; + unsigned char ch; + + /* If the current state can accept multibyte. */ + if (__glibc_unlikely (state->accept_mb)) + { + *err = transit_state_mb (mctx, state); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } + + /* Then decide the next state with the single byte. */ +#if 0 + if (0) + /* don't use transition table */ + return transit_state_sb (err, mctx, state); +#endif + + /* Use transition table */ + ch = re_string_fetch_byte (&mctx->input); + for (;;) + { + trtable = state->trtable; + if (__glibc_likely (trtable != NULL)) + return trtable[ch]; + + trtable = state->word_trtable; + if (__glibc_likely (trtable != NULL)) + { + unsigned int context; + context + = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return trtable[ch + SBC_MAX]; + else + return trtable[ch]; + } + + if (!build_trtable (mctx->dfa, state)) + { + *err = REG_ESPACE; + return NULL; + } + + /* Retry, we now have a transition table. */ + } +} + +/* Update the state_log if we need */ +static re_dfastate_t * +merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *next_state) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx cur_idx = re_string_cur_idx (&mctx->input); + + if (cur_idx > mctx->state_log_top) + { + mctx->state_log[cur_idx] = next_state; + mctx->state_log_top = cur_idx; + } + else if (mctx->state_log[cur_idx] == 0) + { + mctx->state_log[cur_idx] = next_state; + } + else + { + re_dfastate_t *pstate; + unsigned int context; + re_node_set next_nodes, *log_nodes, *table_nodes = NULL; + /* If (state_log[cur_idx] != 0), it implies that cur_idx is + the destination of a multibyte char/collating element/ + back reference. Then the next state is the union set of + these destinations and the results of the transition table. */ + pstate = mctx->state_log[cur_idx]; + log_nodes = pstate->entrance_nodes; + if (next_state != NULL) + { + table_nodes = next_state->entrance_nodes; + *err = re_node_set_init_union (&next_nodes, table_nodes, + log_nodes); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + } + else + next_nodes = *log_nodes; + /* Note: We already add the nodes of the initial state, + then we don't need to add them here. */ + + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + next_state = mctx->state_log[cur_idx] + = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + if (table_nodes != NULL) + re_node_set_free (&next_nodes); + } + + if (__glibc_unlikely (dfa->nbackref) && next_state != NULL) + { + /* Check OP_OPEN_SUBEXP in the current state in case that we use them + later. We must check them here, since the back references in the + next state might use them. */ + *err = check_subexp_matching_top (mctx, &next_state->nodes, + cur_idx); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + + /* If the next state has back references. */ + if (next_state->has_backref) + { + *err = transit_state_bkref (mctx, &next_state->nodes); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + next_state = mctx->state_log[cur_idx]; + } + } + + return next_state; +} + +/* Skip bytes in the input that correspond to part of a + multi-byte match, then look in the log for a state + from which to restart matching. */ +static re_dfastate_t * +find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) +{ + re_dfastate_t *cur_state; + do + { + Idx max = mctx->state_log_top; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + + do + { + if (++cur_str_idx > max) + return NULL; + re_string_skip_bytes (&mctx->input, 1); + } + while (mctx->state_log[cur_str_idx] == NULL); + + cur_state = merge_state_with_log (err, mctx, NULL); + } + while (*err == REG_NOERROR && cur_state == NULL); + return cur_state; +} + +/* Helper functions for transit_state. */ + +/* From the node set CUR_NODES, pick up the nodes whose types are + OP_OPEN_SUBEXP and which have corresponding back references in the regular + expression. And register them to use them later for evaluating the + corresponding back references. */ + +static reg_errcode_t +check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, + Idx str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx node_idx; + reg_errcode_t err; + + /* TODO: This isn't efficient. + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) + { + Idx node = cur_nodes->elems[node_idx]; + if (dfa->nodes[node].type == OP_OPEN_SUBEXP + && dfa->nodes[node].opr.idx < BITSET_WORD_BITS + && (dfa->used_bkref_map + & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) + { + err = match_ctx_add_subtop (mctx, node, str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +#if 0 +/* Return the next state to which the current state STATE will transit by + accepting the current input byte. Return NULL on failure. */ + +static re_dfastate_t * +transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + const re_dfa_t *const dfa = mctx->dfa; + re_node_set next_nodes; + re_dfastate_t *next_state; + Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); + unsigned int context; + + *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); + if (__glibc_unlikely (*err != REG_NOERROR)) + return NULL; + for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) + { + Idx cur_node = state->nodes.elems[node_cnt]; + if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) + { + *err = re_node_set_merge (&next_nodes, + dfa->eclosures + dfa->nexts[cur_node]); + if (__glibc_unlikely (*err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return NULL; + } + } + } + context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); + next_state = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + re_node_set_free (&next_nodes); + re_string_skip_bytes (&mctx->input, 1); + return next_state; +} +#endif + +static reg_errcode_t +transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx i; + + for (i = 0; i < pstate->nodes.nelem; ++i) + { + re_node_set dest_nodes, *new_nodes; + Idx cur_node_idx = pstate->nodes.elems[i]; + int naccepted; + Idx dest_idx; + unsigned int context; + re_dfastate_t *dest_state; + + if (!dfa->nodes[cur_node_idx].accept_mb) + continue; + + if (dfa->nodes[cur_node_idx].constraint) + { + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input), + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, + context)) + continue; + } + + /* How many bytes the node can accept? */ + naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, + re_string_cur_idx (&mctx->input)); + if (naccepted == 0) + continue; + + /* The node can accepts 'naccepted' bytes. */ + dest_idx = re_string_cur_idx (&mctx->input) + naccepted; + mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted + : mctx->max_mb_elem_len); + err = clean_state_log_if_needed (mctx, dest_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + DEBUG_ASSERT (dfa->nexts[cur_node_idx] != -1); + new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; + + dest_state = mctx->state_log[dest_idx]; + if (dest_state == NULL) + dest_nodes = *new_nodes; + else + { + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, new_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + context = re_string_context_at (&mctx->input, dest_idx - 1, + mctx->eflags); + mctx->state_log[dest_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + if (dest_state != NULL) + re_node_set_free (&dest_nodes); + if (__glibc_unlikely (mctx->state_log[dest_idx] == NULL + && err != REG_NOERROR)) + return err; + } + return REG_NOERROR; +} + +static reg_errcode_t +transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx i; + Idx cur_str_idx = re_string_cur_idx (&mctx->input); + + for (i = 0; i < nodes->nelem; ++i) + { + Idx dest_str_idx, prev_nelem, bkc_idx; + Idx node_idx = nodes->elems[i]; + unsigned int context; + const re_token_t *node = dfa->nodes + node_idx; + re_node_set *new_dest_nodes; + + /* Check whether 'node' is a backreference or not. */ + if (node->type != OP_BACK_REF) + continue; + + if (node->constraint) + { + context = re_string_context_at (&mctx->input, cur_str_idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + continue; + } + + /* 'node' is a backreference. + Check the substring which the substring matched. */ + bkc_idx = mctx->nbkref_ents; + err = get_subexp (mctx, node_idx, cur_str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + + /* And add the epsilon closures (which is 'new_dest_nodes') of + the backreference to appropriate state_log. */ + DEBUG_ASSERT (dfa->nexts[node_idx] != -1); + for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) + { + Idx subexp_len; + re_dfastate_t *dest_state; + struct re_backref_cache_entry *bkref_ent; + bkref_ent = mctx->bkref_ents + bkc_idx; + if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) + continue; + subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; + new_dest_nodes = (subexp_len == 0 + ? dfa->eclosures + dfa->edests[node_idx].elems[0] + : dfa->eclosures + dfa->nexts[node_idx]); + dest_str_idx = (cur_str_idx + bkref_ent->subexp_to + - bkref_ent->subexp_from); + context = re_string_context_at (&mctx->input, dest_str_idx - 1, + mctx->eflags); + dest_state = mctx->state_log[dest_str_idx]; + prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 + : mctx->state_log[cur_str_idx]->nodes.nelem); + /* Add 'new_dest_node' to state_log. */ + if (dest_state == NULL) + { + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, new_dest_nodes, + context); + if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR)) + goto free_return; + } + else + { + re_node_set dest_nodes; + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, + new_dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&dest_nodes); + goto free_return; + } + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + re_node_set_free (&dest_nodes); + if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR)) + goto free_return; + } + /* We need to check recursively if the backreference can epsilon + transit. */ + if (subexp_len == 0 + && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) + { + err = check_subexp_matching_top (mctx, new_dest_nodes, + cur_str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + err = transit_state_bkref (mctx, new_dest_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + goto free_return; + } + } + } + err = REG_NOERROR; + free_return: + return err; +} + +/* Enumerate all the candidates which the backreference BKREF_NODE can match + at BKREF_STR_IDX, and register them by match_ctx_add_entry(). + Note that we might collect inappropriate candidates here. + However, the cost of checking them strictly here is too high, then we + delay these checking for prune_impossible_nodes(). */ + +static reg_errcode_t +__attribute_warn_unused_result__ +get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + Idx subexp_num, sub_top_idx; + const char *buf = (const char *) re_string_get_buffer (&mctx->input); + /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ + Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); + if (cache_idx != -1) + { + const struct re_backref_cache_entry *entry + = mctx->bkref_ents + cache_idx; + do + if (entry->node == bkref_node) + return REG_NOERROR; /* We already checked it. */ + while (entry++->more); + } + + subexp_num = dfa->nodes[bkref_node].opr.idx; + + /* For each sub expression */ + for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) + { + reg_errcode_t err; + re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; + re_sub_match_last_t *sub_last; + Idx sub_last_idx, sl_str, bkref_str_off; + + if (dfa->nodes[sub_top->node].opr.idx != subexp_num) + continue; /* It isn't related. */ + + sl_str = sub_top->str_idx; + bkref_str_off = bkref_str_idx; + /* At first, check the last node of sub expressions we already + evaluated. */ + for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) + { + regoff_t sl_str_diff; + sub_last = sub_top->lasts[sub_last_idx]; + sl_str_diff = sub_last->str_idx - sl_str; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_diff > 0) + { + if (__glibc_unlikely (bkref_str_off + sl_str_diff + > mctx->input.valid_len)) + { + /* Not enough chars for a successful match. */ + if (bkref_str_off + sl_str_diff > mctx->input.len) + break; + + err = clean_state_log_if_needed (mctx, + bkref_str_off + + sl_str_diff); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) + /* We don't need to search this sub expression any more. */ + break; + } + bkref_str_off += sl_str_diff; + sl_str += sl_str_diff; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + + /* Reload buf, since the preceding call might have reallocated + the buffer. */ + buf = (const char *) re_string_get_buffer (&mctx->input); + + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + + if (sub_last_idx < sub_top->nlasts) + continue; + if (sub_last_idx > 0) + ++sl_str; + /* Then, search for the other last nodes of the sub expression. */ + for (; sl_str <= bkref_str_idx; ++sl_str) + { + Idx cls_node; + regoff_t sl_str_off; + const re_node_set *nodes; + sl_str_off = sl_str - sub_top->str_idx; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_off > 0) + { + if (__glibc_unlikely (bkref_str_off >= mctx->input.valid_len)) + { + /* If we are at the end of the input, we cannot match. */ + if (bkref_str_off >= mctx->input.len) + break; + + err = extend_buffers (mctx, bkref_str_off + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (buf [bkref_str_off++] != buf[sl_str - 1]) + break; /* We don't need to search this sub expression + any more. */ + } + if (mctx->state_log[sl_str] == NULL) + continue; + /* Does this state have a ')' of the sub expression? */ + nodes = &mctx->state_log[sl_str]->nodes; + cls_node = find_subexp_node (dfa, nodes, subexp_num, + OP_CLOSE_SUBEXP); + if (cls_node == -1) + continue; /* No. */ + if (sub_top->path == NULL) + { + sub_top->path = calloc (sizeof (state_array_t), + sl_str - sub_top->str_idx + 1); + if (sub_top->path == NULL) + return REG_ESPACE; + } + /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node + in the current context? */ + err = check_arrival (mctx, sub_top->path, sub_top->node, + sub_top->str_idx, cls_node, sl_str, + OP_CLOSE_SUBEXP); + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); + if (__glibc_unlikely (sub_last == NULL)) + return REG_ESPACE; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + buf = (const char *) re_string_get_buffer (&mctx->input); + if (err == REG_NOMATCH) + continue; + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + } + return REG_NOERROR; +} + +/* Helper functions for get_subexp(). */ + +/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. + If it can arrive, register the sub expression expressed with SUB_TOP + and SUB_LAST. */ + +static reg_errcode_t +get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) +{ + reg_errcode_t err; + Idx to_idx; + /* Can the subexpression arrive the back reference? */ + err = check_arrival (mctx, &sub_last->path, sub_last->node, + sub_last->str_idx, bkref_node, bkref_str, + OP_OPEN_SUBEXP); + if (err != REG_NOERROR) + return err; + err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, + sub_last->str_idx); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; + return clean_state_log_if_needed (mctx, to_idx); +} + +/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. + Search '(' if FL_OPEN, or search ')' otherwise. + TODO: This function isn't efficient... + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + +static Idx +find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + Idx subexp_idx, int type) +{ + Idx cls_idx; + for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) + { + Idx cls_node = nodes->elems[cls_idx]; + const re_token_t *node = dfa->nodes + cls_node; + if (node->type == type + && node->opr.idx == subexp_idx) + return cls_node; + } + return -1; +} + +/* Check whether the node TOP_NODE at TOP_STR can arrive to the node + LAST_NODE at LAST_STR. We record the path onto PATH since it will be + heavily reused. + Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot, + REG_ESPACE if memory is exhausted. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, + Idx top_str, Idx last_node, Idx last_str, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + Idx subexp_num, backup_cur_idx, str_idx, null_cnt; + re_dfastate_t *cur_state = NULL; + re_node_set *cur_nodes, next_nodes; + re_dfastate_t **backup_state_log; + unsigned int context; + + subexp_num = dfa->nodes[top_node].opr.idx; + /* Extend the buffer if we need. */ + if (__glibc_unlikely (path->alloc < last_str + mctx->max_mb_elem_len + 1)) + { + re_dfastate_t **new_array; + Idx old_alloc = path->alloc; + Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1; + Idx new_alloc; + if (__glibc_unlikely (IDX_MAX - old_alloc < incr_alloc)) + return REG_ESPACE; + new_alloc = old_alloc + incr_alloc; + if (__glibc_unlikely (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc)) + return REG_ESPACE; + new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + path->array = new_array; + path->alloc = new_alloc; + memset (new_array + old_alloc, '\0', + sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); + } + + str_idx = path->next_idx ? path->next_idx : top_str; + + /* Temporary modify MCTX. */ + backup_state_log = mctx->state_log; + backup_cur_idx = mctx->input.cur_idx; + mctx->state_log = path->array; + mctx->input.cur_idx = str_idx; + + /* Setup initial node set. */ + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + if (str_idx == top_str) + { + err = re_node_set_init_1 (&next_nodes, top_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + else + { + cur_state = mctx->state_log[str_idx]; + if (cur_state && cur_state->has_backref) + { + err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + else + re_node_set_init_empty (&next_nodes); + } + if (str_idx == top_str || (cur_state && cur_state->has_backref)) + { + if (next_nodes.nelem) + { + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + } + + for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) + { + re_node_set_empty (&next_nodes); + if (mctx->state_log[str_idx + 1]) + { + err = re_node_set_merge (&next_nodes, + &mctx->state_log[str_idx + 1]->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + if (cur_state) + { + err = check_arrival_add_next_nodes (mctx, str_idx, + &cur_state->non_eps_nodes, + &next_nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + ++str_idx; + if (next_nodes.nelem) + { + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + } + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + null_cnt = cur_state == NULL ? null_cnt + 1 : 0; + } + re_node_set_free (&next_nodes); + cur_nodes = (mctx->state_log[last_str] == NULL ? NULL + : &mctx->state_log[last_str]->nodes); + path->next_idx = str_idx; + + /* Fix MCTX. */ + mctx->state_log = backup_state_log; + mctx->input.cur_idx = backup_cur_idx; + + /* Then check the current node set has the node LAST_NODE. */ + if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) + return REG_NOERROR; + + return REG_NOMATCH; +} + +/* Helper functions for check_arrival. */ + +/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them + to NEXT_NODES. + TODO: This function is similar to the functions transit_state*(), + however this function has many additional works. + Can't we unify them? */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, + re_node_set *cur_nodes, re_node_set *next_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + bool ok; + Idx cur_idx; + reg_errcode_t err = REG_NOERROR; + re_node_set union_set; + re_node_set_init_empty (&union_set); + for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) + { + int naccepted = 0; + Idx cur_node = cur_nodes->elems[cur_idx]; + DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type)); + + /* If the node may accept "multi byte". */ + if (dfa->nodes[cur_node].accept_mb) + { + naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, + str_idx); + if (naccepted > 1) + { + re_dfastate_t *dest_state; + Idx next_node = dfa->nexts[cur_node]; + Idx next_idx = str_idx + naccepted; + dest_state = mctx->state_log[next_idx]; + re_node_set_empty (&union_set); + if (dest_state) + { + err = re_node_set_merge (&union_set, &dest_state->nodes); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&union_set); + return err; + } + } + ok = re_node_set_insert (&union_set, next_node); + if (__glibc_unlikely (! ok)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + mctx->state_log[next_idx] = re_acquire_state (&err, dfa, + &union_set); + if (__glibc_unlikely (mctx->state_log[next_idx] == NULL + && err != REG_NOERROR)) + { + re_node_set_free (&union_set); + return err; + } + } + } + + if (naccepted + || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) + { + ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); + if (__glibc_unlikely (! ok)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + } + } + re_node_set_free (&union_set); + return REG_NOERROR; +} + +/* For all the nodes in CUR_NODES, add the epsilon closures of them to + CUR_NODES, however exclude the nodes which are: + - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. + - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. +*/ + +static reg_errcode_t +check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, + Idx ex_subexp, int type) +{ + reg_errcode_t err; + Idx idx, outside_node; + re_node_set new_nodes; + DEBUG_ASSERT (cur_nodes->nelem); + err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + /* Create a new node set NEW_NODES with the nodes which are epsilon + closures of the node in CUR_NODES. */ + + for (idx = 0; idx < cur_nodes->nelem; ++idx) + { + Idx cur_node = cur_nodes->elems[idx]; + const re_node_set *eclosure = dfa->eclosures + cur_node; + outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); + if (outside_node == -1) + { + /* There are no problematic nodes, just merge them. */ + err = re_node_set_merge (&new_nodes, eclosure); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&new_nodes); + return err; + } + } + else + { + /* There are problematic nodes, re-calculate incrementally. */ + err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, + ex_subexp, type); + if (__glibc_unlikely (err != REG_NOERROR)) + { + re_node_set_free (&new_nodes); + return err; + } + } + } + re_node_set_free (cur_nodes); + *cur_nodes = new_nodes; + return REG_NOERROR; +} + +/* Helper function for check_arrival_expand_ecl. + Check incrementally the epsilon closure of TARGET, and if it isn't + problematic append it to DST_NODES. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, + Idx target, Idx ex_subexp, int type) +{ + Idx cur_node; + for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) + { + bool ok; + + if (dfa->nodes[cur_node].type == type + && dfa->nodes[cur_node].opr.idx == ex_subexp) + { + if (type == OP_CLOSE_SUBEXP) + { + ok = re_node_set_insert (dst_nodes, cur_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + } + break; + } + ok = re_node_set_insert (dst_nodes, cur_node); + if (__glibc_unlikely (! ok)) + return REG_ESPACE; + if (dfa->edests[cur_node].nelem == 0) + break; + if (dfa->edests[cur_node].nelem == 2) + { + reg_errcode_t err; + err = check_arrival_expand_ecl_sub (dfa, dst_nodes, + dfa->edests[cur_node].elems[1], + ex_subexp, type); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + cur_node = dfa->edests[cur_node].elems[0]; + } + return REG_NOERROR; +} + + +/* For all the back references in the current state, calculate the + destination of the back references by the appropriate entry + in MCTX->BKREF_ENTS. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, + Idx cur_str, Idx subexp_num, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); + struct re_backref_cache_entry *ent; + + if (cache_idx_start == -1) + return REG_NOERROR; + + restart: + ent = mctx->bkref_ents + cache_idx_start; + do + { + Idx to_idx, next_node; + + /* Is this entry ENT is appropriate? */ + if (!re_node_set_contains (cur_nodes, ent->node)) + continue; /* No. */ + + to_idx = cur_str + ent->subexp_to - ent->subexp_from; + /* Calculate the destination of the back reference, and append it + to MCTX->STATE_LOG. */ + if (to_idx == cur_str) + { + /* The backreference did epsilon transit, we must re-check all the + node in the current state. */ + re_node_set new_dests; + reg_errcode_t err2, err3; + next_node = dfa->edests[ent->node].elems[0]; + if (re_node_set_contains (cur_nodes, next_node)) + continue; + err = re_node_set_init_1 (&new_dests, next_node); + err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); + err3 = re_node_set_merge (cur_nodes, &new_dests); + re_node_set_free (&new_dests); + if (__glibc_unlikely (err != REG_NOERROR || err2 != REG_NOERROR + || err3 != REG_NOERROR)) + { + err = (err != REG_NOERROR ? err + : (err2 != REG_NOERROR ? err2 : err3)); + return err; + } + /* TODO: It is still inefficient... */ + goto restart; + } + else + { + re_node_set union_set; + next_node = dfa->nexts[ent->node]; + if (mctx->state_log[to_idx]) + { + bool ok; + if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, + next_node)) + continue; + err = re_node_set_init_copy (&union_set, + &mctx->state_log[to_idx]->nodes); + ok = re_node_set_insert (&union_set, next_node); + if (__glibc_unlikely (err != REG_NOERROR || ! ok)) + { + re_node_set_free (&union_set); + err = err != REG_NOERROR ? err : REG_ESPACE; + return err; + } + } + else + { + err = re_node_set_init_1 (&union_set, next_node); + if (__glibc_unlikely (err != REG_NOERROR)) + return err; + } + mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); + re_node_set_free (&union_set); + if (__glibc_unlikely (mctx->state_log[to_idx] == NULL + && err != REG_NOERROR)) + return err; + } + } + while (ent++->more); + return REG_NOERROR; +} + +/* Build transition table for the state. + Return true if successful. */ + +static bool __attribute_noinline__ +build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) +{ + reg_errcode_t err; + Idx i, j; + int ch; + bool need_word_trtable = false; + bitset_word_t elem, mask; + Idx ndests; /* Number of the destination states from 'state'. */ + re_dfastate_t **trtable; + re_dfastate_t *dest_states[SBC_MAX]; + re_dfastate_t *dest_states_word[SBC_MAX]; + re_dfastate_t *dest_states_nl[SBC_MAX]; + re_node_set follows; + bitset_t acceptable; + + /* We build DFA states which corresponds to the destination nodes + from 'state'. 'dests_node[i]' represents the nodes which i-th + destination state contains, and 'dests_ch[i]' represents the + characters which i-th destination state accepts. */ + re_node_set dests_node[SBC_MAX]; + bitset_t dests_ch[SBC_MAX]; + + /* Initialize transition table. */ + state->word_trtable = state->trtable = NULL; + + /* At first, group all nodes belonging to 'state' into several + destinations. */ + ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); + if (__glibc_unlikely (ndests <= 0)) + { + /* Return false in case of an error, true otherwise. */ + if (ndests == 0) + { + state->trtable = (re_dfastate_t **) + calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (__glibc_unlikely (state->trtable == NULL)) + return false; + return true; + } + return false; + } + + err = re_node_set_alloc (&follows, ndests + 1); + if (__glibc_unlikely (err != REG_NOERROR)) + { + out_free: + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + return false; + } + + bitset_empty (acceptable); + + /* Then build the states for all destinations. */ + for (i = 0; i < ndests; ++i) + { + Idx next_node; + re_node_set_empty (&follows); + /* Merge the follows of this destination states. */ + for (j = 0; j < dests_node[i].nelem; ++j) + { + next_node = dfa->nexts[dests_node[i].elems[j]]; + if (next_node != -1) + { + err = re_node_set_merge (&follows, dfa->eclosures + next_node); + if (__glibc_unlikely (err != REG_NOERROR)) + goto out_free; + } + } + dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); + if (__glibc_unlikely (dest_states[i] == NULL && err != REG_NOERROR)) + goto out_free; + /* If the new state has context constraint, + build appropriate states for these contexts. */ + if (dest_states[i]->has_constraint) + { + dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_WORD); + if (__glibc_unlikely (dest_states_word[i] == NULL + && err != REG_NOERROR)) + goto out_free; + + if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) + need_word_trtable = true; + + dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_NEWLINE); + if (__glibc_unlikely (dest_states_nl[i] == NULL && err != REG_NOERROR)) + goto out_free; + } + else + { + dest_states_word[i] = dest_states[i]; + dest_states_nl[i] = dest_states[i]; + } + bitset_merge (acceptable, dests_ch[i]); + } + + if (!__glibc_unlikely (need_word_trtable)) + { + /* We don't care about whether the following character is a word + character, or we are in a single-byte character set so we can + discern by looking at the character code: allocate a + 256-entry transition table. */ + trtable = state->trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (__glibc_unlikely (trtable == NULL)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (__glibc_unlikely (elem & 1)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + if (dfa->word_char[i] & mask) + trtable[ch] = dest_states_word[j]; + else + trtable[ch] = dest_states[j]; + } + } + else + { + /* We care about whether the following character is a word + character, and we are in a multi-byte character set: discern + by looking at the character code: build two 256-entry + transition tables, one starting at trtable[0] and one + starting at trtable[SBC_MAX]. */ + trtable = state->word_trtable = + (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); + if (__glibc_unlikely (trtable == NULL)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (__glibc_unlikely (elem & 1)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + trtable[ch] = dest_states[j]; + trtable[ch + SBC_MAX] = dest_states_word[j]; + } + } + + /* new line */ + if (bitset_contain (acceptable, NEWLINE_CHAR)) + { + /* The current state accepts newline character. */ + for (j = 0; j < ndests; ++j) + if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) + { + /* k-th destination accepts newline character. */ + trtable[NEWLINE_CHAR] = dest_states_nl[j]; + if (need_word_trtable) + trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; + /* There must be only one destination which accepts + newline. See group_nodes_into_DFAstates. */ + break; + } + } + + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + return true; +} + +/* Group all nodes belonging to STATE into several destinations. + Then for all destinations, set the nodes belonging to the destination + to DESTS_NODE[i] and set the characters accepted by the destination + to DEST_CH[i]. Return the number of destinations if successful, + -1 on internal error. */ + +static Idx +group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + re_node_set *dests_node, bitset_t *dests_ch) +{ + reg_errcode_t err; + bool ok; + Idx i, j, k; + Idx ndests; /* Number of the destinations from 'state'. */ + bitset_t accepts; /* Characters a node can accept. */ + const re_node_set *cur_nodes = &state->nodes; + bitset_empty (accepts); + ndests = 0; + + /* For all the nodes belonging to 'state', */ + for (i = 0; i < cur_nodes->nelem; ++i) + { + re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + /* Enumerate all single byte character this node can accept. */ + if (type == CHARACTER) + bitset_set (accepts, node->opr.c); + else if (type == SIMPLE_BRACKET) + { + bitset_merge (accepts, node->opr.sbcset); + } + else if (type == OP_PERIOD) + { + if (dfa->mb_cur_max > 1) + bitset_merge (accepts, dfa->sb_char); + else + bitset_set_all (accepts); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } + else if (type == OP_UTF8_PERIOD) + { + if (ASCII_CHARS % BITSET_WORD_BITS == 0) + memset (accepts, -1, ASCII_CHARS / CHAR_BIT); + else + bitset_merge (accepts, utf8_sb_map); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } + else + continue; + + /* Check the 'accepts' and sift the characters which are not + match it the context. */ + if (constraint) + { + if (constraint & NEXT_NEWLINE_CONSTRAINT) + { + bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); + bitset_empty (accepts); + if (accepts_newline) + bitset_set (accepts, NEWLINE_CHAR); + else + continue; + } + if (constraint & NEXT_ENDBUF_CONSTRAINT) + { + bitset_empty (accepts); + continue; + } + + if (constraint & NEXT_WORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && !node->word_char) + { + bitset_empty (accepts); + continue; + } + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); + else + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= dfa->word_char[j]); + if (!any_set) + continue; + } + if (constraint & NEXT_NOTWORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && node->word_char) + { + bitset_empty (accepts); + continue; + } + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); + else + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~dfa->word_char[j]); + if (!any_set) + continue; + } + } + + /* Then divide 'accepts' into DFA states, or create a new + state. Above, we make sure that accepts is not empty. */ + for (j = 0; j < ndests; ++j) + { + bitset_t intersec; /* Intersection sets, see below. */ + bitset_t remains; + /* Flags, see below. */ + bitset_word_t has_intersec, not_subset, not_consumed; + + /* Optimization, skip if this state doesn't accept the character. */ + if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) + continue; + + /* Enumerate the intersection set of this state and 'accepts'. */ + has_intersec = 0; + for (k = 0; k < BITSET_WORDS; ++k) + has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; + /* And skip if the intersection set is empty. */ + if (!has_intersec) + continue; + + /* Then check if this state is a subset of 'accepts'. */ + not_subset = not_consumed = 0; + for (k = 0; k < BITSET_WORDS; ++k) + { + not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; + not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; + } + + /* If this state isn't a subset of 'accepts', create a + new group state, which has the 'remains'. */ + if (not_subset) + { + bitset_copy (dests_ch[ndests], remains); + bitset_copy (dests_ch[j], intersec); + err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); + if (__glibc_unlikely (err != REG_NOERROR)) + goto error_return; + ++ndests; + } + + /* Put the position in the current group. */ + ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); + if (__glibc_unlikely (! ok)) + goto error_return; + + /* If all characters are consumed, go to next node. */ + if (!not_consumed) + break; + } + /* Some characters remain, create a new group. */ + if (j == ndests) + { + bitset_copy (dests_ch[ndests], accepts); + err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); + if (__glibc_unlikely (err != REG_NOERROR)) + goto error_return; + ++ndests; + bitset_empty (accepts); + } + } + assume (ndests <= SBC_MAX); + return ndests; + error_return: + for (j = 0; j < ndests; ++j) + re_node_set_free (dests_node + j); + return -1; +} + +/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. + Return the number of the bytes the node accepts. + STR_IDX is the current index of the input string. + + This function handles the nodes which can accept one character, or + one collating element like '.', '[a-z]', opposite to the other nodes + can only accept one byte. */ + +#ifdef _LIBC +# include +#endif + +static int +check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, + const re_string_t *input, Idx str_idx) +{ + const re_token_t *node = dfa->nodes + node_idx; + int char_len, elem_len; + Idx i; + + if (__glibc_unlikely (node->type == OP_UTF8_PERIOD)) + { + unsigned char c = re_string_byte_at (input, str_idx), d; + if (__glibc_likely (c < 0xc2)) + return 0; + + if (str_idx + 2 > input->len) + return 0; + + d = re_string_byte_at (input, str_idx + 1); + if (c < 0xe0) + return (d < 0x80 || d > 0xbf) ? 0 : 2; + else if (c < 0xf0) + { + char_len = 3; + if (c == 0xe0 && d < 0xa0) + return 0; + } + else if (c < 0xf8) + { + char_len = 4; + if (c == 0xf0 && d < 0x90) + return 0; + } + else if (c < 0xfc) + { + char_len = 5; + if (c == 0xf8 && d < 0x88) + return 0; + } + else if (c < 0xfe) + { + char_len = 6; + if (c == 0xfc && d < 0x84) + return 0; + } + else + return 0; + + if (str_idx + char_len > input->len) + return 0; + + for (i = 1; i < char_len; ++i) + { + d = re_string_byte_at (input, str_idx + i); + if (d < 0x80 || d > 0xbf) + return 0; + } + return char_len; + } + + char_len = re_string_char_size_at (input, str_idx); + if (node->type == OP_PERIOD) + { + if (char_len <= 1) + return 0; + /* FIXME: I don't think this if is needed, as both '\n' + and '\0' are char_len == 1. */ + /* '.' accepts any one character except the following two cases. */ + if ((!(dfa->syntax & RE_DOT_NEWLINE) + && re_string_byte_at (input, str_idx) == '\n') + || ((dfa->syntax & RE_DOT_NOT_NULL) + && re_string_byte_at (input, str_idx) == '\0')) + return 0; + return char_len; + } + + elem_len = re_string_elem_size_at (input, str_idx); + if ((elem_len <= 1 && char_len <= 1) || char_len == 0) + return 0; + + if (node->type == COMPLEX_BRACKET) + { + const re_charset_t *cset = node->opr.mbcset; +#ifdef _LIBC + const unsigned char *pin + = ((const unsigned char *) re_string_get_buffer (input) + str_idx); + Idx j; + uint32_t nrules; +#endif + int match_len = 0; + wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) + ? re_string_wchar_at (input, str_idx) : 0); + + /* match with multibyte character? */ + for (i = 0; i < cset->nmbchars; ++i) + if (wc == cset->mbchars[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + /* match with character_class? */ + for (i = 0; i < cset->nchar_classes; ++i) + { + wctype_t wt = cset->char_classes[i]; + if (__iswctype (wc, wt)) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + +#ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + unsigned int in_collseq = 0; + const int32_t *table, *indirect; + const unsigned char *weights, *extra; + const char *collseqwc; + + /* match with collating_symbol? */ + if (cset->ncoll_syms) + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + for (i = 0; i < cset->ncoll_syms; ++i) + { + const unsigned char *coll_sym = extra + cset->coll_syms[i]; + /* Compare the length of input collating element and + the length of current collating element. */ + if (*coll_sym != elem_len) + continue; + /* Compare each bytes. */ + for (j = 0; j < *coll_sym; j++) + if (pin[j] != coll_sym[1 + j]) + break; + if (j == *coll_sym) + { + /* Match if every bytes is equal. */ + match_len = j; + goto check_node_accept_bytes_match; + } + } + + if (cset->nranges) + { + if (elem_len <= char_len) + { + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + in_collseq = __collseq_table_lookup (collseqwc, wc); + } + else + in_collseq = find_collation_sequence_value (pin, elem_len); + } + /* match with range expression? */ + /* FIXME: Implement rational ranges here, too. */ + for (i = 0; i < cset->nranges; ++i) + if (cset->range_starts[i] <= in_collseq + && in_collseq <= cset->range_ends[i]) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + + /* match with equivalence_class? */ + if (cset->nequiv_classes) + { + const unsigned char *cp = pin; + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + int32_t idx = findidx (table, indirect, extra, &cp, elem_len); + int32_t rule = idx >> 24; + idx &= 0xffffff; + if (idx > 0) + { + size_t weight_len = weights[idx]; + for (i = 0; i < cset->nequiv_classes; ++i) + { + int32_t equiv_class_idx = cset->equiv_classes[i]; + int32_t equiv_class_rule = equiv_class_idx >> 24; + equiv_class_idx &= 0xffffff; + if (weights[equiv_class_idx] == weight_len + && equiv_class_rule == rule + && memcmp (weights + idx + 1, + weights + equiv_class_idx + 1, + weight_len) == 0) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + } + } + } + } + else +#endif /* _LIBC */ + { + /* match with range expression? */ + for (i = 0; i < cset->nranges; ++i) + { + if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + } + check_node_accept_bytes_match: + if (!cset->non_match) + return match_len; + else + { + if (match_len > 0) + return 0; + else + return (elem_len > char_len) ? elem_len : char_len; + } + } + return 0; +} + +#ifdef _LIBC +static unsigned int +find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) +{ + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules == 0) + { + if (mbs_len == 1) + { + /* No valid character. Match it as a single byte character. */ + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + return collseq[mbs[0]]; + } + return UINT_MAX; + } + else + { + int32_t idx; + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + int32_t extrasize = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; + + for (idx = 0; idx < extrasize;) + { + int mbs_cnt; + bool found = false; + int32_t elem_mbs_len; + /* Skip the name of collating element name. */ + idx = idx + extra[idx] + 1; + elem_mbs_len = extra[idx++]; + if (mbs_len == elem_mbs_len) + { + for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) + if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) + break; + if (mbs_cnt == elem_mbs_len) + /* Found the entry. */ + found = true; + } + /* Skip the byte sequence of the collating element. */ + idx += elem_mbs_len; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + /* Skip the wide char sequence of the collating element. */ + idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1); + /* If we found the entry, return the sequence value. */ + if (found) + return *(uint32_t *) (extra + idx); + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + } + return UINT_MAX; + } +} +#endif /* _LIBC */ + +/* Check whether the node accepts the byte which is IDX-th + byte of the INPUT. */ + +static bool +check_node_accept (const re_match_context_t *mctx, const re_token_t *node, + Idx idx) +{ + unsigned char ch; + ch = re_string_byte_at (&mctx->input, idx); + switch (node->type) + { + case CHARACTER: + if (node->opr.c != ch) + return false; + break; + + case SIMPLE_BRACKET: + if (!bitset_contain (node->opr.sbcset, ch)) + return false; + break; + + case OP_UTF8_PERIOD: + if (ch >= ASCII_CHARS) + return false; + FALLTHROUGH; + case OP_PERIOD: + if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) + || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) + return false; + break; + + default: + return false; + } + + if (node->constraint) + { + /* The node has constraints. Check whether the current context + satisfies the constraints. */ + unsigned int context = re_string_context_at (&mctx->input, idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + return false; + } + + return true; +} + +/* Extend the buffers, if the buffers have run out. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +extend_buffers (re_match_context_t *mctx, int min_len) +{ + reg_errcode_t ret; + re_string_t *pstr = &mctx->input; + + /* Avoid overflow. */ + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2 + <= pstr->bufs_len)) + return REG_ESPACE; + + /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ + ret = re_string_realloc_buffers (pstr, + MAX (min_len, + MIN (pstr->len, pstr->bufs_len * 2))); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + + if (mctx->state_log != NULL) + { + /* And double the length of state_log. */ + /* XXX We have no indication of the size of this buffer. If this + allocation fail we have no indication that the state_log array + does not have the right size. */ + re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, + pstr->bufs_len + 1); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + mctx->state_log = new_array; + } + + /* Then reconstruct the buffers. */ + if (pstr->icase) + { + if (pstr->mb_cur_max > 1) + { + ret = build_wcs_upper_buffer (pstr); + if (__glibc_unlikely (ret != REG_NOERROR)) + return ret; + } + else + build_upper_buffer (pstr); + } + else + { + if (pstr->mb_cur_max > 1) + build_wcs_buffer (pstr); + else + { + if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + } + return REG_NOERROR; +} + + +/* Functions for matching context. */ + +/* Initialize MCTX. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) +{ + mctx->eflags = eflags; + mctx->match_last = -1; + if (n > 0) + { + /* Avoid overflow. */ + size_t max_object_size = + MAX (sizeof (struct re_backref_cache_entry), + sizeof (re_sub_match_top_t *)); + if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n)) + return REG_ESPACE; + + mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); + mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); + if (__glibc_unlikely (mctx->bkref_ents == NULL || mctx->sub_tops == NULL)) + return REG_ESPACE; + } + /* Already zero-ed by the caller. + else + mctx->bkref_ents = NULL; + mctx->nbkref_ents = 0; + mctx->nsub_tops = 0; */ + mctx->abkref_ents = n; + mctx->max_mb_elem_len = 1; + mctx->asub_tops = n; + return REG_NOERROR; +} + +/* Clean the entries which depend on the current input in MCTX. + This function must be invoked when the matcher changes the start index + of the input, or changes the input string. */ + +static void +match_ctx_clean (re_match_context_t *mctx) +{ + Idx st_idx; + for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) + { + Idx sl_idx; + re_sub_match_top_t *top = mctx->sub_tops[st_idx]; + for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) + { + re_sub_match_last_t *last = top->lasts[sl_idx]; + re_free (last->path.array); + re_free (last); + } + re_free (top->lasts); + if (top->path) + { + re_free (top->path->array); + re_free (top->path); + } + re_free (top); + } + + mctx->nsub_tops = 0; + mctx->nbkref_ents = 0; +} + +/* Free all the memory associated with MCTX. */ + +static void +match_ctx_free (re_match_context_t *mctx) +{ + /* First, free all the memory associated with MCTX->SUB_TOPS. */ + match_ctx_clean (mctx); + re_free (mctx->sub_tops); + re_free (mctx->bkref_ents); +} + +/* Add a new backreference entry to MCTX. + Note that we assume that caller never call this function with duplicate + entry, and call with STR_IDX which isn't smaller than any existing entry. +*/ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, + Idx to) +{ + if (mctx->nbkref_ents >= mctx->abkref_ents) + { + struct re_backref_cache_entry* new_entry; + new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, + mctx->abkref_ents * 2); + if (__glibc_unlikely (new_entry == NULL)) + { + re_free (mctx->bkref_ents); + return REG_ESPACE; + } + mctx->bkref_ents = new_entry; + memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', + sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); + mctx->abkref_ents *= 2; + } + if (mctx->nbkref_ents > 0 + && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) + mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; + + mctx->bkref_ents[mctx->nbkref_ents].node = node; + mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; + mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; + mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; + + /* This is a cache that saves negative results of check_dst_limits_calc_pos. + If bit N is clear, means that this entry won't epsilon-transition to + an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If + it is set, check_dst_limits_calc_pos_1 will recurse and try to find one + such node. + + A backreference does not epsilon-transition unless it is empty, so set + to all zeros if FROM != TO. */ + mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map + = (from == to ? -1 : 0); + + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; + if (mctx->max_mb_elem_len < to - from) + mctx->max_mb_elem_len = to - from; + return REG_NOERROR; +} + +/* Return the first entry with the same str_idx, or -1 if none is + found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ + +static Idx +search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) +{ + Idx left, right, mid, last; + last = right = mctx->nbkref_ents; + for (left = 0; left < right;) + { + mid = (left + right) / 2; + if (mctx->bkref_ents[mid].str_idx < str_idx) + left = mid + 1; + else + right = mid; + } + if (left < last && mctx->bkref_ents[left].str_idx == str_idx) + return left; + else + return -1; +} + +/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches + at STR_IDX. */ + +static reg_errcode_t +__attribute_warn_unused_result__ +match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) +{ + DEBUG_ASSERT (mctx->sub_tops != NULL); + DEBUG_ASSERT (mctx->asub_tops > 0); + if (__glibc_unlikely (mctx->nsub_tops == mctx->asub_tops)) + { + Idx new_asub_tops = mctx->asub_tops * 2; + re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, + re_sub_match_top_t *, + new_asub_tops); + if (__glibc_unlikely (new_array == NULL)) + return REG_ESPACE; + mctx->sub_tops = new_array; + mctx->asub_tops = new_asub_tops; + } + mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); + if (__glibc_unlikely (mctx->sub_tops[mctx->nsub_tops] == NULL)) + return REG_ESPACE; + mctx->sub_tops[mctx->nsub_tops]->node = node; + mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; + return REG_NOERROR; +} + +/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches + at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. + Return the new entry if successful, NULL if memory is exhausted. */ + +static re_sub_match_last_t * +match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) +{ + re_sub_match_last_t *new_entry; + if (__glibc_unlikely (subtop->nlasts == subtop->alasts)) + { + Idx new_alasts = 2 * subtop->alasts + 1; + re_sub_match_last_t **new_array = re_realloc (subtop->lasts, + re_sub_match_last_t *, + new_alasts); + if (__glibc_unlikely (new_array == NULL)) + return NULL; + subtop->lasts = new_array; + subtop->alasts = new_alasts; + } + new_entry = calloc (1, sizeof (re_sub_match_last_t)); + if (__glibc_likely (new_entry != NULL)) + { + subtop->lasts[subtop->nlasts] = new_entry; + new_entry->node = node; + new_entry->str_idx = str_idx; + ++subtop->nlasts; + } + return new_entry; +} + +static void +sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) +{ + sctx->sifted_states = sifted_sts; + sctx->limited_states = limited_sts; + sctx->last_node = last_node; + sctx->last_str_idx = last_str_idx; + re_node_set_init_empty (&sctx->limits); +} diff --git a/cross/lib/root-uid.h b/cross/lib/root-uid.h new file mode 100644 index 00000000000..1905575e47b --- /dev/null +++ b/cross/lib/root-uid.h @@ -0,0 +1,30 @@ +/* The user ID that always has appropriate privileges in the POSIX sense. + + Copyright 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef ROOT_UID_H_ +#define ROOT_UID_H_ + +/* The user ID that always has appropriate privileges in the POSIX sense. */ +#ifdef __TANDEM +# define ROOT_UID 65535 +#else +# define ROOT_UID 0 +#endif + +#endif diff --git a/cross/lib/save-cwd.c b/cross/lib/save-cwd.c new file mode 100644 index 00000000000..7c517d1c819 --- /dev/null +++ b/cross/lib/save-cwd.c @@ -0,0 +1,89 @@ +/* save-cwd.c -- Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2023 Free Software + Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Gnulib needs to save and restore the current working directory to + fully emulate functions like fstatat. But Emacs doesn't care what + the current working directory is; it always uses absolute file + names. This module replaces the Gnulib module by omitting the code + that Emacs does not need. */ + +#include + +#include "save-cwd.h" + +#include +#include + +/* Record the location of the current working directory in CWD so that + the program may change to other directories and later use restore_cwd + to return to the recorded location. This function may allocate + space using malloc (via getcwd) or leave a file descriptor open; + use free_cwd to perform the necessary free or close. Upon failure, + no memory is allocated, any locally opened file descriptors are + closed; return non-zero -- in that case, free_cwd need not be + called, but doing so is ok. Otherwise, return zero. + + The _raison d'etre_ for this interface is that the working directory + is sometimes inaccessible, and getcwd is not robust or as efficient. + So, we prefer to use the open/fchdir approach, but fall back on + getcwd if necessary. This module works for most cases with just + the getcwd-lgpl module, but to be truly robust, use the getcwd module. + + Some systems lack fchdir altogether: e.g., OS/2, pre-2001 Cygwin, + SCO Xenix. Also, SunOS 4 and Irix 5.3 provide the function, yet it + doesn't work for partitions on which auditing is enabled. If + you're still using an obsolete system with these problems, please + send email to the maintainer of this code. */ + +#if !defined HAVE_FCHDIR && !defined fchdir +# define fchdir(fd) (-1) +#endif + +int +save_cwd (struct saved_cwd *cwd) +{ + cwd->desc = open (".", O_SEARCH | O_CLOEXEC); + /* The 'name' member is present only to minimize differences from + gnulib. Initialize it to zero, if only to simplify debugging. */ + cwd->name = 0; + return 0; +} + +/* Change to recorded location, CWD, in directory hierarchy. + Upon failure, return -1 (errno is set by chdir or fchdir). + Upon success, return zero. */ + +int +restore_cwd (const struct saved_cwd *cwd) +{ + /* Restore the previous directory if possible, to avoid tying down + the file system of the new directory (Bug#18232). + Don't worry if fchdir fails, as Emacs doesn't care what the + working directory is. The fchdir call is inside an 'if' merely to + pacify compilers that complain if fchdir's return value is ignored. */ + if (fchdir (cwd->desc) == 0) + return 0; + + return 0; +} + +void +free_cwd (struct saved_cwd *cwd) +{ + close (cwd->desc); +} diff --git a/cross/lib/save-cwd.h b/cross/lib/save-cwd.h new file mode 100644 index 00000000000..d089b0e2145 --- /dev/null +++ b/cross/lib/save-cwd.h @@ -0,0 +1,34 @@ +/* Save and restore current working directory. + + Copyright (C) 1995, 1997-1998, 2003, 2009-2023 Free Software Foundation, + Inc. + + This program is free software: you can 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 . */ + +/* Written by Jim Meyering. */ + +#ifndef SAVE_CWD_H +# define SAVE_CWD_H 1 + +struct saved_cwd + { + int desc; + char *name; + }; + +int save_cwd (struct saved_cwd *cwd); +int restore_cwd (const struct saved_cwd *cwd); +void free_cwd (struct saved_cwd *cwd); + +#endif /* SAVE_CWD_H */ diff --git a/cross/lib/scratch_buffer.h b/cross/lib/scratch_buffer.h new file mode 100644 index 00000000000..4cf60d232b7 --- /dev/null +++ b/cross/lib/scratch_buffer.h @@ -0,0 +1,117 @@ +/* Variable-sized buffer with on-stack default allocation. + Copyright (C) 2017-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert, 2017. */ + +#ifndef _GL_SCRATCH_BUFFER_H +#define _GL_SCRATCH_BUFFER_H + +/* Scratch buffers with a default stack allocation and fallback to + heap allocation. It is expected that this function is used in this + way: + + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) + if (!scratch_buffer_grow (&tmpbuf)) + return -1; + + scratch_buffer_free (&tmpbuf); + return 0; + + The allocation functions (scratch_buffer_grow, + scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make + sure that the heap allocation, if any, is freed, so that the code + above does not have a memory leak. The buffer still remains in a + state that can be deallocated using scratch_buffer_free, so a loop + like this is valid as well: + + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) + if (!scratch_buffer_grow (&tmpbuf)) + break; + + scratch_buffer_free (&tmpbuf); + + scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed + to grow the buffer by at least 512 bytes. This means that when + using the scratch buffer as a backing store for a non-character + array whose element size, in bytes, is 512 or smaller, the scratch + buffer only has to grow once to make room for at least one more + element. +*/ + +/* Scratch buffer. Must be initialized with scratch_buffer_init + before its use. */ +struct scratch_buffer; + +/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space + and BUFFER->length reflects the available space. */ +#if 0 +extern void scratch_buffer_init (struct scratch_buffer *buffer); +#endif + +/* Deallocates *BUFFER (if it was heap-allocated). */ +#if 0 +extern void scratch_buffer_free (struct scratch_buffer *buffer); +#endif + +/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT + preserved. Return true on success, false on allocation failure (in + which case the old buffer is freed). On success, the new buffer is + larger than the previous size. On failure, *BUFFER is deallocated, + but remains in a free-able state, and errno is set. */ +#if 0 +extern bool scratch_buffer_grow (struct scratch_buffer *buffer); +#endif + +/* Like scratch_buffer_grow, but preserve the old buffer + contents on success, as a prefix of the new buffer. */ +#if 0 +extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer); +#endif + +/* Grow *BUFFER so that it can store at least NELEM elements of SIZE + bytes. The buffer contents are NOT preserved. Both NELEM and SIZE + can be zero. Return true on success, false on allocation failure + (in which case the old buffer is freed, but *BUFFER remains in a + free-able state, and errno is set). It is unspecified whether this + function can reduce the array size. */ +#if 0 +extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer, + size_t nelem, size_t size); +#endif + + +/* The implementation is imported from glibc. */ + +/* Avoid possible conflicts with symbols exported by the GNU libc. */ +#define __libc_scratch_buffer_grow gl_scratch_buffer_grow +#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve +#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size + +#ifndef _GL_LIKELY +/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ +# define _GL_LIKELY(cond) __builtin_expect ((cond), 1) +# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0) +#endif + +#include + +#endif /* _GL_SCRATCH_BUFFER_H */ diff --git a/cross/lib/set-permissions.c b/cross/lib/set-permissions.c new file mode 100644 index 00000000000..1d6732cc78f --- /dev/null +++ b/cross/lib/set-permissions.c @@ -0,0 +1,847 @@ +/* Set permissions of a file. -*- coding: utf-8 -*- + + Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include "acl-internal.h" + +#if USE_ACL +# if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ +# if HAVE_ACL_GET_FILE && !HAVE_ACL_TYPE_EXTENDED + +static acl_t +acl_from_mode (mode_t mode) +{ +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + char acl_text[] = "u::---,g::---,o::---,"; +# else /* FreeBSD, IRIX, Cygwin >= 2.5 */ + char acl_text[] = "u::---,g::---,o::---"; +# endif + + if (mode & S_IRUSR) acl_text[ 3] = 'r'; + if (mode & S_IWUSR) acl_text[ 4] = 'w'; + if (mode & S_IXUSR) acl_text[ 5] = 'x'; + if (mode & S_IRGRP) acl_text[10] = 'r'; + if (mode & S_IWGRP) acl_text[11] = 'w'; + if (mode & S_IXGRP) acl_text[12] = 'x'; + if (mode & S_IROTH) acl_text[17] = 'r'; + if (mode & S_IWOTH) acl_text[18] = 'w'; + if (mode & S_IXOTH) acl_text[19] = 'x'; + + return acl_from_text (acl_text); +} +# endif +# endif + +# if HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ +static int +set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) +{ +# ifdef ACE_GETACL + /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 + file systems (whereas the other ones are used in UFS file systems). */ + + /* The flags in the ace_t structure changed in a binary incompatible way + when ACL_NO_TRIVIAL etc. were introduced in version 1.15. + How to distinguish the two conventions at runtime? + We fetch the existing ACL. In the old convention, usually three ACEs have + a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. + In the new convention, these values are not used. */ + int convention; + + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) + }; + ace_t buf[alloc_init]; + size_t alloc = alloc_init; + ace_t *entries = buf; + ace_t *malloced = NULL; + int count; + + for (;;) + { + count = (desc != -1 + ? facl (desc, ACE_GETACL, alloc, entries) + : acl (name, ACE_GETACL, alloc, entries)); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + + if (count <= 0) + convention = -1; + else + { + int i; + + convention = 0; + for (i = 0; i < count; i++) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) + { + convention = 1; + break; + } + } + free (malloced); + } + + if (convention >= 0) + { + ace_t entries[6]; + int count; + int ret; + + if (convention) + { + /* Running on Solaris 10. */ + entries[0].a_type = OLD_ALLOW; + entries[0].a_flags = OLD_ACE_OWNER; + entries[0].a_who = 0; /* irrelevant */ + entries[0].a_access_mask = (mode >> 6) & 7; + entries[1].a_type = OLD_ALLOW; + entries[1].a_flags = OLD_ACE_GROUP; + entries[1].a_who = 0; /* irrelevant */ + entries[1].a_access_mask = (mode >> 3) & 7; + entries[2].a_type = OLD_ALLOW; + entries[2].a_flags = OLD_ACE_OTHER; + entries[2].a_who = 0; + entries[2].a_access_mask = mode & 7; + count = 3; + } + else + { + /* Running on Solaris 10 (newer version) or Solaris 11. + The details here were found through "/bin/ls -lvd somefiles". */ + entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[0].a_flags = NEW_ACE_OWNER; + entries[0].a_who = 0; /* irrelevant */ + entries[0].a_access_mask = 0; + entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[1].a_flags = NEW_ACE_OWNER; + entries[1].a_who = 0; /* irrelevant */ + entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + if (mode & 0400) + entries[1].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[0].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0200) + entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0100) + entries[1].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[0].a_access_mask |= NEW_ACE_EXECUTE; + entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[2].a_who = 0; /* irrelevant */ + entries[2].a_access_mask = 0; + entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[3].a_who = 0; /* irrelevant */ + entries[3].a_access_mask = 0; + if (mode & 0040) + entries[3].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[2].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0020) + entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0010) + entries[3].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[2].a_access_mask |= NEW_ACE_EXECUTE; + entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[4].a_flags = NEW_ACE_EVERYONE; + entries[4].a_who = 0; + entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[5].a_flags = NEW_ACE_EVERYONE; + entries[5].a_who = 0; + entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE; + if (mode & 0004) + entries[5].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[4].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0002) + entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0001) + entries[5].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[4].a_access_mask |= NEW_ACE_EXECUTE; + count = 6; + } + if (desc != -1) + ret = facl (desc, ACE_SETACL, count, entries); + else + ret = acl (name, ACE_SETACL, count, entries); + if (ret < 0 && errno != EINVAL && errno != ENOTSUP) + { + if (errno == ENOSYS) + { + *must_chmod = true; + return 0; + } + return -1; + } + if (ret == 0) + return 0; + } +# endif + + { + aclent_t entries[3]; + int ret; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = OTHER_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = mode & 7; + + if (desc != -1) + ret = facl (desc, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + else + ret = acl (name, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP) + { + *must_chmod = true; + return 0; + } + return -1; + } + return 0; + } +} + +# elif HAVE_GETACL /* HP-UX */ +static int +context_acl_from_mode (struct permission_context *ctx, const char *name, int desc) +{ + struct stat statbuf; + int ret; + + if (desc != -1) + ret = fstat (desc, &statbuf); + else + ret = stat (name, &statbuf); + if (ret < 0) + return -1; + + ctx->entries[0].uid = statbuf.st_uid; + ctx->entries[0].gid = ACL_NSGROUP; + ctx->entries[0].mode = (ctx->mode >> 6) & 7; + ctx->entries[1].uid = ACL_NSUSER; + ctx->entries[1].gid = statbuf.st_gid; + ctx->entries[1].mode = (ctx->mode >> 3) & 7; + ctx->entries[2].uid = ACL_NSUSER; + ctx->entries[2].gid = ACL_NSGROUP; + ctx->entries[2].mode = ctx->mode & 7; + ctx->count = 3; + return 0; +} + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ +static int +context_aclv_from_mode (struct permission_context *ctx) +{ + int ret; + + ctx->aclv_entries[0].a_type = USER_OBJ; + ctx->aclv_entries[0].a_id = 0; /* irrelevant */ + ctx->aclv_entries[0].a_perm = (ctx->mode >> 6) & 7; + ctx->aclv_entries[1].a_type = GROUP_OBJ; + ctx->aclv_entries[1].a_id = 0; /* irrelevant */ + ctx->aclv_entries[1].a_perm = (ctx->mode >> 3) & 7; + ctx->aclv_entries[2].a_type = CLASS_OBJ; + ctx->aclv_entries[2].a_id = 0; + ctx->aclv_entries[2].a_perm = (ctx->mode >> 3) & 7; + ctx->aclv_entries[3].a_type = OTHER_OBJ; + ctx->aclv_entries[3].a_id = 0; + ctx->aclv_entries[3].a_perm = ctx->mode & 7; + ctx->aclv_count = 4; + + ret = aclsort (ctx->aclv_count, 1, ctx->aclv_entries); + if (ret > 0) + abort (); + return ret; +} +# endif + +# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ +static int +set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) +{ + acl_type_list_t types; + size_t types_size = sizeof (types); + acl_type_t type; + + if (aclx_gettypes (name, &types, &types_size) < 0 + || types.num_entries == 0) + { + *must_chmod = true; + return 0; + } + + /* XXX Do we need to clear all types of ACLs for the given file, or is it + sufficient to clear the first one? */ + type = types.entries[0]; + if (type.u64 == ACL_AIXC) + { + union { struct acl a; char room[128]; } u; + int ret; + + u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ + u.a.acl_mode = mode & ~(S_IXACL | 0777); + u.a.u_access = (mode >> 6) & 7; + u.a.g_access = (mode >> 3) & 7; + u.a.o_access = mode & 7; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + else if (type.u64 == ACL_NFS4) + { + union { nfs4_acl_int_t a; char room[128]; } u; + nfs4_ace_int_t *ace; + int ret; + + u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION; + u.a.aclEntryN = 0; + ace = &u.a.aclEntry[0]; + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_OWNER; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0200 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0100 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_GROUP; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0020 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0010 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_EVERYONE; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0002 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0001 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + u.a.aclLength = (char *) ace - (char *) &u.a; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + + *must_chmod = true; + return 0; +} + +# elif HAVE_STATACL /* older AIX */ +static int +context_acl_from_mode (struct permission_context *ctx) +{ + ctx->u.a.acl_len = (char *) &ctx->u.a.acl_ext[0] - (char *) &ctx->u.a; /* no entries */ + ctx->u.a.acl_mode = ctx->mode & ~(S_IXACL | 0777); + ctx->u.a.u_access = (ctx->mode >> 6) & 7; + ctx->u.a.g_access = (ctx->mode >> 3) & 7; + ctx->u.a.o_access = ctx->mode & 7; + ctx->have_u = true; + return 0; +} + +# elif HAVE_ACLSORT /* NonStop Kernel */ +static int +context_acl_from_mode (struct permission_context *ctx) +{ + int ret; + + ctx->entries[0].a_type = USER_OBJ; + ctx->entries[0].a_id = 0; /* irrelevant */ + ctx->entries[0].a_perm = (ctx->mode >> 6) & 7; + ctx->entries[1].a_type = GROUP_OBJ; + ctx->entries[1].a_id = 0; /* irrelevant */ + ctx->entries[1].a_perm = (ctx->mode >> 3) & 7; + ctx->entries[2].a_type = CLASS_OBJ; + ctx->entries[2].a_id = 0; + ctx->entries[2].a_perm = (ctx->mode >> 3) & 7; + ctx->entries[3].a_type = OTHER_OBJ; + ctx->entries[3].a_id = 0; + ctx->entries[3].a_perm = ctx->mode & 7; + ctx->count = 4; + + ret = aclsort (ctx->count, 1, entries); + if (ret > 0) + abort (); + return ret; +} +# endif + +static int +set_acls (struct permission_context *ctx, const char *name, int desc, + int from_mode, bool *must_chmod, bool *acls_set) +{ + int ret = 0; + +# if HAVE_ACL_GET_FILE + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ + +# ifndef HAVE_ACL_FROM_TEXT +# error Must have acl_from_text (see POSIX 1003.1e draft 17). +# endif +# ifndef HAVE_ACL_DELETE_DEF_FILE +# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). +# endif + + if (! ctx->acls_not_supported) + { + if (ret == 0 && from_mode) + { + if (ctx->acl) + acl_free (ctx->acl); + ctx->acl = acl_from_mode (ctx->mode); + if (ctx->acl == NULL) + ret = -1; + } + + if (ret == 0 && ctx->acl) + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, ctx->acl); + else + ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl); + if (ret != 0) + { + if (! acl_errno_valid (errno)) + { + ctx->acls_not_supported = true; + if (from_mode || acl_access_nontrivial (ctx->acl) == 0) + ret = 0; + } + } + else + { + *acls_set = true; + if (S_ISDIR(ctx->mode)) + { + if (! from_mode && ctx->default_acl && + acl_default_nontrivial (ctx->default_acl)) + ret = acl_set_file (name, ACL_TYPE_DEFAULT, + ctx->default_acl); + else + ret = acl_delete_def_file (name); + } + } + } + } + +# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */ + + /* File systems either support POSIX ACLs (for example, ufs) or NFS4 ACLs + (for example, zfs). */ + + /* TODO: Implement setting ACLs once get_permissions() reads them. */ + +# endif + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + if (ctx->acl == NULL) + { + acl_t acl; + + /* Remove ACLs if the file has ACLs. */ + if (HAVE_ACL_GET_FD && desc != -1) + acl = acl_get_fd (desc); + else + acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (acl) + { + acl_free (acl); + + acl = acl_init (0); + if (acl) + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, acl); + else + ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); + acl_free (acl); + } + else + ret = -1; + } + } + else + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, ctx->acl); + else + ret = acl_set_file (name, ACL_TYPE_EXTENDED, ctx->acl); + if (ret != 0) + { + if (! acl_errno_valid (errno) + && ! acl_extended_nontrivial (ctx->acl)) + ret = 0; + } + } + *acls_set = true; + +# endif + +# elif defined GETACL /* Solaris, Cygwin, not HP-UX */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ + + /* If both ace_entries and entries are available, try SETACL before + ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL + can. */ + + if (from_mode) + return set_acls_from_mode (name, desc, ctx->mode, must_chmod); + + if (ret == 0 && ctx->count) + { + if (desc != -1) + ret = facl (desc, SETACL, ctx->count, ctx->entries); + else + ret = acl (name, SETACL, ctx->count, ctx->entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + && acl_nontrivial (ctx->count, ctx->entries) == 0) + ret = 0; + } + else + *acls_set = true; + } + +# ifdef ACE_GETACL + if (ret == 0 && ctx->ace_count) + { + if (desc != -1) + ret = facl (desc, ACE_SETACL, ctx->ace_count, ctx->ace_entries); + else + ret = acl (name, ACE_SETACL, ctx->ace_count, ctx->ace_entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) + && acl_ace_nontrivial (ctx->ace_count, ctx->ace_entries) == 0) + ret = 0; + } + else + *acls_set = true; + } +# endif + +# elif HAVE_GETACL /* HP-UX */ + + if (from_mode) + ret = context_acl_from_mode (ctx, name, desc); + + if (ret == 0 && ctx->count > 0) + { + if (desc != -1) + ret = fsetacl (desc, ctx->count, ctx->entries); + else + ret = setacl (name, ctx->count, ctx->entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + && (from_mode || !acl_nontrivial (ctx->count, ctx->entries))) + ret = 0; + } + else + *acls_set = true; + } + +# if HAVE_ACLV_H + if (from_mode) + ret = context_aclv_from_mode (ctx); + + if (ret == 0 && ctx->aclv_count > 0) + { + ret = acl ((char *) name, ACL_SET, ctx->aclv_count, ctx->aclv_entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries))) + ret = 0; + } + else + *acls_set = true; + } +# endif + +# elif HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ + + /* TODO: Implement setting ACLs once get_permissions() reads them. */ + + if (from_mode) + ret = set_acls_from_mode (name, desc, mode, must_chmod); + +# elif HAVE_STATACL /* older AIX */ + + if (from_mode) + ret = context_acl_from_mode (ctx); + + if (ret == 0 && ctx->have_u) + { + if (desc != -1) + ret = fchacl (desc, &ctx->u.a, ctx->u.a.acl_len); + else + ret = chacl ((char *) name, &ctx->u.a, ctx->u.a.acl_len); + if (ret < 0) + { + if (errno == ENOSYS && from_mode) + ret = 0; + } + else + *acls_set = true; + } + +# elif HAVE_ACLSORT /* NonStop Kernel */ + + if (from_mode) + ret = context_acl_from_mode (ctx); + + if (ret == 0 && ctx->count) + { + ret = acl ((char *) name, ACL_SET, ctx->count, ctx->entries); + if (ret != 0) + { + if (!acl_nontrivial (ctx->count, ctx->entries)) + ret = 0; + } + else + *acls_set = true; + } + +# else /* No ACLs */ + + /* Nothing to do. */ + +# endif + + return ret; +} +#endif + +/* If DESC is a valid file descriptor use fchmod to change the + file's mode to MODE on systems that have fchmod. On systems + that don't have fchmod and if DESC is invalid, use chmod on + NAME instead. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +chmod_or_fchmod (const char *name, int desc, mode_t mode) +{ + if (HAVE_FCHMOD && desc != -1) + return fchmod (desc, mode); + else + return chmod (name, mode); +} + +/* Set the permissions in CTX on a file. If DESC is a valid file descriptor, + use file descriptor operations, else use filename based operations on NAME. + If access control lists are not available, fchmod the target file to the + mode in CTX. Also sets the non-permission bits of the destination file + (S_ISUID, S_ISGID, S_ISVTX) to those from the mode in CTX if any are set. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +set_permissions (struct permission_context *ctx, const char *name, int desc) +{ + _GL_UNUSED bool acls_set = false; + bool early_chmod; + bool must_chmod = false; + int ret = 0; + +#if USE_ACL +# if HAVE_STATACL + /* older AIX */ + /* There is no need to call chmod_or_fchmod, since the mode + bits S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ + + early_chmod = false; +# else + /* All other platforms */ + /* On Cygwin, it is necessary to call chmod before acl, because + chmod can change the contents of the ACL (in ways that don't + change the allowed accesses, but still visible). */ + + early_chmod = (! MODE_INSIDE_ACL || (ctx->mode & (S_ISUID | S_ISGID | S_ISVTX))); +# endif +#else + /* No ACLs */ + + early_chmod = true; +#endif + + if (early_chmod) + { + ret = chmod_or_fchmod (name, desc, ctx->mode); + if (ret != 0) + return -1; + } + +#if USE_ACL + ret = set_acls (ctx, name, desc, false, &must_chmod, &acls_set); + if (! acls_set) + { + int saved_errno = ret ? errno : 0; + + /* If we can't set an acl which we expect to be able to set, try setting + the permissions to ctx->mode. Due to possible inherited permissions, + we cannot simply chmod. */ + + ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set); + if (! acls_set) + must_chmod = true; + + if (saved_errno) + { + errno = saved_errno; + ret = -1; + } + } +#endif + + if (must_chmod && ! early_chmod) + { + int saved_errno = ret ? errno : 0; + + ret = chmod_or_fchmod (name, desc, ctx->mode); + + if (saved_errno) + { + errno = saved_errno; + ret = -1; + } + } + + return ret; +} diff --git a/cross/lib/sha1.c b/cross/lib/sha1.c new file mode 100644 index 00000000000..80f0b7a3314 --- /dev/null +++ b/cross/lib/sha1.c @@ -0,0 +1,360 @@ +/* sha1.c - Functions to compute SHA1 message digest of files or + memory blocks according to the NIST specification FIPS-180-1. + + Copyright (C) 2000-2001, 2003-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Scott G. Miller + Credits: + Robert Klep -- Expansion function fix +*/ + +#include + +/* Specification. */ +#if HAVE_OPENSSL_SHA1 +# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE +#endif +#include "sha1.h" + +#include +#include + +#include +#ifdef WORDS_BIGENDIAN +# define SWAP(n) (n) +#else +# define SWAP(n) bswap_32 (n) +#endif + +#if ! HAVE_OPENSSL_SHA1 + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Take a pointer to a 160 bit block of data (five 32 bit ints) and + initialize it to the start constants of the SHA1 algorithm. This + must be called before using hash in the call to sha1_hash. */ +void +sha1_init_ctx (struct sha1_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + ctx->E = 0xc3d2e1f0; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Copy the 4 byte value from v into the memory location pointed to by *cp, + If your architecture allows unaligned access this is equivalent to + * (uint32_t *) cp = v */ +static void +set_uint32 (char *cp, uint32_t v) +{ + memcpy (cp, &v, sizeof v); +} + +/* Put result from CTX in first 20 bytes following RESBUF. The result + must be in little endian byte order. */ +void * +sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) +{ + char *r = resbuf; + set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); + set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); + set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); + set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); + set_uint32 (r + 4 * sizeof ctx->E, SWAP (ctx->E)); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +void * +sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + uint32_t bytes = ctx->buflen; + size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); + ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3); + + memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); + + /* Process last bytes. */ + sha1_process_block (ctx->buffer, size * 4, ctx); + + return sha1_read_ctx (ctx, resbuf); +} + +/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha1_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha1_ctx ctx; + + /* Initialize the computation context. */ + sha1_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha1_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha1_finish_ctx (&ctx, resblock); +} + +void +sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap, + because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ + memcpy (ctx->buffer, + &((char *) ctx->buffer)[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) +# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha1_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha1_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + /* The regions in the following copy operation cannot overlap, + because left_over ≤ 64. */ + memcpy (ctx->buffer, &ctx->buffer[16], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between md5.c and sha1.c --- */ + +/* SHA1 round constants */ +#define K1 0x5a827999 +#define K2 0x6ed9eba1 +#define K3 0x8f1bbcdc +#define K4 0xca62c1d6 + +/* Round functions. Note that F2 is the same as F4. */ +#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) +#define F2(B,C,D) (B ^ C ^ D) +#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) +#define F4(B,C,D) (B ^ C ^ D) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) +{ + const uint32_t *words = buffer; + size_t nwords = len / sizeof (uint32_t); + const uint32_t *endp = words + nwords; + uint32_t x[16]; + uint32_t a = ctx->A; + uint32_t b = ctx->B; + uint32_t c = ctx->C; + uint32_t d = ctx->D; + uint32_t e = ctx->E; + uint32_t lolen = len; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += lolen; + ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); + +#define rol(x, n) (((x) << (n)) | ((uint32_t) (x) >> (32 - (n)))) + +#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ + ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ + , (x[I&0x0f] = rol(tm, 1)) ) + +#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ + + F( B, C, D ) \ + + K \ + + M; \ + B = rol( B, 30 ); \ + } while(0) + + while (words < endp) + { + uint32_t tm; + int t; + for (t = 0; t < 16; t++) + { + x[t] = SWAP (*words); + words++; + } + + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + a = ctx->A += a; + b = ctx->B += b; + c = ctx->C += c; + d = ctx->D += d; + e = ctx->E += e; + } +} + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sha1.h b/cross/lib/sha1.h new file mode 100644 index 00000000000..5a58b567ceb --- /dev/null +++ b/cross/lib/sha1.h @@ -0,0 +1,115 @@ +/* Declarations of functions and data types used for SHA1 sum + library functions. + Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2023 Free Software + Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef SHA1_H +# define SHA1_H 1 + +# include +# include + +# if HAVE_OPENSSL_SHA1 +# ifndef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ +# endif +# include +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +# define SHA1_DIGEST_SIZE 20 + +# if HAVE_OPENSSL_SHA1 +# define GL_OPENSSL_NAME 1 +# include "gl_openssl.h" +# else +/* Structure to save state of computation between the single steps. */ +struct sha1_ctx +{ + uint32_t A; + uint32_t B; + uint32_t C; + uint32_t D; + uint32_t E; + + uint32_t total[2]; + uint32_t buflen; /* ≥ 0, ≤ 128 */ + uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ +}; + +/* Initialize structure containing state of computation. */ +extern void sha1_init_ctx (struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void sha1_process_block (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha1_process_bytes (const void *buffer, size_t len, + struct sha1_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 20 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. */ +extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *restrict resbuf); + + +/* Put result from CTX in first 20 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. */ +extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *restrict resbuf); + + +/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha1_buffer (const char *buffer, size_t len, + void *restrict resblock); + +# endif + +/* Compute SHA1 message digest for bytes read from STREAM. + STREAM is an open file stream. Regular files are handled more efficiently. + The contents of STREAM from its current position to its end will be read. + The case that the last operation on STREAM was an 'ungetc' is not supported. + The resulting message digest number will be written into the 20 bytes + beginning at RESBLOCK. */ +extern int sha1_stream (FILE *stream, void *resblock); + + +# ifdef __cplusplus +} +# endif + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sha256.c b/cross/lib/sha256.c new file mode 100644 index 00000000000..e5fea02bc2e --- /dev/null +++ b/cross/lib/sha256.c @@ -0,0 +1,432 @@ +/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or + memory blocks according to the NIST specification FIPS-180-2. + + Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by David Madore, considerably copypasting from + Scott G. Miller's sha1.c +*/ + +#include + +/* Specification. */ +#if HAVE_OPENSSL_SHA256 +# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE +#endif +#include "sha256.h" + +#include +#include + +#include +#ifdef WORDS_BIGENDIAN +# define SWAP(n) (n) +#else +# define SWAP(n) bswap_32 (n) +#endif + +#if ! HAVE_OPENSSL_SHA256 + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* + Takes a pointer to a 256 bit block of data (eight 32 bit ints) and + initializes it to the start constants of the SHA256 algorithm. This + must be called before using hash in the call to sha256_hash +*/ +void +sha256_init_ctx (struct sha256_ctx *ctx) +{ + ctx->state[0] = 0x6a09e667UL; + ctx->state[1] = 0xbb67ae85UL; + ctx->state[2] = 0x3c6ef372UL; + ctx->state[3] = 0xa54ff53aUL; + ctx->state[4] = 0x510e527fUL; + ctx->state[5] = 0x9b05688cUL; + ctx->state[6] = 0x1f83d9abUL; + ctx->state[7] = 0x5be0cd19UL; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +void +sha224_init_ctx (struct sha256_ctx *ctx) +{ + ctx->state[0] = 0xc1059ed8UL; + ctx->state[1] = 0x367cd507UL; + ctx->state[2] = 0x3070dd17UL; + ctx->state[3] = 0xf70e5939UL; + ctx->state[4] = 0xffc00b31UL; + ctx->state[5] = 0x68581511UL; + ctx->state[6] = 0x64f98fa7UL; + ctx->state[7] = 0xbefa4fa4UL; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Copy the value from v into the memory location pointed to by *CP, + If your architecture allows unaligned access, this is equivalent to + * (__typeof__ (v) *) cp = v */ +static void +set_uint32 (char *cp, uint32_t v) +{ + memcpy (cp, &v, sizeof v); +} + +/* Put result from CTX in first 32 bytes following RESBUF. + The result must be in little endian byte order. */ +void * +sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf) +{ + int i; + char *r = resbuf; + + for (i = 0; i < 8; i++) + set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); + + return resbuf; +} + +void * +sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf) +{ + int i; + char *r = resbuf; + + for (i = 0; i < 7; i++) + set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +static void +sha256_conclude_ctx (struct sha256_ctx *ctx) +{ + /* Take yet unprocessed bytes into account. */ + size_t bytes = ctx->buflen; + size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + /* Put the 64-bit file length in *bits* at the end of the buffer. + Use set_uint32 rather than a simple assignment, to avoid risk of + unaligned access. */ + set_uint32 ((char *) &ctx->buffer[size - 2], + SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29))); + set_uint32 ((char *) &ctx->buffer[size - 1], + SWAP (ctx->total[0] << 3)); + + memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); + + /* Process last bytes. */ + sha256_process_block (ctx->buffer, size * 4, ctx); +} + +void * +sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf) +{ + sha256_conclude_ctx (ctx); + return sha256_read_ctx (ctx, resbuf); +} + +void * +sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf) +{ + sha256_conclude_ctx (ctx); + return sha224_read_ctx (ctx, resbuf); +} + +/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha256_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha256_ctx ctx; + + /* Initialize the computation context. */ + sha256_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha256_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha256_finish_ctx (&ctx, resblock); +} + +void * +sha224_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha256_ctx ctx; + + /* Initialize the computation context. */ + sha224_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha256_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha224_finish_ctx (&ctx, resblock); +} + +void +sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap, + because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ + memcpy (ctx->buffer, + &((char *) ctx->buffer)[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) +# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha256_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha256_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + /* The regions in the following copy operation cannot overlap, + because left_over ≤ 64. */ + memcpy (ctx->buffer, &ctx->buffer[16], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between sha1.c and sha256.c --- */ + +/* SHA256 round constants */ +#define K(I) sha256_round_constants[I] +static const uint32_t sha256_round_constants[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, +}; + +/* Round functions. */ +#define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) ) +#define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) ) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx) +{ + const uint32_t *words = buffer; + size_t nwords = len / sizeof (uint32_t); + const uint32_t *endp = words + nwords; + uint32_t x[16]; + uint32_t a = ctx->state[0]; + uint32_t b = ctx->state[1]; + uint32_t c = ctx->state[2]; + uint32_t d = ctx->state[3]; + uint32_t e = ctx->state[4]; + uint32_t f = ctx->state[5]; + uint32_t g = ctx->state[6]; + uint32_t h = ctx->state[7]; + uint32_t lolen = len; + + /* First increment the byte count. FIPS PUB 180-2 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += lolen; + ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); + +#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define S0(x) (rol(x,25)^rol(x,14)^(x>>3)) +#define S1(x) (rol(x,15)^rol(x,13)^(x>>10)) +#define SS0(x) (rol(x,30)^rol(x,19)^rol(x,10)) +#define SS1(x) (rol(x,26)^rol(x,21)^rol(x,7)) + +#define M(I) ( tm = S1(x[(I-2)&0x0f]) + x[(I-7)&0x0f] \ + + S0(x[(I-15)&0x0f]) + x[I&0x0f] \ + , x[I&0x0f] = tm ) + +#define R(A,B,C,D,E,F,G,H,K,M) do { t0 = SS0(A) + F2(A,B,C); \ + t1 = H + SS1(E) \ + + F1(E,F,G) \ + + K \ + + M; \ + D += t1; H = t0 + t1; \ + } while(0) + + while (words < endp) + { + uint32_t tm; + uint32_t t0, t1; + int t; + /* FIXME: see sha1.c for a better implementation. */ + for (t = 0; t < 16; t++) + { + x[t] = SWAP (*words); + words++; + } + + R( a, b, c, d, e, f, g, h, K( 0), x[ 0] ); + R( h, a, b, c, d, e, f, g, K( 1), x[ 1] ); + R( g, h, a, b, c, d, e, f, K( 2), x[ 2] ); + R( f, g, h, a, b, c, d, e, K( 3), x[ 3] ); + R( e, f, g, h, a, b, c, d, K( 4), x[ 4] ); + R( d, e, f, g, h, a, b, c, K( 5), x[ 5] ); + R( c, d, e, f, g, h, a, b, K( 6), x[ 6] ); + R( b, c, d, e, f, g, h, a, K( 7), x[ 7] ); + R( a, b, c, d, e, f, g, h, K( 8), x[ 8] ); + R( h, a, b, c, d, e, f, g, K( 9), x[ 9] ); + R( g, h, a, b, c, d, e, f, K(10), x[10] ); + R( f, g, h, a, b, c, d, e, K(11), x[11] ); + R( e, f, g, h, a, b, c, d, K(12), x[12] ); + R( d, e, f, g, h, a, b, c, K(13), x[13] ); + R( c, d, e, f, g, h, a, b, K(14), x[14] ); + R( b, c, d, e, f, g, h, a, K(15), x[15] ); + R( a, b, c, d, e, f, g, h, K(16), M(16) ); + R( h, a, b, c, d, e, f, g, K(17), M(17) ); + R( g, h, a, b, c, d, e, f, K(18), M(18) ); + R( f, g, h, a, b, c, d, e, K(19), M(19) ); + R( e, f, g, h, a, b, c, d, K(20), M(20) ); + R( d, e, f, g, h, a, b, c, K(21), M(21) ); + R( c, d, e, f, g, h, a, b, K(22), M(22) ); + R( b, c, d, e, f, g, h, a, K(23), M(23) ); + R( a, b, c, d, e, f, g, h, K(24), M(24) ); + R( h, a, b, c, d, e, f, g, K(25), M(25) ); + R( g, h, a, b, c, d, e, f, K(26), M(26) ); + R( f, g, h, a, b, c, d, e, K(27), M(27) ); + R( e, f, g, h, a, b, c, d, K(28), M(28) ); + R( d, e, f, g, h, a, b, c, K(29), M(29) ); + R( c, d, e, f, g, h, a, b, K(30), M(30) ); + R( b, c, d, e, f, g, h, a, K(31), M(31) ); + R( a, b, c, d, e, f, g, h, K(32), M(32) ); + R( h, a, b, c, d, e, f, g, K(33), M(33) ); + R( g, h, a, b, c, d, e, f, K(34), M(34) ); + R( f, g, h, a, b, c, d, e, K(35), M(35) ); + R( e, f, g, h, a, b, c, d, K(36), M(36) ); + R( d, e, f, g, h, a, b, c, K(37), M(37) ); + R( c, d, e, f, g, h, a, b, K(38), M(38) ); + R( b, c, d, e, f, g, h, a, K(39), M(39) ); + R( a, b, c, d, e, f, g, h, K(40), M(40) ); + R( h, a, b, c, d, e, f, g, K(41), M(41) ); + R( g, h, a, b, c, d, e, f, K(42), M(42) ); + R( f, g, h, a, b, c, d, e, K(43), M(43) ); + R( e, f, g, h, a, b, c, d, K(44), M(44) ); + R( d, e, f, g, h, a, b, c, K(45), M(45) ); + R( c, d, e, f, g, h, a, b, K(46), M(46) ); + R( b, c, d, e, f, g, h, a, K(47), M(47) ); + R( a, b, c, d, e, f, g, h, K(48), M(48) ); + R( h, a, b, c, d, e, f, g, K(49), M(49) ); + R( g, h, a, b, c, d, e, f, K(50), M(50) ); + R( f, g, h, a, b, c, d, e, K(51), M(51) ); + R( e, f, g, h, a, b, c, d, K(52), M(52) ); + R( d, e, f, g, h, a, b, c, K(53), M(53) ); + R( c, d, e, f, g, h, a, b, K(54), M(54) ); + R( b, c, d, e, f, g, h, a, K(55), M(55) ); + R( a, b, c, d, e, f, g, h, K(56), M(56) ); + R( h, a, b, c, d, e, f, g, K(57), M(57) ); + R( g, h, a, b, c, d, e, f, K(58), M(58) ); + R( f, g, h, a, b, c, d, e, K(59), M(59) ); + R( e, f, g, h, a, b, c, d, K(60), M(60) ); + R( d, e, f, g, h, a, b, c, K(61), M(61) ); + R( c, d, e, f, g, h, a, b, K(62), M(62) ); + R( b, c, d, e, f, g, h, a, K(63), M(63) ); + + a = ctx->state[0] += a; + b = ctx->state[1] += b; + c = ctx->state[2] += c; + d = ctx->state[3] += d; + e = ctx->state[4] += e; + f = ctx->state[5] += f; + g = ctx->state[6] += g; + h = ctx->state[7] += h; + } +} + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sha256.h b/cross/lib/sha256.h new file mode 100644 index 00000000000..2879477e89c --- /dev/null +++ b/cross/lib/sha256.h @@ -0,0 +1,121 @@ +/* Declarations of functions and data types used for SHA256 and SHA224 sum + library functions. + Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef SHA256_H +# define SHA256_H 1 + +# include +# include + +# if HAVE_OPENSSL_SHA256 +# ifndef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ +# endif +# include +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +enum { SHA224_DIGEST_SIZE = 224 / 8 }; +enum { SHA256_DIGEST_SIZE = 256 / 8 }; + +# if HAVE_OPENSSL_SHA256 +# define GL_OPENSSL_NAME 224 +# include "gl_openssl.h" +# define GL_OPENSSL_NAME 256 +# include "gl_openssl.h" +# else +/* Structure to save state of computation between the single steps. */ +struct sha256_ctx +{ + uint32_t state[8]; + + uint32_t total[2]; + size_t buflen; /* ≥ 0, ≤ 128 */ + uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ +}; + +/* Initialize structure containing state of computation. */ +extern void sha256_init_ctx (struct sha256_ctx *ctx); +extern void sha224_init_ctx (struct sha256_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void sha256_process_block (const void *buffer, size_t len, + struct sha256_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha256_process_bytes (const void *buffer, size_t len, + struct sha256_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 32 (28) bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. */ +extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf); +extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf); + + +/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. */ +extern void *sha256_read_ctx (const struct sha256_ctx *ctx, + void *restrict resbuf); +extern void *sha224_read_ctx (const struct sha256_ctx *ctx, + void *restrict resbuf); + + +/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER. + The result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha256_buffer (const char *buffer, size_t len, + void *restrict resblock); +extern void *sha224_buffer (const char *buffer, size_t len, + void *restrict resblock); + +# endif + +/* Compute SHA256 (SHA224) message digest for bytes read from STREAM. + STREAM is an open file stream. Regular files are handled more efficiently. + The contents of STREAM from its current position to its end will be read. + The case that the last operation on STREAM was an 'ungetc' is not supported. + The resulting message digest number will be written into the 32 (28) bytes + beginning at RESBLOCK. */ +extern int sha256_stream (FILE *stream, void *resblock); +extern int sha224_stream (FILE *stream, void *resblock); + + +# ifdef __cplusplus +} +# endif + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sha512.c b/cross/lib/sha512.c new file mode 100644 index 00000000000..8ca7fa319f5 --- /dev/null +++ b/cross/lib/sha512.c @@ -0,0 +1,477 @@ +/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or + memory blocks according to the NIST specification FIPS-180-2. + + Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by David Madore, considerably copypasting from + Scott G. Miller's sha1.c +*/ + +#include + +/* Specification. */ +#if HAVE_OPENSSL_SHA512 +# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE +#endif +#include "sha512.h" + +#include +#include + +#include +#ifdef WORDS_BIGENDIAN +# define SWAP(n) (n) +#else +# define SWAP(n) bswap_64 (n) +#endif + +#if ! HAVE_OPENSSL_SHA512 + +/* This array contains the bytes used to pad the buffer to the next + 128-byte boundary. */ +static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* + Takes a pointer to a 512 bit block of data (eight 64 bit ints) and + initializes it to the start constants of the SHA512 algorithm. This + must be called before using hash in the call to sha512_hash +*/ +void +sha512_init_ctx (struct sha512_ctx *ctx) +{ + ctx->state[0] = u64hilo (0x6a09e667, 0xf3bcc908); + ctx->state[1] = u64hilo (0xbb67ae85, 0x84caa73b); + ctx->state[2] = u64hilo (0x3c6ef372, 0xfe94f82b); + ctx->state[3] = u64hilo (0xa54ff53a, 0x5f1d36f1); + ctx->state[4] = u64hilo (0x510e527f, 0xade682d1); + ctx->state[5] = u64hilo (0x9b05688c, 0x2b3e6c1f); + ctx->state[6] = u64hilo (0x1f83d9ab, 0xfb41bd6b); + ctx->state[7] = u64hilo (0x5be0cd19, 0x137e2179); + + ctx->total[0] = ctx->total[1] = u64lo (0); + ctx->buflen = 0; +} + +void +sha384_init_ctx (struct sha512_ctx *ctx) +{ + ctx->state[0] = u64hilo (0xcbbb9d5d, 0xc1059ed8); + ctx->state[1] = u64hilo (0x629a292a, 0x367cd507); + ctx->state[2] = u64hilo (0x9159015a, 0x3070dd17); + ctx->state[3] = u64hilo (0x152fecd8, 0xf70e5939); + ctx->state[4] = u64hilo (0x67332667, 0xffc00b31); + ctx->state[5] = u64hilo (0x8eb44a87, 0x68581511); + ctx->state[6] = u64hilo (0xdb0c2e0d, 0x64f98fa7); + ctx->state[7] = u64hilo (0x47b5481d, 0xbefa4fa4); + + ctx->total[0] = ctx->total[1] = u64lo (0); + ctx->buflen = 0; +} + +/* Copy the value from V into the memory location pointed to by *CP, + If your architecture allows unaligned access, this is equivalent to + * (__typeof__ (v) *) cp = v */ +static void +set_uint64 (char *cp, u64 v) +{ + memcpy (cp, &v, sizeof v); +} + +/* Put result from CTX in first 64 bytes following RESBUF. + The result must be in little endian byte order. */ +void * +sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf) +{ + int i; + char *r = resbuf; + + for (i = 0; i < 8; i++) + set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); + + return resbuf; +} + +void * +sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf) +{ + int i; + char *r = resbuf; + + for (i = 0; i < 6; i++) + set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. */ +static void +sha512_conclude_ctx (struct sha512_ctx *ctx) +{ + /* Take yet unprocessed bytes into account. */ + size_t bytes = ctx->buflen; + size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8; + + /* Now count remaining bytes. */ + ctx->total[0] = u64plus (ctx->total[0], u64lo (bytes)); + if (u64lt (ctx->total[0], u64lo (bytes))) + ctx->total[1] = u64plus (ctx->total[1], u64lo (1)); + + /* Put the 128-bit file length in *bits* at the end of the buffer. + Use set_uint64 rather than a simple assignment, to avoid risk of + unaligned access. */ + set_uint64 ((char *) &ctx->buffer[size - 2], + SWAP (u64or (u64shl (ctx->total[1], 3), + u64shr (ctx->total[0], 61)))); + set_uint64 ((char *) &ctx->buffer[size - 1], + SWAP (u64shl (ctx->total[0], 3))); + + memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 8 - bytes); + + /* Process last bytes. */ + sha512_process_block (ctx->buffer, size * 8, ctx); +} + +void * +sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) +{ + sha512_conclude_ctx (ctx); + return sha512_read_ctx (ctx, resbuf); +} + +void * +sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf) +{ + sha512_conclude_ctx (ctx); + return sha384_read_ctx (ctx, resbuf); +} + +/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha512_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha512_ctx ctx; + + /* Initialize the computation context. */ + sha512_init_ctx (&ctx); + + /* Process whole buffer but last len % 128 bytes. */ + sha512_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha512_finish_ctx (&ctx, resblock); +} + +void * +sha384_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha512_ctx ctx; + + /* Initialize the computation context. */ + sha384_init_ctx (&ctx); + + /* Process whole buffer but last len % 128 bytes. */ + sha512_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha384_finish_ctx (&ctx, resblock); +} + +void +sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 256 - left_over > len ? len : 256 - left_over; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 128) + { + sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx); + + ctx->buflen &= 127; + /* The regions in the following copy operation cannot overlap, + because ctx->buflen < 128 ≤ (left_over + add) & ~127. */ + memcpy (ctx->buffer, + &((char *) ctx->buffer)[(left_over + add) & ~127], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 128) + { +#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) +# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (u64) != 0) + if (UNALIGNED_P (buffer)) + while (len > 128) + { + sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx); + buffer = (const char *) buffer + 128; + len -= 128; + } + else +#endif + { + sha512_process_block (buffer, len & ~127, ctx); + buffer = (const char *) buffer + (len & ~127); + len &= 127; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&((char *) ctx->buffer)[left_over], buffer, len); + left_over += len; + if (left_over >= 128) + { + sha512_process_block (ctx->buffer, 128, ctx); + left_over -= 128; + /* The regions in the following copy operation cannot overlap, + because left_over ≤ 128. */ + memcpy (ctx->buffer, &ctx->buffer[16], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between sha1.c and sha512.c --- */ + +/* SHA512 round constants */ +#define K(I) sha512_round_constants[I] +static u64 const sha512_round_constants[80] = { + u64init (0x428a2f98, 0xd728ae22), u64init (0x71374491, 0x23ef65cd), + u64init (0xb5c0fbcf, 0xec4d3b2f), u64init (0xe9b5dba5, 0x8189dbbc), + u64init (0x3956c25b, 0xf348b538), u64init (0x59f111f1, 0xb605d019), + u64init (0x923f82a4, 0xaf194f9b), u64init (0xab1c5ed5, 0xda6d8118), + u64init (0xd807aa98, 0xa3030242), u64init (0x12835b01, 0x45706fbe), + u64init (0x243185be, 0x4ee4b28c), u64init (0x550c7dc3, 0xd5ffb4e2), + u64init (0x72be5d74, 0xf27b896f), u64init (0x80deb1fe, 0x3b1696b1), + u64init (0x9bdc06a7, 0x25c71235), u64init (0xc19bf174, 0xcf692694), + u64init (0xe49b69c1, 0x9ef14ad2), u64init (0xefbe4786, 0x384f25e3), + u64init (0x0fc19dc6, 0x8b8cd5b5), u64init (0x240ca1cc, 0x77ac9c65), + u64init (0x2de92c6f, 0x592b0275), u64init (0x4a7484aa, 0x6ea6e483), + u64init (0x5cb0a9dc, 0xbd41fbd4), u64init (0x76f988da, 0x831153b5), + u64init (0x983e5152, 0xee66dfab), u64init (0xa831c66d, 0x2db43210), + u64init (0xb00327c8, 0x98fb213f), u64init (0xbf597fc7, 0xbeef0ee4), + u64init (0xc6e00bf3, 0x3da88fc2), u64init (0xd5a79147, 0x930aa725), + u64init (0x06ca6351, 0xe003826f), u64init (0x14292967, 0x0a0e6e70), + u64init (0x27b70a85, 0x46d22ffc), u64init (0x2e1b2138, 0x5c26c926), + u64init (0x4d2c6dfc, 0x5ac42aed), u64init (0x53380d13, 0x9d95b3df), + u64init (0x650a7354, 0x8baf63de), u64init (0x766a0abb, 0x3c77b2a8), + u64init (0x81c2c92e, 0x47edaee6), u64init (0x92722c85, 0x1482353b), + u64init (0xa2bfe8a1, 0x4cf10364), u64init (0xa81a664b, 0xbc423001), + u64init (0xc24b8b70, 0xd0f89791), u64init (0xc76c51a3, 0x0654be30), + u64init (0xd192e819, 0xd6ef5218), u64init (0xd6990624, 0x5565a910), + u64init (0xf40e3585, 0x5771202a), u64init (0x106aa070, 0x32bbd1b8), + u64init (0x19a4c116, 0xb8d2d0c8), u64init (0x1e376c08, 0x5141ab53), + u64init (0x2748774c, 0xdf8eeb99), u64init (0x34b0bcb5, 0xe19b48a8), + u64init (0x391c0cb3, 0xc5c95a63), u64init (0x4ed8aa4a, 0xe3418acb), + u64init (0x5b9cca4f, 0x7763e373), u64init (0x682e6ff3, 0xd6b2b8a3), + u64init (0x748f82ee, 0x5defb2fc), u64init (0x78a5636f, 0x43172f60), + u64init (0x84c87814, 0xa1f0ab72), u64init (0x8cc70208, 0x1a6439ec), + u64init (0x90befffa, 0x23631e28), u64init (0xa4506ceb, 0xde82bde9), + u64init (0xbef9a3f7, 0xb2c67915), u64init (0xc67178f2, 0xe372532b), + u64init (0xca273ece, 0xea26619c), u64init (0xd186b8c7, 0x21c0c207), + u64init (0xeada7dd6, 0xcde0eb1e), u64init (0xf57d4f7f, 0xee6ed178), + u64init (0x06f067aa, 0x72176fba), u64init (0x0a637dc5, 0xa2c898a6), + u64init (0x113f9804, 0xbef90dae), u64init (0x1b710b35, 0x131c471b), + u64init (0x28db77f5, 0x23047d84), u64init (0x32caab7b, 0x40c72493), + u64init (0x3c9ebe0a, 0x15c9bebc), u64init (0x431d67c4, 0x9c100d4c), + u64init (0x4cc5d4be, 0xcb3e42b6), u64init (0x597f299c, 0xfc657e2a), + u64init (0x5fcb6fab, 0x3ad6faec), u64init (0x6c44198c, 0x4a475817), +}; + +/* Round functions. */ +#define F2(A, B, C) u64or (u64and (A, B), u64and (C, u64or (A, B))) +#define F1(E, F, G) u64xor (G, u64and (E, u64xor (F, G))) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 128 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx) +{ + u64 const *words = buffer; + u64 const *endp = words + len / sizeof (u64); + u64 x[16]; + u64 a = ctx->state[0]; + u64 b = ctx->state[1]; + u64 c = ctx->state[2]; + u64 d = ctx->state[3]; + u64 e = ctx->state[4]; + u64 f = ctx->state[5]; + u64 g = ctx->state[6]; + u64 h = ctx->state[7]; + u64 lolen = u64size (len); + + /* First increment the byte count. FIPS PUB 180-2 specifies the possible + length of the file up to 2^128 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] = u64plus (ctx->total[0], lolen); + ctx->total[1] = u64plus (ctx->total[1], + u64plus (u64size (len >> 31 >> 31 >> 2), + u64lo (u64lt (ctx->total[0], lolen)))); + +#define S0(x) u64xor (u64rol(x, 63), u64xor (u64rol (x, 56), u64shr (x, 7))) +#define S1(x) u64xor (u64rol (x, 45), u64xor (u64rol (x, 3), u64shr (x, 6))) +#define SS0(x) u64xor (u64rol (x, 36), u64xor (u64rol (x, 30), u64rol (x, 25))) +#define SS1(x) u64xor (u64rol(x, 50), u64xor (u64rol (x, 46), u64rol (x, 23))) + +#define M(I) (x[(I) & 15] \ + = u64plus (x[(I) & 15], \ + u64plus (S1 (x[((I) - 2) & 15]), \ + u64plus (x[((I) - 7) & 15], \ + S0 (x[((I) - 15) & 15]))))) + +#define R(A, B, C, D, E, F, G, H, K, M) \ + do \ + { \ + u64 t0 = u64plus (SS0 (A), F2 (A, B, C)); \ + u64 t1 = \ + u64plus (H, u64plus (SS1 (E), \ + u64plus (F1 (E, F, G), u64plus (K, M)))); \ + D = u64plus (D, t1); \ + H = u64plus (t0, t1); \ + } \ + while (0) + + while (words < endp) + { + int t; + /* FIXME: see sha1.c for a better implementation. */ + for (t = 0; t < 16; t++) + { + x[t] = SWAP (*words); + words++; + } + + R( a, b, c, d, e, f, g, h, K( 0), x[ 0] ); + R( h, a, b, c, d, e, f, g, K( 1), x[ 1] ); + R( g, h, a, b, c, d, e, f, K( 2), x[ 2] ); + R( f, g, h, a, b, c, d, e, K( 3), x[ 3] ); + R( e, f, g, h, a, b, c, d, K( 4), x[ 4] ); + R( d, e, f, g, h, a, b, c, K( 5), x[ 5] ); + R( c, d, e, f, g, h, a, b, K( 6), x[ 6] ); + R( b, c, d, e, f, g, h, a, K( 7), x[ 7] ); + R( a, b, c, d, e, f, g, h, K( 8), x[ 8] ); + R( h, a, b, c, d, e, f, g, K( 9), x[ 9] ); + R( g, h, a, b, c, d, e, f, K(10), x[10] ); + R( f, g, h, a, b, c, d, e, K(11), x[11] ); + R( e, f, g, h, a, b, c, d, K(12), x[12] ); + R( d, e, f, g, h, a, b, c, K(13), x[13] ); + R( c, d, e, f, g, h, a, b, K(14), x[14] ); + R( b, c, d, e, f, g, h, a, K(15), x[15] ); + R( a, b, c, d, e, f, g, h, K(16), M(16) ); + R( h, a, b, c, d, e, f, g, K(17), M(17) ); + R( g, h, a, b, c, d, e, f, K(18), M(18) ); + R( f, g, h, a, b, c, d, e, K(19), M(19) ); + R( e, f, g, h, a, b, c, d, K(20), M(20) ); + R( d, e, f, g, h, a, b, c, K(21), M(21) ); + R( c, d, e, f, g, h, a, b, K(22), M(22) ); + R( b, c, d, e, f, g, h, a, K(23), M(23) ); + R( a, b, c, d, e, f, g, h, K(24), M(24) ); + R( h, a, b, c, d, e, f, g, K(25), M(25) ); + R( g, h, a, b, c, d, e, f, K(26), M(26) ); + R( f, g, h, a, b, c, d, e, K(27), M(27) ); + R( e, f, g, h, a, b, c, d, K(28), M(28) ); + R( d, e, f, g, h, a, b, c, K(29), M(29) ); + R( c, d, e, f, g, h, a, b, K(30), M(30) ); + R( b, c, d, e, f, g, h, a, K(31), M(31) ); + R( a, b, c, d, e, f, g, h, K(32), M(32) ); + R( h, a, b, c, d, e, f, g, K(33), M(33) ); + R( g, h, a, b, c, d, e, f, K(34), M(34) ); + R( f, g, h, a, b, c, d, e, K(35), M(35) ); + R( e, f, g, h, a, b, c, d, K(36), M(36) ); + R( d, e, f, g, h, a, b, c, K(37), M(37) ); + R( c, d, e, f, g, h, a, b, K(38), M(38) ); + R( b, c, d, e, f, g, h, a, K(39), M(39) ); + R( a, b, c, d, e, f, g, h, K(40), M(40) ); + R( h, a, b, c, d, e, f, g, K(41), M(41) ); + R( g, h, a, b, c, d, e, f, K(42), M(42) ); + R( f, g, h, a, b, c, d, e, K(43), M(43) ); + R( e, f, g, h, a, b, c, d, K(44), M(44) ); + R( d, e, f, g, h, a, b, c, K(45), M(45) ); + R( c, d, e, f, g, h, a, b, K(46), M(46) ); + R( b, c, d, e, f, g, h, a, K(47), M(47) ); + R( a, b, c, d, e, f, g, h, K(48), M(48) ); + R( h, a, b, c, d, e, f, g, K(49), M(49) ); + R( g, h, a, b, c, d, e, f, K(50), M(50) ); + R( f, g, h, a, b, c, d, e, K(51), M(51) ); + R( e, f, g, h, a, b, c, d, K(52), M(52) ); + R( d, e, f, g, h, a, b, c, K(53), M(53) ); + R( c, d, e, f, g, h, a, b, K(54), M(54) ); + R( b, c, d, e, f, g, h, a, K(55), M(55) ); + R( a, b, c, d, e, f, g, h, K(56), M(56) ); + R( h, a, b, c, d, e, f, g, K(57), M(57) ); + R( g, h, a, b, c, d, e, f, K(58), M(58) ); + R( f, g, h, a, b, c, d, e, K(59), M(59) ); + R( e, f, g, h, a, b, c, d, K(60), M(60) ); + R( d, e, f, g, h, a, b, c, K(61), M(61) ); + R( c, d, e, f, g, h, a, b, K(62), M(62) ); + R( b, c, d, e, f, g, h, a, K(63), M(63) ); + R( a, b, c, d, e, f, g, h, K(64), M(64) ); + R( h, a, b, c, d, e, f, g, K(65), M(65) ); + R( g, h, a, b, c, d, e, f, K(66), M(66) ); + R( f, g, h, a, b, c, d, e, K(67), M(67) ); + R( e, f, g, h, a, b, c, d, K(68), M(68) ); + R( d, e, f, g, h, a, b, c, K(69), M(69) ); + R( c, d, e, f, g, h, a, b, K(70), M(70) ); + R( b, c, d, e, f, g, h, a, K(71), M(71) ); + R( a, b, c, d, e, f, g, h, K(72), M(72) ); + R( h, a, b, c, d, e, f, g, K(73), M(73) ); + R( g, h, a, b, c, d, e, f, K(74), M(74) ); + R( f, g, h, a, b, c, d, e, K(75), M(75) ); + R( e, f, g, h, a, b, c, d, K(76), M(76) ); + R( d, e, f, g, h, a, b, c, K(77), M(77) ); + R( c, d, e, f, g, h, a, b, K(78), M(78) ); + R( b, c, d, e, f, g, h, a, K(79), M(79) ); + + a = ctx->state[0] = u64plus (ctx->state[0], a); + b = ctx->state[1] = u64plus (ctx->state[1], b); + c = ctx->state[2] = u64plus (ctx->state[2], c); + d = ctx->state[3] = u64plus (ctx->state[3], d); + e = ctx->state[4] = u64plus (ctx->state[4], e); + f = ctx->state[5] = u64plus (ctx->state[5], f); + g = ctx->state[6] = u64plus (ctx->state[6], g); + h = ctx->state[7] = u64plus (ctx->state[7], h); + } +} + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sha512.h b/cross/lib/sha512.h new file mode 100644 index 00000000000..e3a98a2644c --- /dev/null +++ b/cross/lib/sha512.h @@ -0,0 +1,124 @@ +/* Declarations of functions and data types used for SHA512 and SHA384 sum + library functions. + Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef SHA512_H +# define SHA512_H 1 + +# include +# include "u64.h" + +# if HAVE_OPENSSL_SHA512 +# ifndef OPENSSL_API_COMPAT +# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ +# endif +# include +# endif + +# ifdef __cplusplus +extern "C" { +# endif + +enum { SHA384_DIGEST_SIZE = 384 / 8 }; +enum { SHA512_DIGEST_SIZE = 512 / 8 }; + +# if HAVE_OPENSSL_SHA512 +# define GL_OPENSSL_NAME 384 +# include "gl_openssl.h" +# define GL_OPENSSL_NAME 512 +# include "gl_openssl.h" +# else +/* Structure to save state of computation between the single steps. */ +struct sha512_ctx +{ + u64 state[8]; + + u64 total[2]; + size_t buflen; /* ≥ 0, ≤ 256 */ + u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */ +}; + +/* Initialize structure containing state of computation. */ +extern void sha512_init_ctx (struct sha512_ctx *ctx); +extern void sha384_init_ctx (struct sha512_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 128!!! */ +extern void sha512_process_block (const void *buffer, size_t len, + struct sha512_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 128. */ +extern void sha512_process_bytes (const void *buffer, size_t len, + struct sha512_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 64 (48) bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. */ +extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf); +extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf); + + +/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *sha512_read_ctx (const struct sha512_ctx *ctx, + void *restrict resbuf); +extern void *sha384_read_ctx (const struct sha512_ctx *ctx, + void *restrict resbuf); + + +/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER. + The result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha512_buffer (const char *buffer, size_t len, + void *restrict resblock); +extern void *sha384_buffer (const char *buffer, size_t len, + void *restrict resblock); + +# endif + +/* Compute SHA512 (SHA384) message digest for bytes read from STREAM. + STREAM is an open file stream. Regular files are handled more efficiently. + The contents of STREAM from its current position to its end will be read. + The case that the last operation on STREAM was an 'ungetc' is not supported. + The resulting message digest number will be written into the 64 (48) bytes + beginning at RESBLOCK. */ +extern int sha512_stream (FILE *stream, void *resblock); +extern int sha384_stream (FILE *stream, void *resblock); + + +# ifdef __cplusplus +} +# endif + +#endif + +/* + * Hey Emacs! + * Local Variables: + * coding: utf-8 + * End: + */ diff --git a/cross/lib/sig2str.c b/cross/lib/sig2str.c new file mode 100644 index 00000000000..c5219caaaed --- /dev/null +++ b/cross/lib/sig2str.c @@ -0,0 +1,364 @@ +/* sig2str.c -- convert between signal names and numbers + + Copyright (C) 2002, 2004, 2006, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +#include + +#include +#include +#include +#include +#include + +#include "sig2str.h" + +#ifndef SIGRTMIN +# define SIGRTMIN 0 +# undef SIGRTMAX +#endif +#ifndef SIGRTMAX +# define SIGRTMAX (SIGRTMIN - 1) +#endif + +#define NUMNAME(name) { SIG##name, #name } + +/* Signal names and numbers. Put the preferred name first. */ +static struct numname { int num; char const name[8]; } numname_table[] = + { + /* Signals required by POSIX 1003.1-2001 base, listed in + traditional numeric order where possible. */ +#ifdef SIGHUP + NUMNAME (HUP), +#endif +#ifdef SIGINT + NUMNAME (INT), +#endif +#ifdef SIGQUIT + NUMNAME (QUIT), +#endif +#ifdef SIGILL + NUMNAME (ILL), +#endif +#ifdef SIGTRAP + NUMNAME (TRAP), +#endif +#ifdef SIGABRT + NUMNAME (ABRT), +#endif +#ifdef SIGFPE + NUMNAME (FPE), +#endif +#ifdef SIGKILL + NUMNAME (KILL), +#endif +#ifdef SIGSEGV + NUMNAME (SEGV), +#endif + /* On Haiku, SIGSEGV == SIGBUS, but we prefer SIGSEGV to match + strsignal.c output, so SIGBUS must be listed second. */ +#ifdef SIGBUS + NUMNAME (BUS), +#endif +#ifdef SIGPIPE + NUMNAME (PIPE), +#endif +#ifdef SIGALRM + NUMNAME (ALRM), +#endif +#ifdef SIGTERM + NUMNAME (TERM), +#endif +#ifdef SIGUSR1 + NUMNAME (USR1), +#endif +#ifdef SIGUSR2 + NUMNAME (USR2), +#endif +#ifdef SIGCHLD + NUMNAME (CHLD), +#endif +#ifdef SIGURG + NUMNAME (URG), +#endif +#ifdef SIGSTOP + NUMNAME (STOP), +#endif +#ifdef SIGTSTP + NUMNAME (TSTP), +#endif +#ifdef SIGCONT + NUMNAME (CONT), +#endif +#ifdef SIGTTIN + NUMNAME (TTIN), +#endif +#ifdef SIGTTOU + NUMNAME (TTOU), +#endif + + /* Signals required by POSIX 1003.1-2001 with the XSI extension. */ +#ifdef SIGSYS + NUMNAME (SYS), +#endif +#ifdef SIGPOLL + NUMNAME (POLL), +#endif +#ifdef SIGVTALRM + NUMNAME (VTALRM), +#endif +#ifdef SIGPROF + NUMNAME (PROF), +#endif +#ifdef SIGXCPU + NUMNAME (XCPU), +#endif +#ifdef SIGXFSZ + NUMNAME (XFSZ), +#endif + + /* Unix Version 7. */ +#ifdef SIGIOT + NUMNAME (IOT), /* Older name for ABRT. */ +#endif +#ifdef SIGEMT + NUMNAME (EMT), +#endif + + /* USG Unix. */ +#ifdef SIGPHONE + NUMNAME (PHONE), +#endif +#ifdef SIGWIND + NUMNAME (WIND), +#endif + + /* Unix System V. */ +#ifdef SIGCLD + NUMNAME (CLD), +#endif +#ifdef SIGPWR + NUMNAME (PWR), +#endif + + /* GNU/Linux 2.2 and Solaris 8. */ +#ifdef SIGCANCEL + NUMNAME (CANCEL), +#endif +#ifdef SIGLWP + NUMNAME (LWP), +#endif +#ifdef SIGWAITING + NUMNAME (WAITING), +#endif +#ifdef SIGFREEZE + NUMNAME (FREEZE), +#endif +#ifdef SIGTHAW + NUMNAME (THAW), +#endif +#ifdef SIGLOST + NUMNAME (LOST), +#endif +#ifdef SIGWINCH + NUMNAME (WINCH), +#endif + + /* GNU/Linux 2.2. */ +#ifdef SIGINFO + NUMNAME (INFO), +#endif +#ifdef SIGIO + NUMNAME (IO), +#endif +#ifdef SIGSTKFLT + NUMNAME (STKFLT), +#endif + + /* AIX 7. */ +#ifdef SIGCPUFAIL + NUMNAME (CPUFAIL), +#endif + + /* AIX 5L. */ +#ifdef SIGDANGER + NUMNAME (DANGER), +#endif +#ifdef SIGGRANT + NUMNAME (GRANT), +#endif +#ifdef SIGMIGRATE + NUMNAME (MIGRATE), +#endif +#ifdef SIGMSG + NUMNAME (MSG), +#endif +#ifdef SIGPRE + NUMNAME (PRE), +#endif +#ifdef SIGRETRACT + NUMNAME (RETRACT), +#endif +#ifdef SIGSAK + NUMNAME (SAK), +#endif +#ifdef SIGSOUND + NUMNAME (SOUND), +#endif + + /* Older AIX versions. */ +#ifdef SIGALRM1 + NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */ +#endif +#ifdef SIGKAP + NUMNAME (KAP), /* Older name for SIGGRANT. */ +#endif +#ifdef SIGVIRT + NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */ +#endif +#ifdef SIGWINDOW + NUMNAME (WINDOW), /* Older name for SIGWINCH. */ +#endif + + /* OpenBSD. */ +#ifdef SIGTHR + NUMNAME (THR), +#endif + + /* BeOS, Haiku */ +#ifdef SIGKILLTHR + NUMNAME (KILLTHR), +#endif + + /* Older HP-UX versions. */ +#ifdef SIGDIL + NUMNAME (DIL), +#endif + + /* native Windows */ +#ifdef SIGBREAK + NUMNAME (BREAK), +#endif + + /* Korn shell and Bash, of uncertain vintage. */ + { 0, "EXIT" } + }; + +#define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0]) + +/* ISDIGIT differs from isdigit, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char + or EOF. + - It's typically faster. + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + isdigit unless it's important to use the locale's definition + of "digit" even when the host does not conform to POSIX. */ +#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) + +/* Convert the signal name SIGNAME to a signal number. Return the + signal number if successful, -1 otherwise. */ + +static int +str2signum (char const *signame) +{ + if (ISDIGIT (*signame)) + { + char *endp; + long int n = strtol (signame, &endp, 10); + if (! *endp && n <= SIGNUM_BOUND) + return n; + } + else + { + unsigned int i; + for (i = 0; i < NUMNAME_ENTRIES; i++) + if (strcmp (numname_table[i].name, signame) == 0) + return numname_table[i].num; + + { + char *endp; + int rtmin = SIGRTMIN; + int rtmax = SIGRTMAX; + + if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0) + { + long int n = strtol (signame + 5, &endp, 10); + if (! *endp && 0 <= n && n <= rtmax - rtmin) + return rtmin + n; + } + else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0) + { + long int n = strtol (signame + 5, &endp, 10); + if (! *endp && rtmin - rtmax <= n && n <= 0) + return rtmax + n; + } + } + } + + return -1; +} + +/* Convert the signal name SIGNAME to the signal number *SIGNUM. + Return 0 if successful, -1 otherwise. */ + +int +str2sig (char const *signame, int *signum) +{ + *signum = str2signum (signame); + return *signum < 0 ? -1 : 0; +} + +/* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to + a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1 + otherwise. */ + +int +sig2str (int signum, char *signame) +{ + unsigned int i; + for (i = 0; i < NUMNAME_ENTRIES; i++) + if (numname_table[i].num == signum) + { + strcpy (signame, numname_table[i].name); + return 0; + } + + { + int rtmin = SIGRTMIN; + int rtmax = SIGRTMAX; + int base, delta; + + if (! (rtmin <= signum && signum <= rtmax)) + return -1; + + if (signum <= rtmin + (rtmax - rtmin) / 2) + { + strcpy (signame, "RTMIN"); + base = rtmin; + } + else + { + strcpy (signame, "RTMAX"); + base = rtmax; + } + + delta = signum - base; + if (delta != 0) + sprintf (signame + 5, "%+d", delta); + return 0; + } +} diff --git a/cross/lib/sig2str.h b/cross/lib/sig2str.h new file mode 100644 index 00000000000..1e5253658e7 --- /dev/null +++ b/cross/lib/sig2str.h @@ -0,0 +1,53 @@ +/* sig2str.h -- convert between signal names and numbers + + Copyright (C) 2002, 2005, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +#include + +/* Don't override system declarations of SIG2STR_MAX, sig2str, str2sig. */ +#ifndef SIG2STR_MAX + +# include "intprops.h" + +/* Size of a buffer needed to hold a signal name like "HUP". */ +# define SIG2STR_MAX (sizeof "SIGRTMAX" + INT_STRLEN_BOUND (int) - 1) + +#ifdef __cplusplus +extern "C" { +#endif + +int sig2str (int, char *); +int str2sig (char const *, int *); + +#ifdef __cplusplus +} +#endif + +#endif + +/* An upper bound on signal numbers allowed by the system. */ + +#if defined _sys_nsig +# define SIGNUM_BOUND (_sys_nsig - 1) +#elif defined _SIG_MAXSIG +# define SIGNUM_BOUND (_SIG_MAXSIG - 2) /* FreeBSD >= 7. */ +#elif defined NSIG +# define SIGNUM_BOUND (NSIG - 1) +#else +# define SIGNUM_BOUND 64 +#endif diff --git a/cross/lib/sigdescr_np.c b/cross/lib/sigdescr_np.c new file mode 100644 index 00000000000..fc8a4ad47a2 --- /dev/null +++ b/cross/lib/sigdescr_np.c @@ -0,0 +1,376 @@ +/* English descriptions of signals. + Copyright (C) 2020-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +/* Specification. */ +#include + +#include + +const char * +sigdescr_np (int sig) +{ + /* Note: Some platforms (glibc, FreeBSD, NetBSD, OpenBSD, AIX, IRIX, Haiku, + Android) have an array 'sys_siglist'. (On AIX, you need to declare it + yourself, and it has fewer than NSIG elements.) Its contents varies + depending on the OS. + On other OSes, you can invoke strsignal (sig) in the C locale. + In the code below, we show the differences. + You can see how cryptic some of these strings are. We try to pick more + understandable wordings. */ + + switch (sig) + { + /* Signals specified by ISO C. */ + case SIGABRT: + /* glibc: "Aborted". *BSD: "Abort trap". Solaris: "Abort". */ + return "Aborted"; + case SIGFPE: + /* glibc, *BSD: "Floating point exception". Solaris: "Arithmetic exception". + The latter is more correct, because of integer division by 0 or -1. */ + return "Arithmetic exception"; + case SIGILL: + return "Illegal instruction"; + case SIGINT: + return "Interrupt"; + case SIGSEGV: + return "Segmentation fault"; + case SIGTERM: + return "Terminated"; + + /* Signals specified by POSIX. + */ + #if defined SIGALRM + case SIGALRM: + return "Alarm clock"; + #endif + #if defined SIGBUS + case SIGBUS: + return "Bus error"; + #endif + #if defined SIGCHLD + case SIGCHLD: + /* glibc, *BSD: "Child exited". Solaris: "Child status changed". */ + return "Child stopped or exited"; + #endif + #if defined SIGCONT + case SIGCONT: + return "Continued"; + #endif + #if defined SIGHUP + case SIGHUP: + return "Hangup"; + #endif + #if defined SIGKILL + case SIGKILL: + return "Killed"; + #endif + #if defined SIGPIPE + case SIGPIPE: + return "Broken pipe"; + #endif + #if defined SIGQUIT + case SIGQUIT: + return "Quit"; + #endif + #if defined SIGSTOP + case SIGSTOP: + /* glibc, Solaris: "Stopped (signal)". *BSD: "Suspended (signal)". */ + return "Stopped (signal)"; + #endif + #if defined SIGTSTP + case SIGTSTP: + /* glibc: "Stopped". *BSD: "Suspended". Solaris: "Stopped (user)". */ + return "Stopped"; + #endif + #if defined SIGTTIN + case SIGTTIN: + return "Stopped (tty input)"; + #endif + #if defined SIGTTOU + case SIGTTOU: + return "Stopped (tty output)"; + #endif + #if defined SIGUSR1 + case SIGUSR1: + /* glibc, *BSD: "User defined signal 1". Solaris: "User signal 1". */ + return "User defined signal 1"; + #endif + #if defined SIGUSR2 + case SIGUSR2: + /* glibc, *BSD: "User defined signal 2". Solaris: "User signal 2". */ + return "User defined signal 2"; + #endif + #if defined SIGPOLL + case SIGPOLL: + /* glibc: "I/O possible". Solaris: "Pollable event". */ + return "I/O possible"; + #endif + #if defined SIGPROF + case SIGPROF: + return "Profiling timer expired"; + #endif + #if defined SIGSYS + case SIGSYS: + return "Bad system call"; + #endif + #if defined SIGTRAP + case SIGTRAP: + /* glibc, Solaris: "Trace/breakpoint trap". *BSD: "Trace/BPT trap". */ + return "Trace/breakpoint trap"; + #endif + #if defined SIGURG + case SIGURG: + /* glibc, *BSD: "Urgent I/O condition". Solaris: "Urgent socket condition". */ + return "Urgent I/O condition"; + #endif + #if defined SIGVTALRM + case SIGVTALRM: + return "Virtual timer expired"; + #endif + #if defined SIGXCPU + case SIGXCPU: + /* glibc, *BSD: "CPU time limit exceeded". Solaris: "Cpu limit exceeded". */ + return "CPU time limit exceeded"; + #endif + #if defined SIGXFSZ + case SIGXFSZ: + return "File size limit exceeded"; + #endif + + /* Other signals on other systems. */ + /* native Windows */ + #if defined SIGBREAK + case SIGBREAK: + return "Ctrl-Break"; + #endif + /* IRIX */ + #if defined SIGCKPT + case SIGCKPT: + return "Checkpoint"; /* See man 1 cpr, man 3C atcheckpoint */ + #endif + /* Linux, IRIX, Cygwin */ + #if defined SIGCLD && SIGCLD != SIGCHLD + case SIGCLD: + return "Child stopped or exited"; + #endif + /* AIX */ + #if defined SIGCPUFAIL + case SIGCPUFAIL: + /* AIX: "CPU failure predicted". */ + return "CPU going down"; /* See man bindprocessor */ + #endif + /* AIX */ + #if defined SIGDANGER + case SIGDANGER: + /* AIX: "Paging space low". */ + return "Swap space nearly exhausted"; + #endif + /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, mingw */ + #if defined SIGEMT + case SIGEMT: + /* glibc/Hurd, *BSD: "EMT trap". Solaris: "Emulation trap". */ + return "Instruction emulation needed"; + #endif + /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix */ + #if defined SIGINFO && SIGINFO != SIGPWR + case SIGINFO: + return "Information request"; + #endif + /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin */ + #if defined SIGIO && SIGIO != SIGPOLL + case SIGIO: + return "I/O possible"; + #endif + /* Linux, IRIX, Cygwin, mingw */ + #if defined SIGIOT && SIGIOT != SIGABRT + case SIGIOT: + return "IOT instruction"; /* a PDP-11 instruction */ + #endif + /* AIX */ + #if defined SIGKAP + case SIGKAP: + /* Process must issue a KSKAPACK ioctl, or will be killed in 30 seconds. */ + /* AIX: "Monitor mode granted". */ + return "Keep Alive Poll"; + #endif + /* Haiku */ + #if defined SIGKILLTHR + case SIGKILLTHR: + return "Kill thread"; + #endif + /* Minix */ + #if defined SIGKMEM + case SIGKMEM: + return "Kernel memory request"; + #endif + /* Minix */ + #if defined SIGKMESS + case SIGKMESS: + return "Kernel message"; + #endif + /* Minix */ + #if defined SIGKSIG + case SIGKSIG: + return "Kernel signal"; + #endif + /* Minix */ + #if defined SIGKSIGSM + case SIGKSIGSM: + return "Kernel signal for signal manager"; + #endif + /* FreeBSD */ + #if defined SIGLIBRT + case SIGLIBRT: + return "Real-time library interrupt"; + #endif + /* Cygwin */ + #if defined SIGLOST && SIGLOST != SIGABRT && SIGLOST != SIGPWR + case SIGLOST: + /* Solaris: "Resource lost". */ + return "File lock lost"; + #endif + /* AIX */ + #if defined SIGMIGRATE + case SIGMIGRATE: + return "Process migration"; + #endif + /* AIX */ + #if defined SIGMSG + case SIGMSG: + /* AIX: "Input device data". */ + return "Message in the ring"; + #endif + /* ACM */ + #if defined SIGPLAN + case SIGPLAN: + return "Programming language anomaly"; + #endif + /* AIX */ + #if defined SIGPRE + case SIGPRE: + return "Programmed exception"; + #endif + /* IRIX */ + #if defined SIGPTINTR + case SIGPTINTR: + return "Pthread interrupt"; + #endif + /* IRIX */ + #if defined SIGPTRESCHED + case SIGPTRESCHED: + return "Pthread rescheduling"; + #endif + /* Linux, NetBSD, Minix, AIX, IRIX, Cygwin */ + #if defined SIGPWR + case SIGPWR: + /* glibc: "Power failure". NetBSD: "Power fail/restart". */ + return "Power failure"; + #endif + /* AIX */ + #if defined SIGRECONFIG + case SIGRECONFIG: + return "Dynamic logical partitioning changed"; + #endif + /* AIX */ + #if defined SIGRECOVERY + case SIGRECOVERY: + return "Kernel recovery"; + #endif + /* IRIX */ + #if defined SIGRESTART + case SIGRESTART: + return "Checkpoint restart"; /* See man 1 cpr, man 3C atrestart */ + #endif + /* AIX */ + #if defined SIGRETRACT + case SIGRETRACT: + /* AIX: "Monitor mode retracted". */ + return "Retracting Keep Alive Poll"; + #endif + /* AIX */ + #if defined SIGSAK + case SIGSAK: + /* AIX: "Secure attention". */ + return "Secure Attention Key"; + #endif + /* ACM */ + #if defined SIGSAM + case SIGSAM: + return "Symbolic computation failed"; + #endif + /* Minix */ + #if defined SIGSNDELAY + case SIGSNDELAY: + return "Done sending message"; + #endif + /* AIX */ + #if defined SIGSOUND + case SIGSOUND: + /* AIX: "Sound completed". */ + return "Sound configuration changed"; + #endif + /* Linux */ + #if defined SIGSTKFLT + case SIGSTKFLT: + return "Stack fault"; + #endif + /* AIX */ + #if defined SIGSYSERROR + case SIGSYSERROR: + return "Kernel error"; + #endif + /* AIX */ + #if defined SIGTALRM + case SIGTALRM: + return "Thread alarm clock"; + #endif + /* FreeBSD, OpenBSD */ + #if defined SIGTHR + case SIGTHR: + /* OpenBSD: "Thread AST". */ + return "Thread library interrupt"; + #endif + /* IRIX */ + #if defined SIGUME + case SIGUME: + return "Uncorrectable memory error"; + #endif + /* AIX */ + #if defined SIGVIRT + case SIGVIRT: + return "Virtual time alarm clock"; + #endif + /* AIX */ + #if defined SIGWAITING + case SIGWAITING: + /* AIX: "No runnable lwp". */ + return "Thread waiting"; + #endif + /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, Haiku */ + #if defined SIGWINCH + case SIGWINCH: + /* glibc: "Window changed". *BSD: "Window size changed" or "Window size changes". */ + return "Window size changed"; + #endif + + default: + return NULL; + } +} diff --git a/cross/lib/signal.in.h b/cross/lib/signal.in.h new file mode 100644 index 00000000000..fea12e6572d --- /dev/null +++ b/cross/lib/signal.in.h @@ -0,0 +1,495 @@ +/* A GNU-like . + + Copyright (C) 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_sig_atomic_t || defined __need_sigset_t || defined _GL_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T) +/* Special invocation convention: + - Inside glibc header files. + - On glibc systems we have a sequence of nested includes + -> -> . + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. + - On glibc systems with GCC 4.3 we have a sequence of nested includes + -> -> -> . + In this situation, some of the functions are not yet declared, therefore + we cannot provide the C++ aliases. */ + +# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SIGNAL_H + +#define _GL_ALREADY_INCLUDING_SIGNAL_H + +/* Define pid_t, uid_t. + Also, mingw defines sigset_t not in , but in . + On Solaris 10, includes , which eventually includes + us; so include now, before the second inclusion guard. */ +#include + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@ + +#undef _GL_ALREADY_INCLUDING_SIGNAL_H + +#ifndef _@GUARD_PREFIX@_SIGNAL_H +#define _@GUARD_PREFIX@_SIGNAL_H + +/* For testing the OpenBSD version. */ +#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ + && defined __OpenBSD__ +# include +#endif + +/* Mac OS X 10.3, FreeBSD < 8.0, OpenBSD < 5.1, OSF/1 4.0, Solaris 2.6, Android, + OS/2 kLIBC declare pthread_sigmask in , not in . + But avoid namespace pollution on glibc systems.*/ +#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ + && ((defined __APPLE__ && defined __MACH__) \ + || (defined __FreeBSD__ && __FreeBSD__ < 8) \ + || (defined __OpenBSD__ && OpenBSD < 201205) \ + || defined __osf__ || defined __sun || defined __ANDROID__ \ + || defined __KLIBC__) \ + && ! defined __GLIBC__ +# include +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* On AIX, sig_atomic_t already includes volatile. C99 requires that + 'volatile sig_atomic_t' ignore the extra modifier, but C89 did not. + Hence, redefine this to a non-volatile type as needed. */ +#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +# if !GNULIB_defined_sig_atomic_t +typedef int rpl_sig_atomic_t; +# undef sig_atomic_t +# define sig_atomic_t rpl_sig_atomic_t +# define GNULIB_defined_sig_atomic_t 1 +# endif +#endif + +/* A set or mask of signals. */ +#if !@HAVE_SIGSET_T@ +# if !GNULIB_defined_sigset_t +typedef unsigned int sigset_t; +# define GNULIB_defined_sigset_t 1 +# endif +#endif + +/* Define sighandler_t, the type of signal handlers. A GNU extension. */ +#if !@HAVE_SIGHANDLER_T@ +# ifdef __cplusplus +extern "C" { +# endif +# if !GNULIB_defined_sighandler_t +typedef void (*sighandler_t) (int); +# define GNULIB_defined_sighandler_t 1 +# endif +# ifdef __cplusplus +} +# endif +#endif + + +#if @GNULIB_SIGNAL_H_SIGPIPE@ +# ifndef SIGPIPE +/* Define SIGPIPE to a value that does not overlap with other signals. */ +# define SIGPIPE 13 +# define GNULIB_defined_SIGPIPE 1 +/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask', + 'write', 'stdio'. */ +# endif +#endif + + +/* Maximum signal number + 1. */ +#ifndef NSIG +# if defined __TANDEM +# define NSIG 32 +# endif +#endif + + +#if @GNULIB_PTHREAD_SIGMASK@ +# if @REPLACE_PTHREAD_SIGMASK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pthread_sigmask +# define pthread_sigmask rpl_pthread_sigmask +# endif +_GL_FUNCDECL_RPL (pthread_sigmask, int, + (int how, + const sigset_t *restrict new_mask, + sigset_t *restrict old_mask)); +_GL_CXXALIAS_RPL (pthread_sigmask, int, + (int how, + const sigset_t *restrict new_mask, + sigset_t *restrict old_mask)); +# else +# if !(@HAVE_PTHREAD_SIGMASK@ || defined pthread_sigmask) +_GL_FUNCDECL_SYS (pthread_sigmask, int, + (int how, + const sigset_t *restrict new_mask, + sigset_t *restrict old_mask)); +# endif +_GL_CXXALIAS_SYS (pthread_sigmask, int, + (int how, + const sigset_t *restrict new_mask, + sigset_t *restrict old_mask)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (pthread_sigmask); +# endif +#elif defined GNULIB_POSIXCHECK +# undef pthread_sigmask +# if HAVE_RAW_DECL_PTHREAD_SIGMASK +_GL_WARN_ON_USE (pthread_sigmask, "pthread_sigmask is not portable - " + "use gnulib module pthread_sigmask for portability"); +# endif +#endif + + +#if @GNULIB_RAISE@ +# if @REPLACE_RAISE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef raise +# define raise rpl_raise +# endif +_GL_FUNCDECL_RPL (raise, int, (int sig)); +_GL_CXXALIAS_RPL (raise, int, (int sig)); +# else +# if !@HAVE_RAISE@ +_GL_FUNCDECL_SYS (raise, int, (int sig)); +# endif +_GL_CXXALIAS_SYS (raise, int, (int sig)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (raise); +# endif +#elif defined GNULIB_POSIXCHECK +# undef raise +/* Assume raise is always declared. */ +_GL_WARN_ON_USE (raise, "raise can crash on native Windows - " + "use gnulib module raise for portability"); +#endif + + +#if @GNULIB_SIGPROCMASK@ +# if !@HAVE_POSIX_SIGNALBLOCKING@ + +# ifndef GNULIB_defined_signal_blocking +# define GNULIB_defined_signal_blocking 1 +# endif + +/* Maximum signal number + 1. */ +# ifndef NSIG +# define NSIG 32 +# endif + +/* This code supports only 32 signals. */ +# if !GNULIB_defined_verify_NSIG_constraint +typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1]; +# define GNULIB_defined_verify_NSIG_constraint 1 +# endif + +# endif + +/* When also using extern inline, suppress the use of static inline in + standard headers of problematic Apple configurations, as Libc at + least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., + . + Perhaps Apple will fix this some day. */ +#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ + && (defined __i386__ || defined __x86_64__)) +# undef sigaddset +# undef sigdelset +# undef sigemptyset +# undef sigfillset +# undef sigismember +#endif + +/* Test whether a given signal is contained in a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigismember +# endif +# else +_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigismember); + +/* Initialize a signal set to the empty set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigemptyset +# endif +# else +_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigemptyset); + +/* Add a signal to a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigaddset +# endif +# else +_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigaddset); + +/* Remove a signal from a signal set. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigdelset +# endif +# else +_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig)); +_GL_CXXALIASWARN (sigdelset); + +/* Fill a signal set with all possible signals. */ +# if @HAVE_POSIX_SIGNALBLOCKING@ +/* This function is defined as a macro on Mac OS X. */ +# if defined __cplusplus && defined GNULIB_NAMESPACE +# undef sigfillset +# endif +# else +_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigfillset); + +/* Return the set of those blocked signals that are pending. */ +# if !@HAVE_POSIX_SIGNALBLOCKING@ +_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set)); +_GL_CXXALIASWARN (sigpending); + +/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET. + Then, if SET is not NULL, affect the current set of blocked signals by + combining it with *SET as indicated in OPERATION. + In this implementation, you are not allowed to change a signal handler + while the signal is blocked. */ +# if !@HAVE_POSIX_SIGNALBLOCKING@ +# define SIG_BLOCK 0 /* blocked_set = blocked_set | *set; */ +# define SIG_SETMASK 1 /* blocked_set = *set; */ +# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */ +_GL_FUNCDECL_SYS (sigprocmask, int, + (int operation, + const sigset_t *restrict set, + sigset_t *restrict old_set)); +# endif +_GL_CXXALIAS_SYS (sigprocmask, int, + (int operation, + const sigset_t *restrict set, + sigset_t *restrict old_set)); +_GL_CXXALIASWARN (sigprocmask); + +/* Install the handler FUNC for signal SIG, and return the previous + handler. */ +# ifdef __cplusplus +extern "C" { +# endif +# if !GNULIB_defined_function_taking_int_returning_void_t +typedef void (*_gl_function_taking_int_returning_void_t) (int); +# define GNULIB_defined_function_taking_int_returning_void_t 1 +# endif +# ifdef __cplusplus +} +# endif +# if !@HAVE_POSIX_SIGNALBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define signal rpl_signal +# endif +_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +# else +/* On OpenBSD, the declaration of 'signal' may not be present at this point, + because it occurs in , not directly. */ +# if defined __OpenBSD__ +_GL_FUNCDECL_SYS (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +# endif +_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t, + (int sig, _gl_function_taking_int_returning_void_t func)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (signal); +# endif + +# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE +/* Raise signal SIGPIPE. */ +_GL_EXTERN_C int _gl_raise_SIGPIPE (void); +# endif + +#elif defined GNULIB_POSIXCHECK +# undef sigaddset +# if HAVE_RAW_DECL_SIGADDSET +_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigdelset +# if HAVE_RAW_DECL_SIGDELSET +_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigemptyset +# if HAVE_RAW_DECL_SIGEMPTYSET +_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigfillset +# if HAVE_RAW_DECL_SIGFILLSET +_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigismember +# if HAVE_RAW_DECL_SIGISMEMBER +_GL_WARN_ON_USE (sigismember, "sigismember is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigpending +# if HAVE_RAW_DECL_SIGPENDING +_GL_WARN_ON_USE (sigpending, "sigpending is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +# undef sigprocmask +# if HAVE_RAW_DECL_SIGPROCMASK +_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - " + "use the gnulib module sigprocmask for portability"); +# endif +#endif /* @GNULIB_SIGPROCMASK@ */ + + +#if @GNULIB_SIGACTION@ +# if !@HAVE_SIGACTION@ + +# if !@HAVE_SIGINFO_T@ + +# if !GNULIB_defined_siginfo_types + +/* Present to allow compilation, but unsupported by gnulib. */ +union sigval +{ + int sival_int; + void *sival_ptr; +}; + +/* Present to allow compilation, but unsupported by gnulib. */ +struct siginfo_t +{ + int si_signo; + int si_code; + int si_errno; + pid_t si_pid; + uid_t si_uid; + void *si_addr; + int si_status; + long si_band; + union sigval si_value; +}; +typedef struct siginfo_t siginfo_t; + +# define GNULIB_defined_siginfo_types 1 +# endif + +# endif /* !@HAVE_SIGINFO_T@ */ + +/* We assume that platforms which lack the sigaction() function also lack + the 'struct sigaction' type, and vice versa. */ + +# if !GNULIB_defined_struct_sigaction + +struct sigaction +{ + union + { + void (*_sa_handler) (int); + /* Present to allow compilation, but unsupported by gnulib. POSIX + says that implementations may, but not must, make sa_sigaction + overlap with sa_handler, but we know of no implementation where + they do not overlap. */ + void (*_sa_sigaction) (int, siginfo_t *, void *); + } _sa_func; + sigset_t sa_mask; + /* Not all POSIX flags are supported. */ + int sa_flags; +}; +# define sa_handler _sa_func._sa_handler +# define sa_sigaction _sa_func._sa_sigaction +/* Unsupported flags are not present. */ +# define SA_RESETHAND 1 +# define SA_NODEFER 2 +# define SA_RESTART 4 + +# define GNULIB_defined_struct_sigaction 1 +# endif + +_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict, + struct sigaction *restrict)); + +# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ + +# define sa_sigaction sa_handler + +# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */ + +_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict, + struct sigaction *restrict)); +_GL_CXXALIASWARN (sigaction); + +#elif defined GNULIB_POSIXCHECK +# undef sigaction +# if HAVE_RAW_DECL_SIGACTION +_GL_WARN_ON_USE (sigaction, "sigaction is unportable - " + "use the gnulib module sigaction for portability"); +# endif +#endif + +/* Some systems don't have SA_NODEFER. */ +#ifndef SA_NODEFER +# define SA_NODEFER 0 +#endif + + +#endif /* _@GUARD_PREFIX@_SIGNAL_H */ +#endif /* _@GUARD_PREFIX@_SIGNAL_H */ +#endif diff --git a/cross/lib/stat-time.c b/cross/lib/stat-time.c new file mode 100644 index 00000000000..bc282232ab3 --- /dev/null +++ b/cross/lib/stat-time.c @@ -0,0 +1,21 @@ +/* stat-related time functions. + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define _GL_STAT_TIME_INLINE _GL_EXTERN_INLINE +#include "stat-time.h" diff --git a/cross/lib/stat-time.h b/cross/lib/stat-time.h new file mode 100644 index 00000000000..92aa1e64e20 --- /dev/null +++ b/cross/lib/stat-time.h @@ -0,0 +1,251 @@ +/* stat-related time functions. + + Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef STAT_TIME_H +#define STAT_TIME_H 1 + +#include +#include +#include +#include +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_STAT_TIME_INLINE +# define _GL_STAT_TIME_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type + struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST, + ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST, + if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim + for access, status change, data modification, or birth (creation) + time respectively. + + These macros are private to stat-time.h. */ +#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC +# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) +# else +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) +# endif +#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC +# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) +#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) +#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC +# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec) +#endif + +/* Return the nanosecond component of *ST's access time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_atime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_atim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_atim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's status change time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_ctime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_ctim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_ctim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's data modification time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_mtime_ns (struct stat const *st) +{ +# if defined STAT_TIMESPEC + return STAT_TIMESPEC (st, st_mtim).tv_nsec; +# elif defined STAT_TIMESPEC_NS + return STAT_TIMESPEC_NS (st, st_mtim); +# else + return 0; +# endif +} + +/* Return the nanosecond component of *ST's birth time. */ +_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE +get_stat_birthtime_ns (_GL_UNUSED struct stat const *st) +{ +# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC + return STAT_TIMESPEC (st, st_birthtim).tv_nsec; +# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC + return STAT_TIMESPEC_NS (st, st_birthtim); +# else + return 0; +# endif +} + +/* Return *ST's access time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_atime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_atim); +#else + struct timespec t; + t.tv_sec = st->st_atime; + t.tv_nsec = get_stat_atime_ns (st); + return t; +#endif +} + +/* Return *ST's status change time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_ctime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_ctim); +#else + struct timespec t; + t.tv_sec = st->st_ctime; + t.tv_nsec = get_stat_ctime_ns (st); + return t; +#endif +} + +/* Return *ST's data modification time. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_mtime (struct stat const *st) +{ +#ifdef STAT_TIMESPEC + return STAT_TIMESPEC (st, st_mtim); +#else + struct timespec t; + t.tv_sec = st->st_mtime; + t.tv_nsec = get_stat_mtime_ns (st); + return t; +#endif +} + +/* Return *ST's birth time, if available; otherwise return a value + with tv_sec and tv_nsec both equal to -1. */ +_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE +get_stat_birthtime (_GL_UNUSED struct stat const *st) +{ + struct timespec t; + +#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) + t = STAT_TIMESPEC (st, st_birthtim); +#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC + t.tv_sec = st->st_birthtime; + t.tv_nsec = st->st_birthtimensec; +#elif defined _WIN32 && ! defined __CYGWIN__ + /* Native Windows platforms (but not Cygwin) put the "file creation + time" in st_ctime (!). See + . */ +# if _GL_WINDOWS_STAT_TIMESPEC + t = st->st_ctim; +# else + t.tv_sec = st->st_ctime; + t.tv_nsec = 0; +# endif +#else + /* Birth time is not supported. */ + t.tv_sec = -1; + t.tv_nsec = -1; +#endif + +#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \ + || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) + /* FreeBSD and NetBSD sometimes signal the absence of knowledge by + using zero. Attempt to work around this problem. Alas, this can + report failure even for valid timestamps. Also, NetBSD + sometimes returns junk in the birth time fields; work around this + bug if it is detected. */ + if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) + { + t.tv_sec = -1; + t.tv_nsec = -1; + } +#endif + + return t; +} + +/* If a stat-like function returned RESULT, normalize the timestamps + in *ST, in case this platform suffers from the Solaris 11 bug where + tv_nsec might be negative. Return the adjusted RESULT, setting + errno to EOVERFLOW if normalization overflowed. This function + is intended to be private to this .h file. */ +_GL_STAT_TIME_INLINE int +stat_time_normalize (int result, _GL_UNUSED struct stat *st) +{ +#if defined __sun && defined STAT_TIMESPEC + if (result == 0) + { + long int timespec_hz = 1000000000; + short int const ts_off[] = { offsetof (struct stat, st_atim), + offsetof (struct stat, st_mtim), + offsetof (struct stat, st_ctim) }; + int i; + for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) + { + struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]); + long int q = ts->tv_nsec / timespec_hz; + long int r = ts->tv_nsec % timespec_hz; + if (r < 0) + { + r += timespec_hz; + q--; + } + ts->tv_nsec = r; + /* Overflow is possible, as Solaris 11 stat can yield + tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. + INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */ + if (ckd_add (&ts->tv_sec, q, ts->tv_sec)) + { + errno = EOVERFLOW; + return -1; + } + } + } +#endif + return result; +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif diff --git a/cross/lib/stdalign.in.h b/cross/lib/stdalign.in.h new file mode 100644 index 00000000000..6523546f16d --- /dev/null +++ b/cross/lib/stdalign.in.h @@ -0,0 +1,34 @@ +/* A substitute for ISO C11 . + + Copyright 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert and Bruno Haible. */ + +/* Define two obsolescent C11 macros, assuming alignas and alignof are + either keywords or alignasof-defined macros. */ + +#ifndef _GL_STDALIGN_H +#define _GL_STDALIGN_H + +#if (defined alignas \ + || (defined __STDC_VERSION__ && 202311 <= __STDC_VERSION__) \ + || (defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER))) +# define __alignas_is_defined 1 +#endif + +#define __alignof_is_defined 1 + +#endif /* _GL_STDALIGN_H */ diff --git a/cross/lib/stdckdint.in.h b/cross/lib/stdckdint.in.h new file mode 100644 index 00000000000..71bab5f0c9e --- /dev/null +++ b/cross/lib/stdckdint.in.h @@ -0,0 +1,35 @@ +/* stdckdint.h -- checked integer arithmetic + + Copyright 2022-2023 Free Software Foundation, Inc. + + This program 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 program is distributed in the hope that 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 program. If not, see . */ + +#ifndef _GL_STDCKDINT_H +#define _GL_STDCKDINT_H + +#include "intprops-internal.h" + +/* Store into *R the low-order bits of A + B, A - B, A * B, respectively. + Return 1 if the result overflows, 0 otherwise. + A, B, and *R can have any integer type other than char, bool, a + bit-precise integer type, or an enumeration type. + + These are like the standard macros introduced in C23, except that + arguments should not have side effects. */ + +#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r)) +#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r)) +#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r)) + +#endif /* _GL_STDCKDINT_H */ diff --git a/cross/lib/stddef.in.h b/cross/lib/stddef.in.h new file mode 100644 index 00000000000..6eadcc3d5a4 --- /dev/null +++ b/cross/lib/stddef.in.h @@ -0,0 +1,147 @@ +/* A substitute for POSIX 2008 , for platforms that have issues. + + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Eric Blake. */ + +/* + * POSIX 2008 for platforms that have issues. + * + */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_wchar_t || defined __need_size_t \ + || defined __need_ptrdiff_t || defined __need_NULL \ + || defined __need_wint_t +/* Special invocation convention inside gcc header files. In + particular, gcc provides a version of that blindly + redefines NULL even when __need_wint_t was defined, even though + wint_t is not normally provided by . Hence, we must + remember if special invocation has ever been used to obtain wint_t, + in which case we need to clean up NULL yet again. */ + +# if !(defined _@GUARD_PREFIX@_STDDEF_H && defined _GL_STDDEF_WINT_T) +# ifdef __need_wint_t +# define _GL_STDDEF_WINT_T +# endif +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ + /* On TinyCC, make sure that the macros that indicate the special invocation + convention get undefined. */ +# undef __need_wchar_t +# undef __need_size_t +# undef __need_ptrdiff_t +# undef __need_NULL +# undef __need_wint_t +# endif + +#else +/* Normal invocation convention. */ + +# ifndef _@GUARD_PREFIX@_STDDEF_H + +/* On AIX 7.2, with xlc in 64-bit mode, defines max_align_t to a + type with alignment 4, but 'long' has alignment 8. */ +# if defined _AIX && defined __LP64__ +# if !GNULIB_defined_max_align_t +# ifdef _MAX_ALIGN_T +/* /usr/include/stddef.h has already defined max_align_t. Override it. */ +typedef long rpl_max_align_t; +# define max_align_t rpl_max_align_t +# else +/* Prevent /usr/include/stddef.h from defining max_align_t. */ +typedef long max_align_t; +# define _MAX_ALIGN_T +# endif +# define GNULIB_defined_max_align_t 1 +# endif +# endif + +/* The include_next requires a split double-inclusion guard. */ + +# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ + +/* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ +# if (@REPLACE_NULL@ \ + && (!defined _@GUARD_PREFIX@_STDDEF_H || defined _GL_STDDEF_WINT_T)) +# undef NULL +# ifdef __cplusplus + /* ISO C++ says that the macro NULL must expand to an integer constant + expression, hence '((void *) 0)' is not allowed in C++. */ +# if __GNUG__ >= 3 + /* GNU C++ has a __null macro that behaves like an integer ('int' or + 'long') but has the same size as a pointer. Use that, to avoid + warnings. */ +# define NULL __null +# else +# define NULL 0L +# endif +# else +# define NULL ((void *) 0) +# endif +# endif + +# ifndef _@GUARD_PREFIX@_STDDEF_H +# define _@GUARD_PREFIX@_STDDEF_H + +/* Some platforms lack wchar_t. */ +#if !@HAVE_WCHAR_T@ +# define wchar_t int +#endif + +/* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is + a hack in case the configure-time test was done with g++ even though + we are currently compiling with gcc. + On MSVC, max_align_t is defined only in C++ mode, after was + included. Its definition is good since it has an alignment of 8 (on x86 + and x86_64). + Similarly on OS/2 kLIBC. */ +#if (defined _MSC_VER || (defined __KLIBC__ && !defined __LIBCN__)) \ + && defined __cplusplus +# include +#else +# if ! (@HAVE_MAX_ALIGN_T@ || (defined _GCC_MAX_ALIGN_T && !defined __clang__)) +# if !GNULIB_defined_max_align_t +/* On the x86, the maximum storage alignment of double, long, etc. is 4, + but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8, + and the C11 standard allows this. Work around this problem by + using __alignof__ (which returns 8 for double) rather than _Alignof + (which returns 4), and align each union member accordingly. */ +# if defined __GNUC__ || (__clang_major__ >= 4) +# define _GL_STDDEF_ALIGNAS(type) \ + __attribute__ ((__aligned__ (__alignof__ (type)))) +# else +# define _GL_STDDEF_ALIGNAS(type) /* */ +# endif +typedef union +{ + char *__p _GL_STDDEF_ALIGNAS (char *); + double __d _GL_STDDEF_ALIGNAS (double); + long double __ld _GL_STDDEF_ALIGNAS (long double); + long int __i _GL_STDDEF_ALIGNAS (long int); +} rpl_max_align_t; +# define max_align_t rpl_max_align_t +# define GNULIB_defined_max_align_t 1 +# endif +# endif +#endif + +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +# endif /* _@GUARD_PREFIX@_STDDEF_H */ +#endif /* __need_XXX */ diff --git a/cross/lib/stdint.in.h b/cross/lib/stdint.in.h new file mode 100644 index 00000000000..5ddc644b8ee --- /dev/null +++ b/cross/lib/stdint.in.h @@ -0,0 +1,740 @@ +/* Copyright (C) 2001-2002, 2004-2023 Free Software Foundation, Inc. + Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. + This file is part of gnulib. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* + * ISO C 99 for platforms that lack it. + * + */ + +#ifndef _@GUARD_PREFIX@_STDINT_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* When including a system file that in turn includes , + use the system , not our substitute. This avoids + problems with (for example) VMS, whose includes + . */ +#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* On Android (Bionic libc), includes this file before + having defined 'time_t'. Therefore in this case avoid including + other system header files; just include the system's . + Ideally we should test __BIONIC__ here, but it is only defined after + has been included; hence test __ANDROID__ instead. */ +#if defined __ANDROID__ && defined _GL_INCLUDING_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#else + +/* Get those types that are already defined in other system include + files, so that we can "#define int8_t signed char" below without + worrying about a later system include file containing a "typedef + signed char int8_t;" that will get messed up by our macro. Our + macros should all be consistent with the system versions, except + for the "fast" types and macros, which we recommend against using + in public interfaces due to compiler differences. */ + +#if @HAVE_STDINT_H@ +# if defined __sgi && ! defined __c99 + /* Bypass IRIX's if in C89 mode, since it merely annoys users + with "This header file is to be used only for c99 mode compilations" + diagnostics. */ +# define __STDINT_H__ +# endif + + /* Some pre-C++11 implementations need this. */ +# ifdef __cplusplus +# ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 +# endif +# ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +# endif +# endif + + /* Other systems may have an incomplete or buggy . + Include it before , since any "#include " + in would reinclude us, skipping our contents because + _@GUARD_PREFIX@_STDINT_H is defined. + The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_STDINT_H@ +#endif + +#if ! defined _@GUARD_PREFIX@_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H +#define _@GUARD_PREFIX@_STDINT_H + +/* Get SCHAR_MIN, SCHAR_MAX, UCHAR_MAX, INT_MIN, INT_MAX, + LONG_MIN, LONG_MAX, ULONG_MAX, _GL_INTEGER_WIDTH. */ +#include + +/* Override WINT_MIN and WINT_MAX if gnulib's or overrides + wint_t. */ +#if @GNULIBHEADERS_OVERRIDE_WINT_T@ +# undef WINT_MIN +# undef WINT_MAX +# define WINT_MIN 0x0U +# define WINT_MAX 0xffffffffU +#endif + +#if ! @HAVE_C99_STDINT_H@ + +/* defines some of the stdint.h types as well, on glibc, + IRIX 6.5, and OpenBSD 3.8 (via ). + AIX 5.2 isn't needed and causes troubles. + Mac OS X 10.4.6 includes (which is us), but + relies on the system definitions, so include + after @NEXT_STDINT_H@. */ +# if @HAVE_SYS_TYPES_H@ && ! defined _AIX +# include +# endif + +# if @HAVE_INTTYPES_H@ + /* In OpenBSD 3.8, includes , which defines + int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. + also defines intptr_t and uintptr_t. */ +# include +# elif @HAVE_SYS_INTTYPES_H@ + /* Solaris 7 has the types except the *_fast*_t types, and + the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ +# include +# endif + +# if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ + /* Linux libc4 >= 4.6.7 and libc5 have a that defines + int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is + included by . */ +# include +# endif + +# undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H + +/* Minimum and maximum values for an integer type under the usual assumption. + Return an unspecified value if BITS == 0, adding a check to pacify + picky compilers. */ + +/* These are separate macros, because if you try to merge these macros into + a single one, HP-UX cc rejects the resulting expression in constant + expressions. */ +# define _STDINT_UNSIGNED_MIN(bits, zero) \ + (zero) +# define _STDINT_SIGNED_MIN(bits, zero) \ + (~ _STDINT_MAX (1, bits, zero)) + +# define _STDINT_MAX(signed, bits, zero) \ + (((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) + +#if !GNULIB_defined_stdint_types + +/* 7.18.1.1. Exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef int8_t +# undef uint8_t +typedef signed char gl_int8_t; +typedef unsigned char gl_uint8_t; +# define int8_t gl_int8_t +# define uint8_t gl_uint8_t + +# undef int16_t +# undef uint16_t +typedef short int gl_int16_t; +typedef unsigned short int gl_uint16_t; +# define int16_t gl_int16_t +# define uint16_t gl_uint16_t + +# undef int32_t +# undef uint32_t +typedef int gl_int32_t; +typedef unsigned int gl_uint32_t; +# define int32_t gl_int32_t +# define uint32_t gl_uint32_t + +/* If the system defines INT64_MAX, assume int64_t works. That way, + if the underlying platform defines int64_t to be a 64-bit long long + int, the code below won't mistakenly define it to be a 64-bit long + int, which would mess up C++ name mangling. We must use #ifdef + rather than #if, to avoid an error with HP-UX 10.20 cc. */ + +# ifdef INT64_MAX +# define GL_INT64_T +# else +/* Do not undefine int64_t if gnulib is not being used with 64-bit + types, since otherwise it breaks platforms like Tandem/NSK. */ +# if LONG_MAX >> 31 >> 31 == 1 +# undef int64_t +typedef long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# elif defined _MSC_VER +# undef int64_t +typedef __int64 gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# else +# undef int64_t +typedef long long int gl_int64_t; +# define int64_t gl_int64_t +# define GL_INT64_T +# endif +# endif + +# ifdef UINT64_MAX +# define GL_UINT64_T +# else +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# undef uint64_t +typedef unsigned long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# elif defined _MSC_VER +# undef uint64_t +typedef unsigned __int64 gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# else +# undef uint64_t +typedef unsigned long long int gl_uint64_t; +# define uint64_t gl_uint64_t +# define GL_UINT64_T +# endif +# endif + +/* Avoid collision with Solaris 2.5.1 etc. */ +# define _UINT8_T +# define _UINT32_T +# define _UINT64_T + + +/* 7.18.1.2. Minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef int_least8_t +# undef uint_least8_t +# undef int_least16_t +# undef uint_least16_t +# undef int_least32_t +# undef uint_least32_t +# undef int_least64_t +# undef uint_least64_t +# define int_least8_t int8_t +# define uint_least8_t uint8_t +# define int_least16_t int16_t +# define uint_least16_t uint16_t +# define int_least32_t int32_t +# define uint_least32_t uint32_t +# ifdef GL_INT64_T +# define int_least64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_least64_t uint64_t +# endif + +/* 7.18.1.3. Fastest minimum-width integer types */ + +/* Note: Other substitutes may define these types differently. + It is not recommended to use these types in public header files. */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. The following code normally + uses types consistent with glibc, as that lessens the chance of + incompatibility with older GNU hosts. */ + +# undef int_fast8_t +# undef uint_fast8_t +# undef int_fast16_t +# undef uint_fast16_t +# undef int_fast32_t +# undef uint_fast32_t +# undef int_fast64_t +# undef uint_fast64_t +typedef signed char gl_int_fast8_t; +typedef unsigned char gl_uint_fast8_t; + +# ifdef __sun +/* Define types compatible with SunOS 5.10, so that code compiled under + earlier SunOS versions works with code compiled under SunOS 5.10. */ +typedef int gl_int_fast32_t; +typedef unsigned int gl_uint_fast32_t; +# else +typedef long int gl_int_fast32_t; +typedef unsigned long int gl_uint_fast32_t; +# endif +typedef gl_int_fast32_t gl_int_fast16_t; +typedef gl_uint_fast32_t gl_uint_fast16_t; + +# define int_fast8_t gl_int_fast8_t +# define uint_fast8_t gl_uint_fast8_t +# define int_fast16_t gl_int_fast16_t +# define uint_fast16_t gl_uint_fast16_t +# define int_fast32_t gl_int_fast32_t +# define uint_fast32_t gl_uint_fast32_t +# ifdef GL_INT64_T +# define int_fast64_t int64_t +# endif +# ifdef GL_UINT64_T +# define uint_fast64_t uint64_t +# endif + +/* 7.18.1.4. Integer types capable of holding object pointers */ + +/* kLIBC's defines _INTPTR_T_DECLARED and needs its own + definitions of intptr_t and uintptr_t (which use int and unsigned) + to avoid clashes with declarations of system functions like sbrk. + Similarly, MinGW WSL-5.4.1 needs its own intptr_t and + uintptr_t to avoid conflicting declarations of system functions like + _findclose in . */ +# if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \ + || defined __MINGW32__) +# undef intptr_t +# undef uintptr_t +# ifdef _WIN64 +typedef long long int gl_intptr_t; +typedef unsigned long long int gl_uintptr_t; +# else +typedef long int gl_intptr_t; +typedef unsigned long int gl_uintptr_t; +# endif +# define intptr_t gl_intptr_t +# define uintptr_t gl_uintptr_t +# endif + +/* 7.18.1.5. Greatest-width integer types */ + +/* Note: These types are compiler dependent. It may be unwise to use them in + public header files. */ + +/* If the system defines INTMAX_MAX, assume that intmax_t works, and + similarly for UINTMAX_MAX and uintmax_t. This avoids problems with + assuming one type where another is used by the system. */ + +# ifndef INTMAX_MAX +# undef INTMAX_C +# undef intmax_t +# if LONG_MAX >> 30 == 1 +typedef long long int gl_intmax_t; +# define intmax_t gl_intmax_t +# elif defined GL_INT64_T +# define intmax_t int64_t +# else +typedef long int gl_intmax_t; +# define intmax_t gl_intmax_t +# endif +# endif + +# ifndef UINTMAX_MAX +# undef UINTMAX_C +# undef uintmax_t +# if ULONG_MAX >> 31 == 1 +typedef unsigned long long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# elif defined GL_UINT64_T +# define uintmax_t uint64_t +# else +typedef unsigned long int gl_uintmax_t; +# define uintmax_t gl_uintmax_t +# endif +# endif + +/* Verify that intmax_t and uintmax_t have the same size. Too much code + breaks if this is not the case. If this check fails, the reason is likely + to be found in the autoconf macros. */ +typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t) + ? 1 : -1]; + +# define GNULIB_defined_stdint_types 1 +# endif /* !GNULIB_defined_stdint_types */ + +/* 7.18.2. Limits of specified-width integer types */ + +/* 7.18.2.1. Limits of exact-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. */ + +# undef INT8_MIN +# undef INT8_MAX +# undef UINT8_MAX +# define INT8_MIN (~ INT8_MAX) +# define INT8_MAX 127 +# define UINT8_MAX 255 + +# undef INT16_MIN +# undef INT16_MAX +# undef UINT16_MAX +# define INT16_MIN (~ INT16_MAX) +# define INT16_MAX 32767 +# define UINT16_MAX 65535 + +# undef INT32_MIN +# undef INT32_MAX +# undef UINT32_MAX +# define INT32_MIN (~ INT32_MAX) +# define INT32_MAX 2147483647 +# define UINT32_MAX 4294967295U + +# if defined GL_INT64_T && ! defined INT64_MAX +/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 + evaluates the latter incorrectly in preprocessor expressions. */ +# define INT64_MIN (- INTMAX_C (1) << 63) +# define INT64_MAX INTMAX_C (9223372036854775807) +# endif + +# if defined GL_UINT64_T && ! defined UINT64_MAX +# define UINT64_MAX UINTMAX_C (18446744073709551615) +# endif + +/* 7.18.2.2. Limits of minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types + are the same as the corresponding N_t types. */ + +# undef INT_LEAST8_MIN +# undef INT_LEAST8_MAX +# undef UINT_LEAST8_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST8_MAX UINT8_MAX + +# undef INT_LEAST16_MIN +# undef INT_LEAST16_MAX +# undef UINT_LEAST16_MAX +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST16_MAX UINT16_MAX + +# undef INT_LEAST32_MIN +# undef INT_LEAST32_MAX +# undef UINT_LEAST32_MAX +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST32_MAX INT32_MAX +# define UINT_LEAST32_MAX UINT32_MAX + +# undef INT_LEAST64_MIN +# undef INT_LEAST64_MAX +# ifdef GL_INT64_T +# define INT_LEAST64_MIN INT64_MIN +# define INT_LEAST64_MAX INT64_MAX +# endif + +# undef UINT_LEAST64_MAX +# ifdef GL_UINT64_T +# define UINT_LEAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.3. Limits of fastest minimum-width integer types */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types + are taken from the same list of types. */ + +# undef INT_FAST8_MIN +# undef INT_FAST8_MAX +# undef UINT_FAST8_MAX +# define INT_FAST8_MIN SCHAR_MIN +# define INT_FAST8_MAX SCHAR_MAX +# define UINT_FAST8_MAX UCHAR_MAX + +# undef INT_FAST16_MIN +# undef INT_FAST16_MAX +# undef UINT_FAST16_MAX +# define INT_FAST16_MIN INT_FAST32_MIN +# define INT_FAST16_MAX INT_FAST32_MAX +# define UINT_FAST16_MAX UINT_FAST32_MAX + +# undef INT_FAST32_MIN +# undef INT_FAST32_MAX +# undef UINT_FAST32_MAX +# ifdef __sun +# define INT_FAST32_MIN INT_MIN +# define INT_FAST32_MAX INT_MAX +# define UINT_FAST32_MAX UINT_MAX +# else +# define INT_FAST32_MIN LONG_MIN +# define INT_FAST32_MAX LONG_MAX +# define UINT_FAST32_MAX ULONG_MAX +# endif + +# undef INT_FAST64_MIN +# undef INT_FAST64_MAX +# ifdef GL_INT64_T +# define INT_FAST64_MIN INT64_MIN +# define INT_FAST64_MAX INT64_MAX +# endif + +# undef UINT_FAST64_MAX +# ifdef GL_UINT64_T +# define UINT_FAST64_MAX UINT64_MAX +# endif + +/* 7.18.2.4. Limits of integer types capable of holding object pointers */ + +# undef INTPTR_MIN +# undef INTPTR_MAX +# undef UINTPTR_MAX +# ifdef _WIN64 +# define INTPTR_MIN LLONG_MIN +# define INTPTR_MAX LLONG_MAX +# define UINTPTR_MAX ULLONG_MAX +# else +# define INTPTR_MIN LONG_MIN +# define INTPTR_MAX LONG_MAX +# define UINTPTR_MAX ULONG_MAX +# endif + +/* 7.18.2.5. Limits of greatest-width integer types */ + +# ifndef INTMAX_MAX +# undef INTMAX_MIN +# ifdef INT64_MAX +# define INTMAX_MIN INT64_MIN +# define INTMAX_MAX INT64_MAX +# else +# define INTMAX_MIN INT32_MIN +# define INTMAX_MAX INT32_MAX +# endif +# endif + +# ifndef UINTMAX_MAX +# ifdef UINT64_MAX +# define UINTMAX_MAX UINT64_MAX +# else +# define UINTMAX_MAX UINT32_MAX +# endif +# endif + +/* 7.18.3. Limits of other integer types */ + +/* ptrdiff_t limits */ +# undef PTRDIFF_MIN +# undef PTRDIFF_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (64, 0l) +# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) +# else +# define PTRDIFF_MIN _STDINT_SIGNED_MIN (32, 0) +# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) +# endif +# else +# define PTRDIFF_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# define PTRDIFF_MAX \ + _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) +# endif + +/* sig_atomic_t limits */ +# undef SIG_ATOMIC_MIN +# undef SIG_ATOMIC_MAX +# if @HAVE_SIGNED_SIG_ATOMIC_T@ +# define SIG_ATOMIC_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# else +# define SIG_ATOMIC_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_SIG_ATOMIC_T@, 0@SIG_ATOMIC_T_SUFFIX@) +# endif +# define SIG_ATOMIC_MAX \ + _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ + 0@SIG_ATOMIC_T_SUFFIX@) + + +/* size_t limit */ +# undef SIZE_MAX +# if @APPLE_UNIVERSAL_BUILD@ +# ifdef _LP64 +# define SIZE_MAX _STDINT_MAX (0, 64, 0ul) +# else +# define SIZE_MAX _STDINT_MAX (0, 32, 0ul) +# endif +# else +# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) +# endif + +/* wchar_t limits */ +/* Get WCHAR_MIN, WCHAR_MAX. + This include is not on the top, above, because on OSF/1 4.0 we have a + sequence of nested includes + -> -> -> , and the latter includes + and assumes its types are already defined. */ +# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX) +# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# include +# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H +# endif +# undef WCHAR_MIN +# undef WCHAR_MAX +# if @HAVE_SIGNED_WCHAR_T@ +# define WCHAR_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# else +# define WCHAR_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) +# endif +# define WCHAR_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) + +/* wint_t limits */ +/* If gnulib's or overrides wint_t, @WINT_T_SUFFIX@ is not + accurate, therefore use the definitions from above. */ +# if !@GNULIBHEADERS_OVERRIDE_WINT_T@ +# undef WINT_MIN +# undef WINT_MAX +# if @HAVE_SIGNED_WINT_T@ +# define WINT_MIN \ + _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# else +# define WINT_MIN \ + _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif +# define WINT_MAX \ + _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) +# endif + +/* 7.18.4. Macros for integer constants */ + +/* 7.18.4.1. Macros for minimum-width integer constants */ +/* According to ISO C 99 Technical Corrigendum 1 */ + +/* Here we assume a standard architecture where the hardware integer + types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ + +# undef INT8_C +# undef UINT8_C +# define INT8_C(x) x +# define UINT8_C(x) x + +# undef INT16_C +# undef UINT16_C +# define INT16_C(x) x +# define UINT16_C(x) x + +# undef INT32_C +# undef UINT32_C +# define INT32_C(x) x +# define UINT32_C(x) x ## U + +# undef INT64_C +# undef UINT64_C +# if LONG_MAX >> 31 >> 31 == 1 +# define INT64_C(x) x##L +# elif defined _MSC_VER +# define INT64_C(x) x##i64 +# else +# define INT64_C(x) x##LL +# endif +# if ULONG_MAX >> 31 >> 31 >> 1 == 1 +# define UINT64_C(x) x##UL +# elif defined _MSC_VER +# define UINT64_C(x) x##ui64 +# else +# define UINT64_C(x) x##ULL +# endif + +/* 7.18.4.2. Macros for greatest-width integer constants */ + +# ifndef INTMAX_C +# if LONG_MAX >> 30 == 1 +# define INTMAX_C(x) x##LL +# elif defined GL_INT64_T +# define INTMAX_C(x) INT64_C(x) +# else +# define INTMAX_C(x) x##L +# endif +# endif + +# ifndef UINTMAX_C +# if ULONG_MAX >> 31 == 1 +# define UINTMAX_C(x) x##ULL +# elif defined GL_UINT64_T +# define UINTMAX_C(x) UINT64_C(x) +# else +# define UINTMAX_C(x) x##UL +# endif +# endif + +#endif /* !@HAVE_C99_STDINT_H@ */ + +/* Macros specified by ISO/IEC TS 18661-1:2014. */ + +#if (!defined UINTMAX_WIDTH \ + && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__)) +# ifdef INT8_MAX +# define INT8_WIDTH _GL_INTEGER_WIDTH (INT8_MIN, INT8_MAX) +# endif +# ifdef UINT8_MAX +# define UINT8_WIDTH _GL_INTEGER_WIDTH (0, UINT8_MAX) +# endif +# ifdef INT16_MAX +# define INT16_WIDTH _GL_INTEGER_WIDTH (INT16_MIN, INT16_MAX) +# endif +# ifdef UINT16_MAX +# define UINT16_WIDTH _GL_INTEGER_WIDTH (0, UINT16_MAX) +# endif +# ifdef INT32_MAX +# define INT32_WIDTH _GL_INTEGER_WIDTH (INT32_MIN, INT32_MAX) +# endif +# ifdef UINT32_MAX +# define UINT32_WIDTH _GL_INTEGER_WIDTH (0, UINT32_MAX) +# endif +# ifdef INT64_MAX +# define INT64_WIDTH _GL_INTEGER_WIDTH (INT64_MIN, INT64_MAX) +# endif +# ifdef UINT64_MAX +# define UINT64_WIDTH _GL_INTEGER_WIDTH (0, UINT64_MAX) +# endif +# define INT_LEAST8_WIDTH _GL_INTEGER_WIDTH (INT_LEAST8_MIN, INT_LEAST8_MAX) +# define UINT_LEAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST8_MAX) +# define INT_LEAST16_WIDTH _GL_INTEGER_WIDTH (INT_LEAST16_MIN, INT_LEAST16_MAX) +# define UINT_LEAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST16_MAX) +# define INT_LEAST32_WIDTH _GL_INTEGER_WIDTH (INT_LEAST32_MIN, INT_LEAST32_MAX) +# define UINT_LEAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST32_MAX) +# define INT_LEAST64_WIDTH _GL_INTEGER_WIDTH (INT_LEAST64_MIN, INT_LEAST64_MAX) +# define UINT_LEAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_LEAST64_MAX) +# define INT_FAST8_WIDTH _GL_INTEGER_WIDTH (INT_FAST8_MIN, INT_FAST8_MAX) +# define UINT_FAST8_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST8_MAX) +# define INT_FAST16_WIDTH _GL_INTEGER_WIDTH (INT_FAST16_MIN, INT_FAST16_MAX) +# define UINT_FAST16_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST16_MAX) +# define INT_FAST32_WIDTH _GL_INTEGER_WIDTH (INT_FAST32_MIN, INT_FAST32_MAX) +# define UINT_FAST32_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST32_MAX) +# define INT_FAST64_WIDTH _GL_INTEGER_WIDTH (INT_FAST64_MIN, INT_FAST64_MAX) +# define UINT_FAST64_WIDTH _GL_INTEGER_WIDTH (0, UINT_FAST64_MAX) +# define INTPTR_WIDTH _GL_INTEGER_WIDTH (INTPTR_MIN, INTPTR_MAX) +# define UINTPTR_WIDTH _GL_INTEGER_WIDTH (0, UINTPTR_MAX) +# define INTMAX_WIDTH _GL_INTEGER_WIDTH (INTMAX_MIN, INTMAX_MAX) +# define UINTMAX_WIDTH _GL_INTEGER_WIDTH (0, UINTMAX_MAX) +# define PTRDIFF_WIDTH _GL_INTEGER_WIDTH (PTRDIFF_MIN, PTRDIFF_MAX) +# define SIZE_WIDTH _GL_INTEGER_WIDTH (0, SIZE_MAX) +# define WCHAR_WIDTH _GL_INTEGER_WIDTH (WCHAR_MIN, WCHAR_MAX) +# ifdef WINT_MAX +# define WINT_WIDTH _GL_INTEGER_WIDTH (WINT_MIN, WINT_MAX) +# endif +# ifdef SIG_ATOMIC_MAX +# define SIG_ATOMIC_WIDTH _GL_INTEGER_WIDTH (SIG_ATOMIC_MIN, SIG_ATOMIC_MAX) +# endif +#endif /* !WINT_WIDTH && (_GNU_SOURCE || __STDC_WANT_IEC_60559_BFP_EXT__) */ + +#endif /* _@GUARD_PREFIX@_STDINT_H */ +#endif /* !(defined __ANDROID__ && ...) */ +#endif /* !defined _@GUARD_PREFIX@_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/cross/lib/stdio-impl.h b/cross/lib/stdio-impl.h new file mode 100644 index 00000000000..46608bed198 --- /dev/null +++ b/cross/lib/stdio-impl.h @@ -0,0 +1,218 @@ +/* Implementation details of FILE streams. + Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Many stdio implementations have the same logic and therefore can share + the same implementation of stdio extension API, except that some fields + have different naming conventions, or their access requires some casts. */ + +/* Glibc 2.28 made _IO_UNBUFFERED and _IO_IN_BACKUP private. For now, work + around this problem by defining them ourselves. FIXME: Do not rely on glibc + internals. */ +#if defined _IO_EOF_SEEN +# if !defined _IO_UNBUFFERED +# define _IO_UNBUFFERED 0x2 +# endif +# if !defined _IO_IN_BACKUP +# define _IO_IN_BACKUP 0x100 +# endif +#endif + +/* BSD stdio derived implementations. */ + +#if defined __NetBSD__ /* NetBSD */ +/* Get __NetBSD_Version__. */ +# include +#endif + +#include /* For detecting Plan9. */ + +#if defined __sferror || defined __DragonFly__ || defined __ANDROID__ + /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */ + +# if defined __DragonFly__ /* DragonFly */ + /* See . */ +# define fp_ ((struct { struct __FILE_public pub; \ + struct { unsigned char *_base; int _size; } _bf; \ + void *cookie; \ + void *_close; \ + void *_read; \ + void *_seek; \ + void *_write; \ + struct { unsigned char *_base; int _size; } _ub; \ + int _ur; \ + unsigned char _ubuf[3]; \ + unsigned char _nbuf[1]; \ + struct { unsigned char *_base; int _size; } _lb; \ + int _blksize; \ + fpos_t _offset; \ + /* More fields, not relevant here. */ \ + } *) fp) + /* See . */ +# define _p pub._p +# define _flags pub._flags +# define _r pub._r +# define _w pub._w +# elif defined __ANDROID__ /* Android */ +# ifdef __LP64__ +# define _gl_flags_file_t int +# else +# define _gl_flags_file_t short +# endif +# ifdef __LP64__ +# define _gl_file_offset_t int64_t +# else + /* see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */ +# define _gl_file_offset_t __kernel_off_t +# endif + /* Up to this commit from 2015-10-12 + + the innards of FILE were public, and fp_ub could be defined like for OpenBSD, + see + and . + After this commit, the innards of FILE are hidden. */ +# define fp_ ((struct { unsigned char *_p; \ + int _r; \ + int _w; \ + _gl_flags_file_t _flags; \ + _gl_flags_file_t _file; \ + struct { unsigned char *_base; size_t _size; } _bf; \ + int _lbfsize; \ + void *_cookie; \ + void *_close; \ + void *_read; \ + void *_seek; \ + void *_write; \ + struct { unsigned char *_base; size_t _size; } _ext; \ + unsigned char *_up; \ + int _ur; \ + unsigned char _ubuf[3]; \ + unsigned char _nbuf[1]; \ + struct { unsigned char *_base; size_t _size; } _lb; \ + int _blksize; \ + _gl_file_offset_t _offset; \ + /* More fields, not relevant here. */ \ + } *) fp) +# else +# define fp_ fp +# endif + +# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix /* NetBSD >= 1.5ZA, OpenBSD, Minix 3 */ + /* See + and + and */ + struct __sfileext + { + struct __sbuf _ub; /* ungetc buffer */ + /* More fields, not relevant here. */ + }; +# define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub +# elif defined __ANDROID__ /* Android */ + struct __sfileext + { + struct { unsigned char *_base; size_t _size; } _ub; /* ungetc buffer */ + /* More fields, not relevant here. */ + }; +# define fp_ub ((struct __sfileext *) fp_->_ext._base)->_ub +# else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, Mac OS X, Cygwin */ +# define fp_ub fp_->_ub +# endif + +# define HASUB(fp) (fp_ub._base != NULL) + +# if defined __ANDROID__ /* Android */ + /* Needed after this commit from 2016-01-25 + */ +# ifndef __SEOF +# define __SLBF 1 +# define __SNBF 2 +# define __SRD 4 +# define __SWR 8 +# define __SRW 0x10 +# define __SEOF 0x20 +# define __SERR 0x40 +# endif +# ifndef __SOFF +# define __SOFF 0x1000 +# endif +# endif + +#endif + + +/* SystemV derived implementations. */ + +#ifdef __TANDEM /* NonStop Kernel */ +# ifndef _IOERR +/* These values were determined by the program 'stdioext-flags' at + . */ +# define _IOERR 0x40 +# define _IOREAD 0x80 +# define _IOWRT 0x4 +# define _IORW 0x100 +# endif +#endif + +#if defined _IOERR + +# if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */ +# define fp_ ((struct { unsigned char *_ptr; \ + unsigned char *_base; \ + unsigned char *_end; \ + long _cnt; \ + int _file; \ + unsigned int _flag; \ + } *) fp) +# elif defined __VMS /* OpenVMS */ +# define fp_ ((struct _iobuf *) fp) +# else +# define fp_ fp +# endif + +# if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__) /* OpenServer 5, OpenServer 6, UnixWare 7 */ +# define _cnt __cnt +# define _ptr __ptr +# define _base __base +# define _flag __flag +# endif + +#elif defined _WIN32 && ! defined __CYGWIN__ /* newer Windows with MSVC */ + +/* does not define the innards of FILE any more. */ +# define WINDOWS_OPAQUE_FILE + +struct _gl_real_FILE +{ + /* Note: Compared to older Windows and to mingw, it has the fields + _base and _cnt swapped. */ + unsigned char *_ptr; + unsigned char *_base; + int _cnt; + int _flag; + int _file; + int _charbuf; + int _bufsiz; +}; +# define fp_ ((struct _gl_real_FILE *) fp) + +/* These values were determined by a program similar to the one at + . */ +# define _IOREAD 0x1 +# define _IOWRT 0x2 +# define _IORW 0x4 +# define _IOEOF 0x8 +# define _IOERR 0x10 + +#endif diff --git a/cross/lib/stdio.in.h b/cross/lib/stdio.in.h new file mode 100644 index 00000000000..8b5ef4bd2dd --- /dev/null +++ b/cross/lib/stdio.in.h @@ -0,0 +1,1719 @@ +/* A GNU-like . + + Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_FILE || defined __need___FILE || defined _GL_ALREADY_INCLUDING_STDIO_H +/* Special invocation convention: + - Inside glibc header files. + - On OSF/1 5.1 we have a sequence of nested includes + -> -> -> -> + -> -> -> . + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDIO_H + +#define _GL_ALREADY_INCLUDING_STDIO_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#undef _GL_ALREADY_INCLUDING_STDIO_H + +#ifndef _@GUARD_PREFIX@_STDIO_H +#define _@GUARD_PREFIX@_STDIO_H + +/* Get va_list. Needed on many systems, including glibc 2.8. */ +#include + +#include + +/* Get off_t and ssize_t. Needed on many systems, including glibc 2.8 + and eglibc 2.11.2. + May also define off_t to a 64-bit type on native Windows. */ +#include + +/* Solaris 10 and NetBSD 7.0 declare renameat in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && (defined __sun || defined __NetBSD__) \ + && ! defined __GLIBC__ +# include +#endif + +/* Android 4.3 declares renameat in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __ANDROID__ \ + && ! defined __GLIBC__ +# include +#endif + +/* MSVC declares 'perror' in , not in . We must include + it before we #define perror rpl_perror. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_PERROR@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include +#endif + +/* MSVC declares 'remove' in , not in . We must include + it before we #define remove rpl_remove. */ +/* MSVC declares 'rename' in , not in . We must include + it before we #define rename rpl_rename. */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_REMOVE@ || @GNULIB_RENAME@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__) \ + && ! defined __GLIBC__ +# include +#endif + + +/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. */ +#ifndef _GL_ATTRIBUTE_DEALLOC +# if __GNUC__ >= 11 +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) +# else +# define _GL_ATTRIBUTE_DEALLOC(f, i) +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The __-protected variants of the attributes 'format' and 'printf' are + accepted by gcc versions 2.6.4 (effectively 2.7) and later. + We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because + gnulib and libintl do '#define printf __printf__' when they override + the 'printf' function. */ +#ifndef _GL_ATTRIBUTE_FORMAT +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) || defined __clang__ +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +# else +# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */ +# endif +#endif + +/* An __attribute__ __format__ specifier for a function that takes a format + string and arguments, where the format string directives are the ones + standardized by ISO C99 and POSIX. + _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD */ +/* __gnu_printf__ is supported in GCC >= 4.4. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __gnu_printf__ +#else +# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __printf__ +#endif + +/* An __attribute__ __format__ specifier for a function that takes a format + string and arguments, where the format string directives are the ones of the + system printf(), rather than the ones standardized by ISO C99 and POSIX. + _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM */ +/* On mingw, Gnulib sets __USE_MINGW_ANSI_STDIO in order to get closer to + the standards. The macro GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU indicates + whether this change is effective. On older mingw, it is not. */ +#if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU +# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD +#else +# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM __printf__ +#endif + +/* _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, formatstring_parameter, first_argument)) + +/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD, + except that it indicates to GCC that the supported format string directives + are the ones of the system printf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM, formatstring_parameter, first_argument)) + +/* _GL_ATTRIBUTE_FORMAT_SCANF + indicates to GCC that the function takes a format string and arguments, + where the format string directives are the ones standardized by ISO C99 + and POSIX. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__gnu_scanf__, formatstring_parameter, first_argument)) +#else +# define _GL_ATTRIBUTE_FORMAT_SCANF(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) +#endif + +/* _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_SCANF, + except that it indicates to GCC that the supported format string directives + are the ones of the system scanf(), rather than the ones standardized by + ISO C99 and POSIX. */ +#define _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM(formatstring_parameter, first_argument) \ + _GL_ATTRIBUTE_FORMAT ((__scanf__, formatstring_parameter, first_argument)) + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Macros for stringification. */ +#define _GL_STDIO_STRINGIZE(token) #token +#define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) + +/* When also using extern inline, suppress the use of static inline in + standard headers of problematic Apple configurations, as Libc at + least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., + . + Perhaps Apple will fix this some day. */ +#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ + && defined __GNUC__ && defined __STDC__) +# undef putc_unlocked +#endif + +#if @GNULIB_DPRINTF@ +# if @REPLACE_DPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dprintf rpl_dprintf +# endif +_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *restrict format, ...)); +# else +# if !@HAVE_DPRINTF@ +_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *restrict format, ...)); +# endif +_GL_CXXALIASWARN (dprintf); +#elif defined GNULIB_POSIXCHECK +# undef dprintf +# if HAVE_RAW_DECL_DPRINTF +_GL_WARN_ON_USE (dprintf, "dprintf is unportable - " + "use gnulib module dprintf for portability"); +# endif +#endif + +#if @GNULIB_FCLOSE@ +/* Close STREAM and its underlying file descriptor. */ +# if @REPLACE_FCLOSE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fclose rpl_fclose +# endif +_GL_FUNCDECL_RPL (fclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fclose, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fclose, int, (FILE *stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fclose); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fclose +/* Assume fclose is always declared. */ +_GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - " + "use gnulib module fclose for portable POSIX compliance"); +#endif + +#if @GNULIB_MDA_FCLOSEALL@ +/* On native Windows, map 'fcloseall' to '_fcloseall', so that -loldnames is + not required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::fcloseall on all platforms that have + it. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fcloseall +# define fcloseall _fcloseall +# endif +_GL_CXXALIAS_MDA (fcloseall, int, (void)); +# else +# if @HAVE_DECL_FCLOSEALL@ +# if defined __FreeBSD__ || defined __DragonFly__ +_GL_CXXALIAS_SYS (fcloseall, void, (void)); +# else +_GL_CXXALIAS_SYS (fcloseall, int, (void)); +# endif +# endif +# endif +# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCLOSEALL@ +_GL_CXXALIASWARN (fcloseall); +# endif +#endif + +#if @GNULIB_FDOPEN@ +# if @REPLACE_FDOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen rpl_fdopen +# endif +_GL_FUNCDECL_RPL (fdopen, FILE *, + (int fd, const char *mode) + _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +_GL_CXXALIAS_RPL (fdopen, FILE *, (int fd, const char *mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen _fdopen +# endif +_GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char *mode)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (fdopen, FILE *, + (int fd, const char *mode) + _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode)); +# endif +_GL_CXXALIASWARN (fdopen); +#else +# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined fdopen +/* For -Wmismatched-dealloc: Associate fdopen with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (fdopen, FILE *, + (int fd, const char *mode) + _GL_ARG_NONNULL ((2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef fdopen +/* Assume fdopen is always declared. */ +_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fdopen for portability"); +# elif @GNULIB_MDA_FDOPEN@ +/* On native Windows, map 'fdopen' to '_fdopen', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::fdopen always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fdopen +# define fdopen _fdopen +# endif +_GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char *mode)); +# else +_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode)); +# endif +_GL_CXXALIASWARN (fdopen); +# endif +#endif + +#if @GNULIB_FFLUSH@ +/* Flush all pending data on STREAM according to POSIX rules. Both + output and seekable input streams are supported. + Note! LOSS OF DATA can occur if fflush is applied on an input stream + that is _not_seekable_ or on an update stream that is _not_seekable_ + and in which the most recent operation was input. Seekability can + be tested with lseek(fileno(fp),0,SEEK_CUR). */ +# if @REPLACE_FFLUSH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fflush rpl_fflush +# endif +_GL_FUNCDECL_RPL (fflush, int, (FILE *gl_stream)); +_GL_CXXALIAS_RPL (fflush, int, (FILE *gl_stream)); +# else +_GL_CXXALIAS_SYS (fflush, int, (FILE *gl_stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fflush); +# endif +#elif defined GNULIB_POSIXCHECK +# undef fflush +/* Assume fflush is always declared. */ +_GL_WARN_ON_USE (fflush, "fflush is not always POSIX compliant - " + "use gnulib module fflush for portable POSIX compliance"); +#endif + +#if @GNULIB_FGETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgetc +# define fgetc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (fgetc, int, (FILE *stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fgetc); +# endif +#endif + +#if @GNULIB_FGETS@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fgets +# define fgets rpl_fgets +# endif +_GL_FUNCDECL_RPL (fgets, char *, + (char *restrict s, int n, FILE *restrict stream) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (fgets, char *, + (char *restrict s, int n, FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (fgets, char *, + (char *restrict s, int n, FILE *restrict stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fgets); +# endif +#endif + +#if @GNULIB_MDA_FILENO@ +/* On native Windows, map 'fileno' to '_fileno', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::fileno always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fileno +# define fileno _fileno +# endif +_GL_CXXALIAS_MDA (fileno, int, (FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (fileno, int, (FILE *restrict stream)); +# endif +_GL_CXXALIASWARN (fileno); +#endif + +#if @GNULIB_FOPEN@ +# if (@GNULIB_FOPEN@ && @REPLACE_FOPEN@) \ + || (@GNULIB_FOPEN_GNU@ && @REPLACE_FOPEN_FOR_FOPEN_GNU@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fopen +# define fopen rpl_fopen +# endif +_GL_FUNCDECL_RPL (fopen, FILE *, + (const char *restrict filename, const char *restrict mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +_GL_CXXALIAS_RPL (fopen, FILE *, + (const char *restrict filename, const char *restrict mode)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate fopen with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (fopen, FILE *, + (const char *restrict filename, const char *restrict mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +_GL_CXXALIAS_SYS (fopen, FILE *, + (const char *restrict filename, const char *restrict mode)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fopen); +# endif +#else +# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined fopen +/* For -Wmismatched-dealloc: Associate fopen with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (fopen, FILE *, + (const char *restrict filename, const char *restrict mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef fopen +/* Assume fopen is always declared. */ +_GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX compliant - " + "use gnulib module fopen for portability"); +# endif +#endif + +#if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@ +# if (@GNULIB_FPRINTF_POSIX@ && @REPLACE_FPRINTF@) \ + || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fprintf rpl_fprintf +# endif +# define GNULIB_overrides_fprintf 1 +# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (fprintf, int, + (FILE *restrict fp, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (fprintf, int, + (FILE *restrict fp, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (fprintf, int, + (FILE *restrict fp, const char *restrict format, ...)); +# else +_GL_CXXALIAS_SYS (fprintf, int, + (FILE *restrict fp, const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fprintf); +# endif +#endif +#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_fprintf +# undef fprintf +# endif +/* Assume fprintf is always declared. */ +_GL_WARN_ON_USE (fprintf, "fprintf is not always POSIX compliant - " + "use gnulib module fprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_FPURGE@ +/* Discard all pending buffered I/O data on STREAM. + STREAM must not be wide-character oriented. + When discarding pending output, the file position is set back to where it + was before the write calls. When discarding pending input, the file + position is advanced to match the end of the previously read input. + Return 0 if successful. Upon error, return -1 and set errno. */ +# if @REPLACE_FPURGE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define fpurge rpl_fpurge +# endif +_GL_FUNCDECL_RPL (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fpurge, int, (FILE *gl_stream)); +# else +# if !@HAVE_DECL_FPURGE@ +_GL_FUNCDECL_SYS (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fpurge, int, (FILE *gl_stream)); +# endif +_GL_CXXALIASWARN (fpurge); +#elif defined GNULIB_POSIXCHECK +# undef fpurge +# if HAVE_RAW_DECL_FPURGE +_GL_WARN_ON_USE (fpurge, "fpurge is not always present - " + "use gnulib module fpurge for portability"); +# endif +#endif + +#if @GNULIB_FPUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputc +# define fputc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (fputc, int, (int c, FILE *stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fputc); +# endif +#endif + +#if @GNULIB_FPUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fputs +# define fputs rpl_fputs +# endif +_GL_FUNCDECL_RPL (fputs, int, + (const char *restrict string, FILE *restrict stream) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fputs, int, + (const char *restrict string, FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (fputs, int, + (const char *restrict string, FILE *restrict stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fputs); +# endif +#endif + +#if @GNULIB_FREAD@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fread +# define fread rpl_fread +# endif +_GL_FUNCDECL_RPL (fread, size_t, + (void *restrict ptr, size_t s, size_t n, + FILE *restrict stream) + _GL_ARG_NONNULL ((4))); +_GL_CXXALIAS_RPL (fread, size_t, + (void *restrict ptr, size_t s, size_t n, + FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (fread, size_t, + (void *restrict ptr, size_t s, size_t n, + FILE *restrict stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fread); +# endif +#endif + +#if @GNULIB_FREOPEN@ +# if @REPLACE_FREOPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef freopen +# define freopen rpl_freopen +# endif +_GL_FUNCDECL_RPL (freopen, FILE *, + (const char *restrict filename, const char *restrict mode, + FILE *restrict stream) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (freopen, FILE *, + (const char *restrict filename, const char *restrict mode, + FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (freopen, FILE *, + (const char *restrict filename, const char *restrict mode, + FILE *restrict stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (freopen); +# endif +#elif defined GNULIB_POSIXCHECK +# undef freopen +/* Assume freopen is always declared. */ +_GL_WARN_ON_USE (freopen, + "freopen on native Windows platforms is not POSIX compliant - " + "use gnulib module freopen for portability"); +#endif + +#if @GNULIB_FSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fscanf +# define fscanf rpl_fscanf +# endif +_GL_FUNCDECL_RPL (fscanf, int, + (FILE *restrict stream, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (fscanf, int, + (FILE *restrict stream, const char *restrict format, ...)); +# else +_GL_CXXALIAS_SYS (fscanf, int, + (FILE *restrict stream, const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fscanf); +# endif +#endif + + +/* Set up the following warnings, based on which modules are in use. + GNU Coding Standards discourage the use of fseek, since it imposes + an arbitrary limitation on some 32-bit hosts. Remember that the + fseek module depends on the fseeko module, so we only have three + cases to consider: + + 1. The developer is not using either module. Issue a warning under + GNULIB_POSIXCHECK for both functions, to remind them that both + functions have bugs on some systems. _GL_NO_LARGE_FILES has no + impact on this warning. + + 2. The developer is using both modules. They may be unaware of the + arbitrary limitations of fseek, so issue a warning under + GNULIB_POSIXCHECK. On the other hand, they may be using both + modules intentionally, so the developer can define + _GL_NO_LARGE_FILES in the compilation units where the use of fseek + is safe, to silence the warning. + + 3. The developer is using the fseeko module, but not fseek. Gnulib + guarantees that fseek will still work around platform bugs in that + case, but we presume that the developer is aware of the pitfalls of + fseek and was trying to avoid it, so issue a warning even when + GNULIB_POSIXCHECK is undefined. Again, _GL_NO_LARGE_FILES can be + defined to silence the warning in particular compilation units. + In C++ compilations with GNULIB_NAMESPACE, in order to avoid that + fseek gets defined as a macro, it is recommended that the developer + uses the fseek module, even if he is not calling the fseek function. + + Most gnulib clients that perform stream operations should fall into + category 3. */ + +#if @GNULIB_FSEEK@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 2, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseek +# define fseek rpl_fseek +# endif +_GL_FUNCDECL_RPL (fseek, int, (FILE *fp, long offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseek, int, (FILE *fp, long offset, int whence)); +# else +_GL_CXXALIAS_SYS (fseek, int, (FILE *fp, long offset, int whence)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fseek); +# endif +#endif + +#if @GNULIB_FSEEKO@ +# if !@GNULIB_FSEEK@ && !defined _GL_NO_LARGE_FILES +# define _GL_FSEEK_WARN /* Category 3, above. */ +# undef fseek +# endif +# if @REPLACE_FSEEKO@ +/* Provide an fseeko function that is aware of a preceding fflush(), and which + detects pipes. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fseeko +# define fseeko rpl_fseeko +# endif +_GL_FUNCDECL_RPL (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (fseeko, int, (FILE *fp, off_t offset, int whence)); +# else +# if ! @HAVE_DECL_FSEEKO@ +_GL_FUNCDECL_SYS (fseeko, int, (FILE *fp, off_t offset, int whence) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (fseeko, int, (FILE *fp, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (fseeko); +#elif defined GNULIB_POSIXCHECK +# define _GL_FSEEK_WARN /* Category 1, above. */ +# undef fseek +# undef fseeko +# if HAVE_RAW_DECL_FSEEKO +_GL_WARN_ON_USE (fseeko, "fseeko is unportable - " + "use gnulib module fseeko for portability"); +# endif +#endif + +#ifdef _GL_FSEEK_WARN +# undef _GL_FSEEK_WARN +/* Here, either fseek is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_fseek (declared above). */ +_GL_WARN_ON_USE (fseek, "fseek cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use fseeko function for handling of large files"); +#endif + + +/* ftell, ftello. See the comments on fseek/fseeko. */ + +#if @GNULIB_FTELL@ +# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 2, above. */ +# undef ftell +# endif +# if @REPLACE_FTELL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftell +# define ftell rpl_ftell +# endif +_GL_FUNCDECL_RPL (ftell, long, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftell, long, (FILE *fp)); +# else +_GL_CXXALIAS_SYS (ftell, long, (FILE *fp)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (ftell); +# endif +#endif + +#if @GNULIB_FTELLO@ +# if !@GNULIB_FTELL@ && !defined _GL_NO_LARGE_FILES +# define _GL_FTELL_WARN /* Category 3, above. */ +# undef ftell +# endif +# if @REPLACE_FTELLO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftello +# define ftello rpl_ftello +# endif +_GL_FUNCDECL_RPL (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ftello, off_t, (FILE *fp)); +# else +# if ! @HAVE_DECL_FTELLO@ +_GL_FUNCDECL_SYS (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (ftello, off_t, (FILE *fp)); +# endif +_GL_CXXALIASWARN (ftello); +#elif defined GNULIB_POSIXCHECK +# define _GL_FTELL_WARN /* Category 1, above. */ +# undef ftell +# undef ftello +# if HAVE_RAW_DECL_FTELLO +_GL_WARN_ON_USE (ftello, "ftello is unportable - " + "use gnulib module ftello for portability"); +# endif +#endif + +#ifdef _GL_FTELL_WARN +# undef _GL_FTELL_WARN +/* Here, either ftell is undefined (but C89 guarantees that it is + declared), or it is defined as rpl_ftell (declared above). */ +_GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB " + "on 32-bit platforms - " + "use ftello function for handling of large files"); +#endif + + +#if @GNULIB_FWRITE@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fwrite +# define fwrite rpl_fwrite +# endif +_GL_FUNCDECL_RPL (fwrite, size_t, + (const void *restrict ptr, size_t s, size_t n, + FILE *restrict stream) + _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (fwrite, size_t, + (const void *restrict ptr, size_t s, size_t n, + FILE *restrict stream)); +# else +_GL_CXXALIAS_SYS (fwrite, size_t, + (const void *restrict ptr, size_t s, size_t n, + FILE *restrict stream)); + +/* Work around bug 11959 when fortifying glibc 2.4 through 2.15 + , + which sometimes causes an unwanted diagnostic for fwrite calls. + This affects only function declaration attributes under certain + versions of gcc and clang, and is not needed for C++. */ +# if (0 < __USE_FORTIFY_LEVEL \ + && __GLIBC__ == 2 && 4 <= __GLIBC_MINOR__ && __GLIBC_MINOR__ <= 15 \ + && 3 < __GNUC__ + (4 <= __GNUC_MINOR__) \ + && !defined __cplusplus) +# undef fwrite +# undef fwrite_unlocked +extern size_t __REDIRECT (rpl_fwrite, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite); +extern size_t __REDIRECT (rpl_fwrite_unlocked, + (const void *__restrict, size_t, size_t, + FILE *__restrict), + fwrite_unlocked); +# define fwrite rpl_fwrite +# define fwrite_unlocked rpl_fwrite_unlocked +# endif +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fwrite); +# endif +#endif + +#if @GNULIB_GETC@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getc +# define getc rpl_fgetc +# endif +_GL_FUNCDECL_RPL (fgetc, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (getc, rpl_fgetc, int, (FILE *stream)); +# else +_GL_CXXALIAS_SYS (getc, int, (FILE *stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (getc); +# endif +#endif + +#if @GNULIB_GETCHAR@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getchar +# define getchar rpl_getchar +# endif +_GL_FUNCDECL_RPL (getchar, int, (void)); +_GL_CXXALIAS_RPL (getchar, int, (void)); +# else +_GL_CXXALIAS_SYS (getchar, int, (void)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (getchar); +# endif +#endif + +#if @GNULIB_GETDELIM@ +/* Read input, up to (and including) the next occurrence of DELIMITER, from + STREAM, store it in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETDELIM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdelim +# define getdelim rpl_getdelim +# endif +_GL_FUNCDECL_RPL (getdelim, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + int delimiter, + FILE *restrict stream) + _GL_ARG_NONNULL ((1, 2, 4))); +_GL_CXXALIAS_RPL (getdelim, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + int delimiter, + FILE *restrict stream)); +# else +# if !@HAVE_DECL_GETDELIM@ +_GL_FUNCDECL_SYS (getdelim, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + int delimiter, + FILE *restrict stream) + _GL_ARG_NONNULL ((1, 2, 4))); +# endif +_GL_CXXALIAS_SYS (getdelim, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + int delimiter, + FILE *restrict stream)); +# endif +_GL_CXXALIASWARN (getdelim); +#elif defined GNULIB_POSIXCHECK +# undef getdelim +# if HAVE_RAW_DECL_GETDELIM +_GL_WARN_ON_USE (getdelim, "getdelim is unportable - " + "use gnulib module getdelim for portability"); +# endif +#endif + +#if @GNULIB_GETLINE@ +/* Read a line, up to (and including) the next newline, from STREAM, store it + in *LINEPTR (and NUL-terminate it). + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +# if @REPLACE_GETLINE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getline +# define getline rpl_getline +# endif +_GL_FUNCDECL_RPL (getline, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + FILE *restrict stream) + _GL_ARG_NONNULL ((1, 2, 3))); +_GL_CXXALIAS_RPL (getline, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + FILE *restrict stream)); +# else +# if !@HAVE_DECL_GETLINE@ +_GL_FUNCDECL_SYS (getline, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + FILE *restrict stream) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getline, ssize_t, + (char **restrict lineptr, size_t *restrict linesize, + FILE *restrict stream)); +# endif +# if @HAVE_DECL_GETLINE@ +_GL_CXXALIASWARN (getline); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getline +# if HAVE_RAW_DECL_GETLINE +_GL_WARN_ON_USE (getline, "getline is unportable - " + "use gnulib module getline for portability"); +# endif +#endif + +/* It is very rare that the developer ever has full control of stdin, + so any use of gets warrants an unconditional warning; besides, C11 + removed it. */ +#undef gets +#if HAVE_RAW_DECL_GETS && !defined __cplusplus +_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); +#endif + +#if @GNULIB_MDA_GETW@ +/* On native Windows, map 'getw' to '_getw', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::getw always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getw +# define getw _getw +# endif +_GL_CXXALIAS_MDA (getw, int, (FILE *restrict stream)); +# else +# if @HAVE_DECL_GETW@ +_GL_CXXALIAS_SYS (getw, int, (FILE *restrict stream)); +# endif +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (getw); +# endif +#endif + +#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ +struct obstack; +/* Grow an obstack with formatted output. Return the number of + bytes added to OBS. No trailing nul byte is added, and the + object should be closed with obstack_finish before use. Upon + memory allocation error, call obstack_alloc_failed_handler. Upon + other error, return -1. */ +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_printf rpl_obstack_printf +# endif +_GL_FUNCDECL_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_printf, int, + (struct obstack *obs, const char *format, ...)); +# endif +_GL_CXXALIASWARN (obstack_printf); +# if @REPLACE_OBSTACK_PRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define obstack_vprintf rpl_obstack_vprintf +# endif +_GL_FUNCDECL_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# else +# if !@HAVE_DECL_OBSTACK_PRINTF@ +_GL_FUNCDECL_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (obstack_vprintf, int, + (struct obstack *obs, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (obstack_vprintf); +#endif + +#if @GNULIB_PCLOSE@ +# if !@HAVE_PCLOSE@ +_GL_FUNCDECL_SYS (pclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pclose, int, (FILE *stream)); +_GL_CXXALIASWARN (pclose); +#elif defined GNULIB_POSIXCHECK +# undef pclose +# if HAVE_RAW_DECL_PCLOSE +_GL_WARN_ON_USE (pclose, "pclose is unportable - " + "use gnulib module pclose for more portability"); +# endif +#endif + +#if @GNULIB_PERROR@ +/* Print a message to standard error, describing the value of ERRNO, + (if STRING is not NULL and not empty) prefixed with STRING and ": ", + and terminated with a newline. */ +# if @REPLACE_PERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define perror rpl_perror +# endif +_GL_FUNCDECL_RPL (perror, void, (const char *string)); +_GL_CXXALIAS_RPL (perror, void, (const char *string)); +# else +_GL_CXXALIAS_SYS (perror, void, (const char *string)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (perror); +# endif +#elif defined GNULIB_POSIXCHECK +# undef perror +/* Assume perror is always declared. */ +_GL_WARN_ON_USE (perror, "perror is not always POSIX compliant - " + "use gnulib module perror for portability"); +#endif + +#if @GNULIB_POPEN@ +# if @REPLACE_POPEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef popen +# define popen rpl_popen +# endif +_GL_FUNCDECL_RPL (popen, FILE *, + (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1)); +_GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode)); +# else +# if !@HAVE_POPEN@ || __GNUC__ >= 11 +_GL_FUNCDECL_SYS (popen, FILE *, + (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1)); +# endif +_GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); +# endif +_GL_CXXALIASWARN (popen); +#else +# if @GNULIB_PCLOSE@ && __GNUC__ >= 11 && !defined popen +/* For -Wmismatched-dealloc: Associate popen with pclose or rpl_pclose. */ +_GL_FUNCDECL_SYS (popen, FILE *, + (const char *cmd, const char *mode) + _GL_ARG_NONNULL ((1, 2)) _GL_ATTRIBUTE_DEALLOC (pclose, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef popen +# if HAVE_RAW_DECL_POPEN +_GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " + "use gnulib module popen or pipe for more portability"); +# endif +# endif +#endif + +#if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ +# if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ + || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if defined __GNUC__ || defined __clang__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +/* Don't break __attribute__((format(printf,M,N))). */ +# define printf __printf__ +# endif +# if @GNULIB_PRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *restrict format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL_1 (__printf__, int, + (const char *restrict format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define printf rpl_printf +# endif +_GL_FUNCDECL_RPL (printf, int, + (const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (printf, int, (const char *restrict format, ...)); +# endif +# define GNULIB_overrides_printf 1 +# else +_GL_CXXALIAS_SYS (printf, int, (const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (printf); +# endif +#endif +#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_printf +# undef printf +# endif +/* Assume printf is always declared. */ +_GL_WARN_ON_USE (printf, "printf is not always POSIX compliant - " + "use gnulib module printf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_PUTC@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putc +# define putc rpl_fputc +# endif +_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL_1 (putc, rpl_fputc, int, (int c, FILE *stream)); +# else +_GL_CXXALIAS_SYS (putc, int, (int c, FILE *stream)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (putc); +# endif +#endif + +#if @GNULIB_PUTCHAR@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putchar +# define putchar rpl_putchar +# endif +_GL_FUNCDECL_RPL (putchar, int, (int c)); +_GL_CXXALIAS_RPL (putchar, int, (int c)); +# else +_GL_CXXALIAS_SYS (putchar, int, (int c)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (putchar); +# endif +#endif + +#if @GNULIB_PUTS@ +# if @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef puts +# define puts rpl_puts +# endif +_GL_FUNCDECL_RPL (puts, int, (const char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (puts, int, (const char *string)); +# else +_GL_CXXALIAS_SYS (puts, int, (const char *string)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (puts); +# endif +#endif + +#if @GNULIB_MDA_PUTW@ +/* On native Windows, map 'putw' to '_putw', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::putw always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putw +# define putw _putw +# endif +_GL_CXXALIAS_MDA (putw, int, (int w, FILE *restrict stream)); +# else +# if @HAVE_DECL_PUTW@ +_GL_CXXALIAS_SYS (putw, int, (int w, FILE *restrict stream)); +# endif +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (putw); +# endif +#endif + +#if @GNULIB_REMOVE@ +# if @REPLACE_REMOVE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef remove +# define remove rpl_remove +# endif +_GL_FUNCDECL_RPL (remove, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (remove, int, (const char *name)); +# else +_GL_CXXALIAS_SYS (remove, int, (const char *name)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (remove); +# endif +#elif defined GNULIB_POSIXCHECK +# undef remove +/* Assume remove is always declared. */ +_GL_WARN_ON_USE (remove, "remove cannot handle directories on some platforms - " + "use gnulib module remove for more portability"); +#endif + +#if @GNULIB_RENAME@ +# if @REPLACE_RENAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef rename +# define rename rpl_rename +# endif +_GL_FUNCDECL_RPL (rename, int, + (const char *old_filename, const char *new_filename) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (rename, int, + (const char *old_filename, const char *new_filename)); +# else +_GL_CXXALIAS_SYS (rename, int, + (const char *old_filename, const char *new_filename)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (rename); +# endif +#elif defined GNULIB_POSIXCHECK +# undef rename +/* Assume rename is always declared. */ +_GL_WARN_ON_USE (rename, "rename is buggy on some platforms - " + "use gnulib module rename for more portability"); +#endif + +#if @GNULIB_RENAMEAT@ +# if @REPLACE_RENAMEAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef renameat +# define renameat rpl_renameat +# endif +_GL_FUNCDECL_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# else +# if !@HAVE_RENAMEAT@ +_GL_FUNCDECL_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (renameat, int, + (int fd1, char const *file1, int fd2, char const *file2)); +# endif +_GL_CXXALIASWARN (renameat); +#elif defined GNULIB_POSIXCHECK +# undef renameat +# if HAVE_RAW_DECL_RENAMEAT +_GL_WARN_ON_USE (renameat, "renameat is not portable - " + "use gnulib module renameat for portability"); +# endif +#endif + +#if @GNULIB_SCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if defined __GNUC__ || defined __clang__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +/* Don't break __attribute__((format(scanf,M,N))). */ +# define scanf __scanf__ +# endif +_GL_FUNCDECL_RPL_1 (__scanf__, int, + (const char *restrict format, ...) + __asm__ (@ASM_SYMBOL_PREFIX@ + _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_scanf)) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL_1 (scanf, __scanf__, int, (const char *restrict format, ...)); +# else +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef scanf +# define scanf rpl_scanf +# endif +_GL_FUNCDECL_RPL (scanf, int, (const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 2) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (scanf, int, (const char *restrict format, ...)); +# endif +# else +_GL_CXXALIAS_SYS (scanf, int, (const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (scanf); +# endif +#endif + +#if @GNULIB_SNPRINTF@ +# if @REPLACE_SNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define snprintf rpl_snprintf +# endif +# define GNULIB_overrides_snprintf 1 +_GL_FUNCDECL_RPL (snprintf, int, + (char *restrict str, size_t size, + const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (snprintf, int, + (char *restrict str, size_t size, + const char *restrict format, ...)); +# else +# if !@HAVE_DECL_SNPRINTF@ +_GL_FUNCDECL_SYS (snprintf, int, + (char *restrict str, size_t size, + const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (snprintf, int, + (char *restrict str, size_t size, + const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (snprintf); +# endif +#elif defined GNULIB_POSIXCHECK +# undef snprintf +# if HAVE_RAW_DECL_SNPRINTF +_GL_WARN_ON_USE (snprintf, "snprintf is unportable - " + "use gnulib module snprintf for portability"); +# endif +#endif + +/* Some people would argue that all sprintf uses should be warned about + (for example, OpenBSD issues a link warning for it), + since it can cause security holes due to buffer overruns. + However, we believe that sprintf can be used safely, and is more + efficient than snprintf in those safe cases; and as proof of our + belief, we use sprintf in several gnulib modules. So this header + intentionally avoids adding a warning to sprintf except when + GNULIB_POSIXCHECK is defined. */ + +#if @GNULIB_SPRINTF_POSIX@ +# if @REPLACE_SPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define sprintf rpl_sprintf +# endif +# define GNULIB_overrides_sprintf 1 +_GL_FUNCDECL_RPL (sprintf, int, + (char *restrict str, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (sprintf, int, + (char *restrict str, const char *restrict format, ...)); +# else +_GL_CXXALIAS_SYS (sprintf, int, + (char *restrict str, const char *restrict format, ...)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (sprintf); +# endif +#elif defined GNULIB_POSIXCHECK +# undef sprintf +/* Assume sprintf is always declared. */ +_GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - " + "use gnulib module sprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_MDA_TEMPNAM@ +/* On native Windows, map 'tempnam' to '_tempnam', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::tempnam always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tempnam +# define tempnam _tempnam +# endif +_GL_CXXALIAS_MDA (tempnam, char *, (const char *dir, const char *prefix)); +# else +_GL_CXXALIAS_SYS (tempnam, char *, (const char *dir, const char *prefix)); +# endif +_GL_CXXALIASWARN (tempnam); +#endif + +#if @GNULIB_TMPFILE@ +# if @REPLACE_TMPFILE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define tmpfile rpl_tmpfile +# endif +_GL_FUNCDECL_RPL (tmpfile, FILE *, (void) + _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +_GL_CXXALIAS_RPL (tmpfile, FILE *, (void)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate tmpfile with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (tmpfile, FILE *, (void) + _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +_GL_CXXALIAS_SYS (tmpfile, FILE *, (void)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (tmpfile); +# endif +#else +# if @GNULIB_FCLOSE@ && __GNUC__ >= 11 && !defined tmpfile +/* For -Wmismatched-dealloc: Associate tmpfile with fclose or rpl_fclose. */ +_GL_FUNCDECL_SYS (tmpfile, FILE *, (void) + _GL_ATTRIBUTE_DEALLOC (fclose, 1)); +# endif +# if defined GNULIB_POSIXCHECK +# undef tmpfile +# if HAVE_RAW_DECL_TMPFILE +_GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " + "use gnulib module tmpfile for portability"); +# endif +# endif +#endif + +#if @GNULIB_VASPRINTF@ +/* Write formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, store the address of the string in + *RESULT and return the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, return -1. */ +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define asprintf rpl_asprintf +# endif +# define GNULIB_overrides_asprintf +_GL_FUNCDECL_RPL (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (asprintf, int, + (char **result, const char *format, ...)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (asprintf, int, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (asprintf, int, + (char **result, const char *format, ...)); +# endif +_GL_CXXALIASWARN (asprintf); +# if @REPLACE_VASPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vasprintf rpl_vasprintf +# endif +# define GNULIB_overrides_vasprintf 1 +_GL_FUNCDECL_RPL (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vasprintf, int, + (char **result, const char *format, va_list args)); +# else +# if !@HAVE_VASPRINTF@ +_GL_FUNCDECL_SYS (vasprintf, int, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (vasprintf, int, + (char **result, const char *format, va_list args)); +# endif +_GL_CXXALIASWARN (vasprintf); +#endif + +#if @GNULIB_VDPRINTF@ +# if @REPLACE_VDPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vdprintf rpl_vdprintf +# endif +_GL_FUNCDECL_RPL (vdprintf, int, + (int fd, const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (vdprintf, int, + (int fd, const char *restrict format, va_list args)); +# else +# if !@HAVE_VDPRINTF@ +_GL_FUNCDECL_SYS (vdprintf, int, + (int fd, const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((2))); +# endif +/* Need to cast, because on Solaris, the third parameter will likely be + __va_list args. */ +_GL_CXXALIAS_SYS_CAST (vdprintf, int, + (int fd, const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vdprintf); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vdprintf +# if HAVE_RAW_DECL_VDPRINTF +_GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - " + "use gnulib module vdprintf for portability"); +# endif +#endif + +#if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ +# if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ + || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vfprintf rpl_vfprintf +# endif +# define GNULIB_overrides_vfprintf 1 +# if @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vfprintf, int, + (FILE *restrict fp, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# else +_GL_FUNCDECL_RPL (vfprintf, int, + (FILE *restrict fp, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_RPL (vfprintf, int, + (FILE *restrict fp, + const char *restrict format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vfprintf, int, + (FILE *restrict fp, + const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vfprintf); +# endif +#endif +#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vfprintf +# undef vfprintf +# endif +/* Assume vfprintf is always declared. */ +_GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - " + "use gnulib module vfprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VFSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vfscanf +# define vfscanf rpl_vfscanf +# endif +_GL_FUNCDECL_RPL (vfscanf, int, + (FILE *restrict stream, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vfscanf, int, + (FILE *restrict stream, + const char *restrict format, va_list args)); +# else +_GL_CXXALIAS_SYS (vfscanf, int, + (FILE *restrict stream, + const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vfscanf); +# endif +#endif + +#if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ +# if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ + || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && (@GNULIB_STDIO_H_NONBLOCKING@ || @GNULIB_STDIO_H_SIGPIPE@)) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vprintf rpl_vprintf +# endif +# define GNULIB_overrides_vprintf 1 +# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@ +_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0) + _GL_ARG_NONNULL ((1))); +# else +_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_RPL (vprintf, int, (const char *restrict format, va_list args)); +# else +/* Need to cast, because on Solaris, the second parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vprintf, int, + (const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vprintf); +# endif +#endif +#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK +# if !GNULIB_overrides_vprintf +# undef vprintf +# endif +/* Assume vprintf is always declared. */ +_GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " + "use gnulib module vprintf-posix for portable " + "POSIX compliance"); +#endif + +#if @GNULIB_VSCANF@ +# if @REPLACE_STDIO_READ_FUNCS@ && @GNULIB_STDIO_H_NONBLOCKING@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef vscanf +# define vscanf rpl_vscanf +# endif +_GL_FUNCDECL_RPL (vscanf, int, (const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_SCANF_SYSTEM (1, 0) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (vscanf, int, (const char *restrict format, va_list args)); +# else +_GL_CXXALIAS_SYS (vscanf, int, (const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vscanf); +# endif +#endif + +#if @GNULIB_VSNPRINTF@ +# if @REPLACE_VSNPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsnprintf rpl_vsnprintf +# endif +# define GNULIB_overrides_vsnprintf 1 +_GL_FUNCDECL_RPL (vsnprintf, int, + (char *restrict str, size_t size, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_RPL (vsnprintf, int, + (char *restrict str, size_t size, + const char *restrict format, va_list args)); +# else +# if !@HAVE_DECL_VSNPRINTF@ +_GL_FUNCDECL_SYS (vsnprintf, int, + (char *restrict str, size_t size, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) + _GL_ARG_NONNULL ((3))); +# endif +_GL_CXXALIAS_SYS (vsnprintf, int, + (char *restrict str, size_t size, + const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vsnprintf); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vsnprintf +# if HAVE_RAW_DECL_VSNPRINTF +_GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " + "use gnulib module vsnprintf for portability"); +# endif +#endif + +#if @GNULIB_VSPRINTF_POSIX@ +# if @REPLACE_VSPRINTF@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define vsprintf rpl_vsprintf +# endif +# define GNULIB_overrides_vsprintf 1 +_GL_FUNCDECL_RPL (vsprintf, int, + (char *restrict str, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (vsprintf, int, + (char *restrict str, + const char *restrict format, va_list args)); +# else +/* Need to cast, because on Solaris, the third parameter is + __va_list args + and GCC's fixincludes did not change this to __gnuc_va_list. */ +_GL_CXXALIAS_SYS_CAST (vsprintf, int, + (char *restrict str, + const char *restrict format, va_list args)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (vsprintf); +# endif +#elif defined GNULIB_POSIXCHECK +# undef vsprintf +/* Assume vsprintf is always declared. */ +_GL_WARN_ON_USE (vsprintf, "vsprintf is not always POSIX compliant - " + "use gnulib module vsprintf-posix for portable " + "POSIX compliance"); +#endif + +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif /* _@GUARD_PREFIX@_STDIO_H */ +#endif diff --git a/cross/lib/stdlib.in.h b/cross/lib/stdlib.in.h new file mode 100644 index 00000000000..b79e5f70965 --- /dev/null +++ b/cross/lib/stdlib.in.h @@ -0,0 +1,1563 @@ +/* A GNU-like . + + Copyright (C) 1995, 2001-2004, 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_stdlib_h || defined __need_malloc_and_calloc +/* Special invocation conventions inside some gnulib header files, + and inside some glibc header files, respectively. */ + +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STDLIB_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ + +#ifndef _@GUARD_PREFIX@_STDLIB_H +#define _@GUARD_PREFIX@_STDLIB_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* MirBSD 10 defines WEXITSTATUS in , not in . */ +#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS +# include +#endif + +/* Solaris declares getloadavg() in . */ +#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@ +/* OpenIndiana has a bug: must be included before + . */ +# include +# include +#endif + +/* Native Windows platforms declare _mktemp() in . */ +#if defined _WIN32 && !defined __CYGWIN__ +# include +#endif + +#if @GNULIB_RANDOM_R@ + +/* OSF/1 5.1 declares 'struct random_data' in , which is included + from if _REENTRANT is defined. Include it whenever we need + 'struct random_data'. */ +# if @HAVE_RANDOM_H@ +# include +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ || @REPLACE_RANDOM_R@ || !@HAVE_RANDOM_R@ +# include +# endif + +# if !@HAVE_STRUCT_RANDOM_DATA@ +/* Define 'struct random_data'. + But allow multiple gnulib generated replacements to coexist. */ +# if !GNULIB_defined_struct_random_data +struct random_data +{ + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + int rand_type; /* Type of random number generator. */ + int rand_deg; /* Degree of random number generator. */ + int rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ +}; +# define GNULIB_defined_struct_random_data 1 +# endif +# endif +#endif + +#if (@GNULIB_MKSTEMP@ || @GNULIB_MKSTEMPS@ || @GNULIB_MKOSTEMP@ || @GNULIB_MKOSTEMPS@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !(defined _WIN32 && ! defined __CYGWIN__) +/* On Mac OS X 10.3, only declares mkstemp. */ +/* On Mac OS X 10.5, only declares mkstemps. */ +/* On Mac OS X 10.13, only declares mkostemp and mkostemps. */ +/* On Cygwin 1.7.1, only declares getsubopt. */ +/* But avoid namespace pollution on glibc systems and native Windows. */ +# include +#endif + +/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. */ +#ifndef _GL_ATTRIBUTE_DEALLOC +# if __GNUC__ >= 11 +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) +# else +# define _GL_ATTRIBUTE_DEALLOC(f, i) +# endif +#endif + +/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that + can be freed via 'free'; it can be used only after declaring 'free'. */ +/* Applies to: functions. Cannot be used on inline functions. */ +#ifndef _GL_ATTRIBUTE_DEALLOC_FREE +# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) +#endif + +/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly + allocated memory. */ +/* Applies to: functions. */ +#ifndef _GL_ATTRIBUTE_MALLOC +# if __GNUC__ >= 3 || defined __clang__ +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define _GL_ATTRIBUTE_MALLOC +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#ifndef _GL_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif +#endif + +/* The definition of _Noreturn is copied here. */ + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere + with proper operation of xargs. */ +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#elif EXIT_FAILURE != 1 +# undef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + + +#if @GNULIB__EXIT@ +/* Terminate the current process with the given return code, without running + the 'atexit' handlers. */ +# if !@HAVE__EXIT@ +_GL_FUNCDECL_SYS (_Exit, _Noreturn void, (int status)); +# endif +_GL_CXXALIAS_SYS (_Exit, void, (int status)); +_GL_CXXALIASWARN (_Exit); +#elif defined GNULIB_POSIXCHECK +# undef _Exit +# if HAVE_RAW_DECL__EXIT +_GL_WARN_ON_USE (_Exit, "_Exit is unportable - " + "use gnulib module _Exit for portability"); +# endif +#endif + + +#if @GNULIB_FREE_POSIX@ +# if @REPLACE_FREE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef free +# define free rpl_free +# endif +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_FUNCDECL_RPL (free, void, (void *ptr) throw ()); +# else +_GL_FUNCDECL_RPL (free, void, (void *ptr)); +# endif +_GL_CXXALIAS_RPL (free, void, (void *ptr)); +# else +_GL_CXXALIAS_SYS (free, void, (void *ptr)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (free); +# endif +#elif defined GNULIB_POSIXCHECK +# undef free +/* Assume free is always declared. */ +_GL_WARN_ON_USE (free, "free is not future POSIX compliant everywhere - " + "use gnulib module free for portability"); +#endif + + +/* Allocate memory with indefinite extent and specified alignment. */ +#if @GNULIB_ALIGNED_ALLOC@ +# if @REPLACE_ALIGNED_ALLOC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef aligned_alloc +# define aligned_alloc rpl_aligned_alloc +# endif +_GL_FUNCDECL_RPL (aligned_alloc, void *, + (size_t alignment, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (aligned_alloc, void *, (size_t alignment, size_t size)); +# else +# if @HAVE_ALIGNED_ALLOC@ +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (aligned_alloc, void *, + (size_t alignment, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (aligned_alloc, void *, (size_t alignment, size_t size)); +# endif +# endif +# if (__GLIBC__ >= 2) && @HAVE_ALIGNED_ALLOC@ +_GL_CXXALIASWARN (aligned_alloc); +# endif +#else +# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined aligned_alloc +/* For -Wmismatched-dealloc: Associate aligned_alloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (aligned_alloc, void *, + (size_t alignment, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK +# undef aligned_alloc +# if HAVE_RAW_DECL_ALIGNED_ALLOC +_GL_WARN_ON_USE (aligned_alloc, "aligned_alloc is not portable - " + "use gnulib module aligned_alloc for portability"); +# endif +# endif +#endif + +#if @GNULIB_ATOLL@ +/* Parse a signed decimal integer. + Returns the value of the integer. Errors are not detected. */ +# if !@HAVE_ATOLL@ +_GL_FUNCDECL_SYS (atoll, long long, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (atoll, long long, (const char *string)); +_GL_CXXALIASWARN (atoll); +#elif defined GNULIB_POSIXCHECK +# undef atoll +# if HAVE_RAW_DECL_ATOLL +_GL_WARN_ON_USE (atoll, "atoll is unportable - " + "use gnulib module atoll for portability"); +# endif +#endif + +#if @GNULIB_CALLOC_POSIX@ +# if (@GNULIB_CALLOC_POSIX@ && @REPLACE_CALLOC_FOR_CALLOC_POSIX@) \ + || (@GNULIB_CALLOC_GNU@ && @REPLACE_CALLOC_FOR_CALLOC_GNU@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef calloc +# define calloc rpl_calloc +# endif +_GL_FUNCDECL_RPL (calloc, void *, + (size_t nmemb, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate calloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (calloc, void *, + (size_t nmemb, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (calloc); +# endif +#else +# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined calloc +/* For -Wmismatched-dealloc: Associate calloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (calloc, void *, + (size_t nmemb, size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK +# undef calloc +/* Assume calloc is always declared. */ +_GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - " + "use gnulib module calloc-posix for portability"); +# endif +#endif + +#if @GNULIB_CANONICALIZE_FILE_NAME@ +# if @REPLACE_CANONICALIZE_FILE_NAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define canonicalize_file_name rpl_canonicalize_file_name +# endif +_GL_FUNCDECL_RPL (canonicalize_file_name, char *, + (const char *name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name)); +# else +# if !@HAVE_CANONICALIZE_FILE_NAME@ || __GNUC__ >= 11 +_GL_FUNCDECL_SYS (canonicalize_file_name, char *, + (const char *name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); +# endif +# ifndef GNULIB_defined_canonicalize_file_name +# define GNULIB_defined_canonicalize_file_name \ + (!@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@) +# endif +_GL_CXXALIASWARN (canonicalize_file_name); +#else +# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined canonicalize_file_name +/* For -Wmismatched-dealloc: Associate canonicalize_file_name with free or + rpl_free. */ +_GL_FUNCDECL_SYS (canonicalize_file_name, char *, + (const char *name) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK +# undef canonicalize_file_name +# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME +_GL_WARN_ON_USE (canonicalize_file_name, + "canonicalize_file_name is unportable - " + "use gnulib module canonicalize-lgpl for portability"); +# endif +# endif +#endif + +#if @GNULIB_MDA_ECVT@ +/* On native Windows, map 'ecvt' to '_ecvt', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::ecvt on all platforms that have + it. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ecvt +# define ecvt _ecvt +# endif +_GL_CXXALIAS_MDA (ecvt, char *, + (double number, int ndigits, int *decptp, int *signp)); +# else +# if @HAVE_DECL_ECVT@ +_GL_CXXALIAS_SYS (ecvt, char *, + (double number, int ndigits, int *decptp, int *signp)); +# endif +# endif +# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_ECVT@ +_GL_CXXALIASWARN (ecvt); +# endif +#endif + +#if @GNULIB_MDA_FCVT@ +/* On native Windows, map 'fcvt' to '_fcvt', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::fcvt on all platforms that have + it. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fcvt +# define fcvt _fcvt +# endif +_GL_CXXALIAS_MDA (fcvt, char *, + (double number, int ndigits, int *decptp, int *signp)); +# else +# if @HAVE_DECL_FCVT@ +_GL_CXXALIAS_SYS (fcvt, char *, + (double number, int ndigits, int *decptp, int *signp)); +# endif +# endif +# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCVT@ +_GL_CXXALIASWARN (fcvt); +# endif +#endif + +#if @GNULIB_MDA_GCVT@ +/* On native Windows, map 'gcvt' to '_gcvt', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::gcvt on all platforms that have + it. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gcvt +# define gcvt _gcvt +# endif +_GL_CXXALIAS_MDA (gcvt, char *, (double number, int ndigits, char *buf)); +# else +# if @HAVE_DECL_GCVT@ +_GL_CXXALIAS_SYS (gcvt, char *, (double number, int ndigits, char *buf)); +# endif +# endif +# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_GCVT@ +_GL_CXXALIASWARN (gcvt); +# endif +#endif + +#if @GNULIB_GETLOADAVG@ +/* Store max(NELEM,3) load average numbers in LOADAVG[]. + The three numbers are the load average of the last 1 minute, the last 5 + minutes, and the last 15 minutes, respectively. + LOADAVG is an array of NELEM numbers. */ +# if !@HAVE_DECL_GETLOADAVG@ +_GL_FUNCDECL_SYS (getloadavg, int, (double loadavg[], int nelem) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getloadavg, int, (double loadavg[], int nelem)); +_GL_CXXALIASWARN (getloadavg); +#elif defined GNULIB_POSIXCHECK +# undef getloadavg +# if HAVE_RAW_DECL_GETLOADAVG +_GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - " + "use gnulib module getloadavg for portability"); +# endif +#endif + +#if @GNULIB_GETSUBOPT@ +/* Assuming *OPTIONP is a comma separated list of elements of the form + "token" or "token=value", getsubopt parses the first of these elements. + If the first element refers to a "token" that is member of the given + NULL-terminated array of tokens: + - It replaces the comma with a NUL byte, updates *OPTIONP to point past + the first option and the comma, sets *VALUEP to the value of the + element (or NULL if it doesn't contain an "=" sign), + - It returns the index of the "token" in the given array of tokens. + Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined. + For more details see the POSIX specification. + https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html */ +# if !@HAVE_GETSUBOPT@ +_GL_FUNCDECL_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (getsubopt, int, + (char **optionp, char *const *tokens, char **valuep)); +_GL_CXXALIASWARN (getsubopt); +#elif defined GNULIB_POSIXCHECK +# undef getsubopt +# if HAVE_RAW_DECL_GETSUBOPT +_GL_WARN_ON_USE (getsubopt, "getsubopt is unportable - " + "use gnulib module getsubopt for portability"); +# endif +#endif + +#if @GNULIB_GRANTPT@ +/* Change the ownership and access permission of the slave side of the + pseudo-terminal whose master side is specified by FD. */ +# if !@HAVE_GRANTPT@ +_GL_FUNCDECL_SYS (grantpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (grantpt, int, (int fd)); +_GL_CXXALIASWARN (grantpt); +#elif defined GNULIB_POSIXCHECK +# undef grantpt +# if HAVE_RAW_DECL_GRANTPT +_GL_WARN_ON_USE (grantpt, "grantpt is not portable - " + "use gnulib module grantpt for portability"); +# endif +#endif + +/* If _GL_USE_STDLIB_ALLOC is nonzero, the including module does not + rely on GNU or POSIX semantics for malloc and realloc (for example, + by never specifying a zero size), so it does not need malloc or + realloc to be redefined. */ +#if @GNULIB_MALLOC_POSIX@ +# if (@GNULIB_MALLOC_POSIX@ && @REPLACE_MALLOC_FOR_MALLOC_POSIX@) \ + || (@GNULIB_MALLOC_GNU@ && @REPLACE_MALLOC_FOR_MALLOC_GNU@) +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef malloc +# define malloc rpl_malloc +# endif +_GL_FUNCDECL_RPL (malloc, void *, + (size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (malloc, void *, (size_t size)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate malloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (malloc, void *, + (size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (malloc, void *, (size_t size)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (malloc); +# endif +#else +# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined malloc +/* For -Wmismatched-dealloc: Associate malloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (malloc, void *, + (size_t size) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef malloc +/* Assume malloc is always declared. */ +_GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " + "use gnulib module malloc-posix for portability"); +# endif +#endif + +/* Convert a multibyte character to a wide character. */ +#if @GNULIB_MBTOWC@ +# if @REPLACE_MBTOWC@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mbtowc +# define mbtowc rpl_mbtowc +# endif +_GL_FUNCDECL_RPL (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); +_GL_CXXALIAS_RPL (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); +# else +# if !@HAVE_MBTOWC@ +_GL_FUNCDECL_SYS (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); +# endif +_GL_CXXALIAS_SYS (mbtowc, int, + (wchar_t *restrict pwc, const char *restrict s, size_t n)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (mbtowc); +# endif +#elif defined GNULIB_POSIXCHECK +# undef mbtowc +# if HAVE_RAW_DECL_MBTOWC +_GL_WARN_ON_USE (mbtowc, "mbtowc is not portable - " + "use gnulib module mbtowc for portability"); +# endif +#endif + +#if @GNULIB_MKDTEMP@ +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +# if !@HAVE_MKDTEMP@ +_GL_FUNCDECL_SYS (mkdtemp, char *, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkdtemp, char *, (char * /*template*/)); +_GL_CXXALIASWARN (mkdtemp); +#elif defined GNULIB_POSIXCHECK +# undef mkdtemp +# if HAVE_RAW_DECL_MKDTEMP +_GL_WARN_ON_USE (mkdtemp, "mkdtemp is unportable - " + "use gnulib module mkdtemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMP@ +_GL_FUNCDECL_SYS (mkostemp, int, (char * /*template*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemp, int, (char * /*template*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemp); +#elif defined GNULIB_POSIXCHECK +# undef mkostemp +# if HAVE_RAW_DECL_MKOSTEMP +_GL_WARN_ON_USE (mkostemp, "mkostemp is unportable - " + "use gnulib module mkostemp for portability"); +# endif +#endif + +#if @GNULIB_MKOSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE before a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + The file is then created, with the specified flags, ensuring it didn't exist + before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKOSTEMPS@ +_GL_FUNCDECL_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkostemps, int, + (char * /*template*/, int /*suffixlen*/, int /*flags*/)); +_GL_CXXALIASWARN (mkostemps); +#elif defined GNULIB_POSIXCHECK +# undef mkostemps +# if HAVE_RAW_DECL_MKOSTEMPS +_GL_WARN_ON_USE (mkostemps, "mkostemps is unportable - " + "use gnulib module mkostemps for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMP@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if @REPLACE_MKSTEMP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mkstemp rpl_mkstemp +# endif +_GL_FUNCDECL_RPL (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkstemp, int, (char * /*template*/)); +# else +# if ! @HAVE_MKSTEMP@ +_GL_FUNCDECL_SYS (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemp, int, (char * /*template*/)); +# endif +_GL_CXXALIASWARN (mkstemp); +#elif defined GNULIB_POSIXCHECK +# undef mkstemp +# if HAVE_RAW_DECL_MKSTEMP +_GL_WARN_ON_USE (mkstemp, "mkstemp is unportable - " + "use gnulib module mkstemp for portability"); +# endif +#endif + +#if @GNULIB_MKSTEMPS@ +/* Create a unique temporary file from TEMPLATE. + The last six characters of TEMPLATE prior to a suffix of length + SUFFIXLEN must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + The file is then created, ensuring it didn't exist before. + The file is created read-write (mask at least 0600 & ~umask), but it may be + world-readable and world-writable (mask 0666 & ~umask), depending on the + implementation. + Returns the open file descriptor if successful, otherwise -1 and errno + set. */ +# if !@HAVE_MKSTEMPS@ +_GL_FUNCDECL_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/)); +_GL_CXXALIASWARN (mkstemps); +#elif defined GNULIB_POSIXCHECK +# undef mkstemps +# if HAVE_RAW_DECL_MKSTEMPS +_GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - " + "use gnulib module mkstemps for portability"); +# endif +#endif + +#if @GNULIB_MDA_MKTEMP@ +/* On native Windows, map 'mktemp' to '_mktemp', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::mktemp always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mktemp +# define mktemp _mktemp +# endif +_GL_CXXALIAS_MDA (mktemp, char *, (char * /*template*/)); +# else +_GL_CXXALIAS_SYS (mktemp, char *, (char * /*template*/)); +# endif +_GL_CXXALIASWARN (mktemp); +#endif + +/* Allocate memory with indefinite extent and specified alignment. */ +#if @GNULIB_POSIX_MEMALIGN@ +# if @REPLACE_POSIX_MEMALIGN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef posix_memalign +# define posix_memalign rpl_posix_memalign +# endif +_GL_FUNCDECL_RPL (posix_memalign, int, + (void **memptr, size_t alignment, size_t size) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (posix_memalign, int, + (void **memptr, size_t alignment, size_t size)); +# else +# if @HAVE_POSIX_MEMALIGN@ +_GL_CXXALIAS_SYS (posix_memalign, int, + (void **memptr, size_t alignment, size_t size)); +# endif +# endif +# if @HAVE_POSIX_MEMALIGN@ +_GL_CXXALIASWARN (posix_memalign); +# endif +#elif defined GNULIB_POSIXCHECK +# undef posix_memalign +# if HAVE_RAW_DECL_POSIX_MEMALIGN +_GL_WARN_ON_USE (posix_memalign, "posix_memalign is not portable - " + "use gnulib module posix_memalign for portability"); +# endif +#endif + +#if @GNULIB_POSIX_OPENPT@ +/* Return an FD open to the master side of a pseudo-terminal. Flags should + include O_RDWR, and may also include O_NOCTTY. */ +# if !@HAVE_POSIX_OPENPT@ +_GL_FUNCDECL_SYS (posix_openpt, int, (int flags)); +# endif +_GL_CXXALIAS_SYS (posix_openpt, int, (int flags)); +_GL_CXXALIASWARN (posix_openpt); +#elif defined GNULIB_POSIXCHECK +# undef posix_openpt +# if HAVE_RAW_DECL_POSIX_OPENPT +_GL_WARN_ON_USE (posix_openpt, "posix_openpt is not portable - " + "use gnulib module posix_openpt for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME@ +/* Return the pathname of the pseudo-terminal slave associated with + the master FD is open on, or NULL on errors. */ +# if @REPLACE_PTSNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname +# define ptsname rpl_ptsname +# endif +_GL_FUNCDECL_RPL (ptsname, char *, (int fd)); +_GL_CXXALIAS_RPL (ptsname, char *, (int fd)); +# else +# if !@HAVE_PTSNAME@ +_GL_FUNCDECL_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIAS_SYS (ptsname, char *, (int fd)); +# endif +_GL_CXXALIASWARN (ptsname); +#elif defined GNULIB_POSIXCHECK +# undef ptsname +# if HAVE_RAW_DECL_PTSNAME +_GL_WARN_ON_USE (ptsname, "ptsname is not portable - " + "use gnulib module ptsname for portability"); +# endif +#endif + +#if @GNULIB_PTSNAME_R@ +/* Set the pathname of the pseudo-terminal slave associated with + the master FD is open on and return 0, or set errno and return + non-zero on errors. */ +# if @REPLACE_PTSNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ptsname_r +# define ptsname_r rpl_ptsname_r +# endif +_GL_FUNCDECL_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +_GL_CXXALIAS_RPL (ptsname_r, int, (int fd, char *buf, size_t len)); +# else +# if !@HAVE_PTSNAME_R@ +_GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +_GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len)); +# endif +# ifndef GNULIB_defined_ptsname_r +# define GNULIB_defined_ptsname_r (!@HAVE_PTSNAME_R@ || @REPLACE_PTSNAME_R@) +# endif +_GL_CXXALIASWARN (ptsname_r); +#elif defined GNULIB_POSIXCHECK +# undef ptsname_r +# if HAVE_RAW_DECL_PTSNAME_R +_GL_WARN_ON_USE (ptsname_r, "ptsname_r is not portable - " + "use gnulib module ptsname_r for portability"); +# endif +#endif + +#if @GNULIB_PUTENV@ +# if @REPLACE_PUTENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putenv +# define putenv rpl_putenv +# endif +_GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (putenv, int, (char *string)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putenv +# define putenv _putenv +# endif +_GL_CXXALIAS_MDA (putenv, int, (char *string)); +# else +_GL_CXXALIAS_SYS (putenv, int, (char *string)); +# endif +_GL_CXXALIASWARN (putenv); +#elif @GNULIB_MDA_PUTENV@ +/* On native Windows, map 'putenv' to '_putenv', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::putenv always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef putenv +# define putenv _putenv +# endif +/* Need to cast, because on mingw, the parameter is either + 'const char *string' or 'char *string'. */ +_GL_CXXALIAS_MDA_CAST (putenv, int, (char *string)); +# else +_GL_CXXALIAS_SYS (putenv, int, (char *string)); +# endif +_GL_CXXALIASWARN (putenv); +#endif + +#if @GNULIB_QSORT_R@ +/* Sort an array of NMEMB elements, starting at address BASE, each element + occupying SIZE bytes, in ascending order according to the comparison + function COMPARE. */ +# ifdef __cplusplus +extern "C" { +# endif +# if !GNULIB_defined_qsort_r_fn_types +typedef int (*_gl_qsort_r_compar_fn) (void const *, void const *, void *); +# define GNULIB_defined_qsort_r_fn_types 1 +# endif +# ifdef __cplusplus +} +# endif +# if @REPLACE_QSORT_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef qsort_r +# define qsort_r rpl_qsort_r +# endif +_GL_FUNCDECL_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + _gl_qsort_r_compar_fn compare, + void *arg) _GL_ARG_NONNULL ((1, 4))); +_GL_CXXALIAS_RPL (qsort_r, void, (void *base, size_t nmemb, size_t size, + _gl_qsort_r_compar_fn compare, + void *arg)); +# else +# if !@HAVE_QSORT_R@ +_GL_FUNCDECL_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size, + _gl_qsort_r_compar_fn compare, + void *arg) _GL_ARG_NONNULL ((1, 4))); +# endif +_GL_CXXALIAS_SYS (qsort_r, void, (void *base, size_t nmemb, size_t size, + _gl_qsort_r_compar_fn compare, + void *arg)); +# endif +_GL_CXXALIASWARN (qsort_r); +#elif defined GNULIB_POSIXCHECK +# undef qsort_r +# if HAVE_RAW_DECL_QSORT_R +_GL_WARN_ON_USE (qsort_r, "qsort_r is not portable - " + "use gnulib module qsort_r for portability"); +# endif +#endif + + +#if @GNULIB_RANDOM_R@ +# if !@HAVE_RANDOM_R@ +# ifndef RAND_MAX +# define RAND_MAX 2147483647 +# endif +# endif +#endif + + +#if @GNULIB_RANDOM@ +# if @REPLACE_RANDOM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef random +# define random rpl_random +# endif +_GL_FUNCDECL_RPL (random, long, (void)); +_GL_CXXALIAS_RPL (random, long, (void)); +# else +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (random, long, (void)); +# endif +/* Need to cast, because on Haiku, the return type is + int. */ +_GL_CXXALIAS_SYS_CAST (random, long, (void)); +# endif +_GL_CXXALIASWARN (random); +#elif defined GNULIB_POSIXCHECK +# undef random +# if HAVE_RAW_DECL_RANDOM +_GL_WARN_ON_USE (random, "random is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if @REPLACE_RANDOM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef srandom +# define srandom rpl_srandom +# endif +_GL_FUNCDECL_RPL (srandom, void, (unsigned int seed)); +_GL_CXXALIAS_RPL (srandom, void, (unsigned int seed)); +# else +# if !@HAVE_RANDOM@ +_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed)); +# endif +/* Need to cast, because on FreeBSD, the first parameter is + unsigned long seed. */ +_GL_CXXALIAS_SYS_CAST (srandom, void, (unsigned int seed)); +# endif +_GL_CXXALIASWARN (srandom); +#elif defined GNULIB_POSIXCHECK +# undef srandom +# if HAVE_RAW_DECL_SRANDOM +_GL_WARN_ON_USE (srandom, "srandom is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if @REPLACE_INITSTATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef initstate +# define initstate rpl_initstate +# endif +_GL_FUNCDECL_RPL (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +# else +# if !@HAVE_INITSTATE@ || !@HAVE_DECL_INITSTATE@ +_GL_FUNCDECL_SYS (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size) + _GL_ARG_NONNULL ((2))); +# endif +/* Need to cast, because on FreeBSD, the first parameter is + unsigned long seed. */ +_GL_CXXALIAS_SYS_CAST (initstate, char *, + (unsigned int seed, char *buf, size_t buf_size)); +# endif +_GL_CXXALIASWARN (initstate); +#elif defined GNULIB_POSIXCHECK +# undef initstate +# if HAVE_RAW_DECL_INITSTATE +_GL_WARN_ON_USE (initstate, "initstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + +#if @GNULIB_RANDOM@ +# if @REPLACE_SETSTATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setstate +# define setstate rpl_setstate +# endif +_GL_FUNCDECL_RPL (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (setstate, char *, (char *arg_state)); +# else +# if !@HAVE_SETSTATE@ || !@HAVE_DECL_SETSTATE@ +_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Mac OS X 10.13, HP-UX, Solaris the first parameter + is const char *arg_state. */ +_GL_CXXALIAS_SYS_CAST (setstate, char *, (char *arg_state)); +# endif +_GL_CXXALIASWARN (setstate); +#elif defined GNULIB_POSIXCHECK +# undef setstate +# if HAVE_RAW_DECL_SETSTATE +_GL_WARN_ON_USE (setstate, "setstate is unportable - " + "use gnulib module random for portability"); +# endif +#endif + + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef random_r +# define random_r rpl_random_r +# endif +_GL_FUNCDECL_RPL (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (random_r, int, (struct random_data *buf, int32_t *result)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (random_r, int, (struct random_data *buf, int32_t *result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (random_r, int, (struct random_data *buf, int32_t *result)); +# endif +_GL_CXXALIASWARN (random_r); +#elif defined GNULIB_POSIXCHECK +# undef random_r +# if HAVE_RAW_DECL_RANDOM_R +_GL_WARN_ON_USE (random_r, "random_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef srandom_r +# define srandom_r rpl_srandom_r +# endif +_GL_FUNCDECL_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (srandom_r, int, + (unsigned int seed, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (srandom_r); +#elif defined GNULIB_POSIXCHECK +# undef srandom_r +# if HAVE_RAW_DECL_SRANDOM_R +_GL_WARN_ON_USE (srandom_r, "srandom_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef initstate_r +# define initstate_r rpl_initstate_r +# endif +_GL_FUNCDECL_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state) + _GL_ARG_NONNULL ((2, 4))); +# endif +/* Need to cast, because on Haiku, the third parameter is + unsigned long buf_size. */ +_GL_CXXALIAS_SYS_CAST (initstate_r, int, + (unsigned int seed, char *buf, size_t buf_size, + struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (initstate_r); +#elif defined GNULIB_POSIXCHECK +# undef initstate_r +# if HAVE_RAW_DECL_INITSTATE_R +_GL_WARN_ON_USE (initstate_r, "initstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + +#if @GNULIB_RANDOM_R@ +# if @REPLACE_RANDOM_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setstate_r +# define setstate_r rpl_setstate_r +# endif +_GL_FUNCDECL_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# else +# if !@HAVE_RANDOM_R@ +_GL_FUNCDECL_SYS (setstate_r, int, + (char *arg_state, struct random_data *rand_state) + _GL_ARG_NONNULL ((1, 2))); +# endif +/* Need to cast, because on Haiku, the first parameter is + void *arg_state. */ +_GL_CXXALIAS_SYS_CAST (setstate_r, int, + (char *arg_state, struct random_data *rand_state)); +# endif +_GL_CXXALIASWARN (setstate_r); +#elif defined GNULIB_POSIXCHECK +# undef setstate_r +# if HAVE_RAW_DECL_SETSTATE_R +_GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " + "use gnulib module random_r for portability"); +# endif +#endif + + +#if @GNULIB_REALLOC_POSIX@ +# if (@GNULIB_REALLOC_POSIX@ && @REPLACE_REALLOC_FOR_REALLOC_POSIX@) \ + || (@GNULIB_REALLOC_GNU@ && @REPLACE_REALLOC_FOR_REALLOC_GNU@) +# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \ + || _GL_USE_STDLIB_ALLOC) +# undef realloc +# define realloc rpl_realloc +# endif +_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size) + _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size)); +# else +# if __GNUC__ >= 11 +/* For -Wmismatched-dealloc: Associate realloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size) + _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (realloc); +# endif +#else +# if @GNULIB_FREE_POSIX@ && __GNUC__ >= 11 && !defined realloc +/* For -Wmismatched-dealloc: Associate realloc with free or rpl_free. */ +_GL_FUNCDECL_SYS (realloc, void *, (void *ptr, size_t size) + _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC +# undef realloc +/* Assume realloc is always declared. */ +_GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " + "use gnulib module realloc-posix for portability"); +# endif +#endif + + +#if @GNULIB_REALLOCARRAY@ +# if @REPLACE_REALLOCARRAY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef reallocarray +# define reallocarray rpl_reallocarray +# endif +_GL_FUNCDECL_RPL (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +_GL_CXXALIAS_RPL (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +# else +# if ! @HAVE_REALLOCARRAY@ +_GL_FUNCDECL_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +# endif +_GL_CXXALIAS_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +# endif +_GL_CXXALIASWARN (reallocarray); +#elif defined GNULIB_POSIXCHECK +# undef reallocarray +# if HAVE_RAW_DECL_REALLOCARRAY +_GL_WARN_ON_USE (reallocarray, "reallocarray is not portable - " + "use gnulib module reallocarray for portability"); +# endif +#endif + +#if @GNULIB_REALPATH@ +# if @REPLACE_REALPATH@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define realpath rpl_realpath +# endif +_GL_FUNCDECL_RPL (realpath, char *, + (const char *restrict name, char *restrict resolved) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (realpath, char *, + (const char *restrict name, char *restrict resolved)); +# else +# if !@HAVE_REALPATH@ +_GL_FUNCDECL_SYS (realpath, char *, + (const char *restrict name, char *restrict resolved) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (realpath, char *, + (const char *restrict name, char *restrict resolved)); +# endif +_GL_CXXALIASWARN (realpath); +#elif defined GNULIB_POSIXCHECK +# undef realpath +# if HAVE_RAW_DECL_REALPATH +_GL_WARN_ON_USE (realpath, "realpath is unportable - use gnulib module " + "canonicalize or canonicalize-lgpl for portability"); +# endif +#endif + +#if @GNULIB_RPMATCH@ +/* Test a user response to a question. + Return 1 if it is affirmative, 0 if it is negative, or -1 if not clear. */ +# if !@HAVE_RPMATCH@ +_GL_FUNCDECL_SYS (rpmatch, int, (const char *response) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (rpmatch, int, (const char *response)); +_GL_CXXALIASWARN (rpmatch); +#elif defined GNULIB_POSIXCHECK +# undef rpmatch +# if HAVE_RAW_DECL_RPMATCH +_GL_WARN_ON_USE (rpmatch, "rpmatch is unportable - " + "use gnulib module rpmatch for portability"); +# endif +#endif + +#if @GNULIB_SECURE_GETENV@ +/* Look up NAME in the environment, returning 0 in insecure situations. */ +# if !@HAVE_SECURE_GETENV@ +_GL_FUNCDECL_SYS (secure_getenv, char *, + (char const *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (secure_getenv, char *, (char const *name)); +_GL_CXXALIASWARN (secure_getenv); +#elif defined GNULIB_POSIXCHECK +# undef secure_getenv +# if HAVE_RAW_DECL_SECURE_GETENV +_GL_WARN_ON_USE (secure_getenv, "secure_getenv is unportable - " + "use gnulib module secure_getenv for portability"); +# endif +#endif + +#if @GNULIB_SETENV@ +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +# if @REPLACE_SETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef setenv +# define setenv rpl_setenv +# endif +_GL_FUNCDECL_RPL (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (setenv, int, + (const char *name, const char *value, int replace)); +# else +# if !@HAVE_DECL_SETENV@ +_GL_FUNCDECL_SYS (setenv, int, + (const char *name, const char *value, int replace) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (setenv, int, + (const char *name, const char *value, int replace)); +# endif +# if !(@REPLACE_SETENV@ && !@HAVE_DECL_SETENV@) +_GL_CXXALIASWARN (setenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef setenv +# if HAVE_RAW_DECL_SETENV +_GL_WARN_ON_USE (setenv, "setenv is unportable - " + "use gnulib module setenv for portability"); +# endif +#endif + +#if @GNULIB_STRTOD@ + /* Parse a double from STRING, updating ENDP if appropriate. */ +# if @REPLACE_STRTOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtod rpl_strtod +# endif +# define GNULIB_defined_strtod_function 1 +_GL_FUNCDECL_RPL (strtod, double, + (const char *restrict str, char **restrict endp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtod, double, + (const char *restrict str, char **restrict endp)); +# else +# if !@HAVE_STRTOD@ +_GL_FUNCDECL_SYS (strtod, double, + (const char *restrict str, char **restrict endp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtod, double, + (const char *restrict str, char **restrict endp)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strtod); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtod +# if HAVE_RAW_DECL_STRTOD +_GL_WARN_ON_USE (strtod, "strtod is unportable - " + "use gnulib module strtod for portability"); +# endif +#endif + +#if @GNULIB_STRTOLD@ + /* Parse a 'long double' from STRING, updating ENDP if appropriate. */ +# if @REPLACE_STRTOLD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtold rpl_strtold +# endif +# define GNULIB_defined_strtold_function 1 +_GL_FUNCDECL_RPL (strtold, long double, + (const char *restrict str, char **restrict endp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtold, long double, + (const char *restrict str, char **restrict endp)); +# else +# if !@HAVE_STRTOLD@ +_GL_FUNCDECL_SYS (strtold, long double, + (const char *restrict str, char **restrict endp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtold, long double, + (const char *restrict str, char **restrict endp)); +# endif +_GL_CXXALIASWARN (strtold); +#elif defined GNULIB_POSIXCHECK +# undef strtold +# if HAVE_RAW_DECL_STRTOLD +_GL_WARN_ON_USE (strtold, "strtold is unportable - " + "use gnulib module strtold for portability"); +# endif +#endif + +#if @GNULIB_STRTOL@ +/* Parse a signed integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is LONG_MAX or LONG_MIN, and errno is set + to ERANGE. */ +# if @REPLACE_STRTOL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtol rpl_strtol +# endif +# define GNULIB_defined_strtol_function 1 +_GL_FUNCDECL_RPL (strtol, long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtol, long, + (const char *restrict string, char **restrict endptr, + int base)); +# else +# if !@HAVE_STRTOL@ +_GL_FUNCDECL_SYS (strtol, long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtol, long, + (const char *restrict string, char **restrict endptr, + int base)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strtol); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtol +# if HAVE_RAW_DECL_STRTOL +_GL_WARN_ON_USE (strtol, "strtol is unportable - " + "use gnulib module strtol for portability"); +# endif +#endif + +#if @GNULIB_STRTOLL@ +/* Parse a signed integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set + to ERANGE. */ +# if @REPLACE_STRTOLL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtoll rpl_strtoll +# endif +# define GNULIB_defined_strtoll_function 1 +_GL_FUNCDECL_RPL (strtoll, long long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtoll, long long, + (const char *restrict string, char **restrict endptr, + int base)); +# else +# if !@HAVE_STRTOLL@ +_GL_FUNCDECL_SYS (strtoll, long long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoll, long long, + (const char *restrict string, char **restrict endptr, + int base)); +# endif +_GL_CXXALIASWARN (strtoll); +#elif defined GNULIB_POSIXCHECK +# undef strtoll +# if HAVE_RAW_DECL_STRTOLL +_GL_WARN_ON_USE (strtoll, "strtoll is unportable - " + "use gnulib module strtoll for portability"); +# endif +#endif + +#if @GNULIB_STRTOUL@ +/* Parse an unsigned integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is ULONG_MAX, and errno is set to ERANGE. */ +# if @REPLACE_STRTOUL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtoul rpl_strtoul +# endif +# define GNULIB_defined_strtoul_function 1 +_GL_FUNCDECL_RPL (strtoul, unsigned long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtoul, unsigned long, + (const char *restrict string, char **restrict endptr, + int base)); +# else +# if !@HAVE_STRTOUL@ +_GL_FUNCDECL_SYS (strtoul, unsigned long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoul, unsigned long, + (const char *restrict string, char **restrict endptr, + int base)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strtoul); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtoul +# if HAVE_RAW_DECL_STRTOUL +_GL_WARN_ON_USE (strtoul, "strtoul is unportable - " + "use gnulib module strtoul for portability"); +# endif +#endif + +#if @GNULIB_STRTOULL@ +/* Parse an unsigned integer whose textual representation starts at STRING. + The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, + it may be decimal or octal (with prefix "0") or hexadecimal (with prefix + "0x"). + If ENDPTR is not NULL, the address of the first byte after the integer is + stored in *ENDPTR. + Upon overflow, the return value is ULLONG_MAX, and errno is set to + ERANGE. */ +# if @REPLACE_STRTOULL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strtoull rpl_strtoull +# endif +# define GNULIB_defined_strtoull_function 1 +_GL_FUNCDECL_RPL (strtoull, unsigned long long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strtoull, unsigned long long, + (const char *restrict string, char **restrict endptr, + int base)); +# else +# if !@HAVE_STRTOULL@ +_GL_FUNCDECL_SYS (strtoull, unsigned long long, + (const char *restrict string, char **restrict endptr, + int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strtoull, unsigned long long, + (const char *restrict string, char **restrict endptr, + int base)); +# endif +_GL_CXXALIASWARN (strtoull); +#elif defined GNULIB_POSIXCHECK +# undef strtoull +# if HAVE_RAW_DECL_STRTOULL +_GL_WARN_ON_USE (strtoull, "strtoull is unportable - " + "use gnulib module strtoull for portability"); +# endif +#endif + +#if @GNULIB_UNLOCKPT@ +/* Unlock the slave side of the pseudo-terminal whose master side is specified + by FD, so that it can be opened. */ +# if !@HAVE_UNLOCKPT@ +_GL_FUNCDECL_SYS (unlockpt, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (unlockpt, int, (int fd)); +_GL_CXXALIASWARN (unlockpt); +#elif defined GNULIB_POSIXCHECK +# undef unlockpt +# if HAVE_RAW_DECL_UNLOCKPT +_GL_WARN_ON_USE (unlockpt, "unlockpt is not portable - " + "use gnulib module unlockpt for portability"); +# endif +#endif + +#if @GNULIB_UNSETENV@ +/* Remove the variable NAME from the environment. */ +# if @REPLACE_UNSETENV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unsetenv +# define unsetenv rpl_unsetenv +# endif +_GL_FUNCDECL_RPL (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unsetenv, int, (const char *name)); +# else +# if !@HAVE_DECL_UNSETENV@ +_GL_FUNCDECL_SYS (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (unsetenv, int, (const char *name)); +# endif +# if !(@REPLACE_UNSETENV@ && !@HAVE_DECL_UNSETENV@) +_GL_CXXALIASWARN (unsetenv); +# endif +#elif defined GNULIB_POSIXCHECK +# undef unsetenv +# if HAVE_RAW_DECL_UNSETENV +_GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - " + "use gnulib module unsetenv for portability"); +# endif +#endif + +/* Convert a wide character to a multibyte character. */ +#if @GNULIB_WCTOMB@ +# if @REPLACE_WCTOMB@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef wctomb +# define wctomb rpl_wctomb +# endif +_GL_FUNCDECL_RPL (wctomb, int, (char *s, wchar_t wc)); +_GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc)); +# else +_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (wctomb); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif /* _@GUARD_PREFIX@_STDLIB_H */ +#endif diff --git a/cross/lib/stpcpy.c b/cross/lib/stpcpy.c new file mode 100644 index 00000000000..73c1eb786ff --- /dev/null +++ b/cross/lib/stpcpy.c @@ -0,0 +1,49 @@ +/* stpcpy.c -- copy a string and return pointer to end of new string + Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2023 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#include + +#undef __stpcpy +#ifdef _LIBC +# undef stpcpy +#endif + +#ifndef weak_alias +# define __stpcpy stpcpy +#endif + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char * +__stpcpy (char *dest, const char *src) +{ + register char *d = dest; + register const char *s = src; + + do + *d++ = *s; + while (*s++ != '\0'); + + return d - 1; +} +#ifdef weak_alias +weak_alias (__stpcpy, stpcpy) +#endif diff --git a/cross/lib/str-two-way.h b/cross/lib/str-two-way.h new file mode 100644 index 00000000000..dfe702241c0 --- /dev/null +++ b/cross/lib/str-two-way.h @@ -0,0 +1,452 @@ +/* Byte-wise substring search, using the Two-Way algorithm. + Copyright (C) 2008-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Eric Blake , 2008. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Before including this file, you need to include and + , and define: + RETURN_TYPE A macro that expands to the return type. + AVAILABLE(h, h_l, j, n_l) + A macro that returns nonzero if there are + at least N_L bytes left starting at H[J]. + H is 'unsigned char *', H_L, J, and N_L + are 'size_t'; H_L is an lvalue. For + NUL-terminated searches, H_L can be + modified each iteration to avoid having + to compute the end of H up front. + + For case-insensitivity, you may optionally define: + CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L + characters of P1 and P2 are equal. + CANON_ELEMENT(c) A macro that canonicalizes an element right after + it has been fetched from one of the two strings. + The argument is an 'unsigned char'; the result + must be an 'unsigned char' as well. + + This file undefines the macros documented above, and defines + LONG_NEEDLE_THRESHOLD. +*/ + +#include +#include + +/* We use the Two-Way string matching algorithm (also known as + Chrochemore-Perrin), which guarantees linear complexity with + constant space. Additionally, for long needles, we also use a bad + character shift table similar to the Boyer-Moore algorithm to + achieve improved (potentially sub-linear) performance. + + See https://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260, + https://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm, + https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf +*/ + +/* Point at which computing a bad-byte shift table is likely to be + worthwhile. Small needles should not compute a table, since it + adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a + speedup no greater than a factor of NEEDLE_LEN. The larger the + needle, the better the potential performance gain. On the other + hand, on non-POSIX systems with CHAR_BIT larger than eight, the + memory required for the table is prohibitive. */ +#if CHAR_BIT < 10 +# define LONG_NEEDLE_THRESHOLD 32U +#else +# define LONG_NEEDLE_THRESHOLD SIZE_MAX +#endif + +#ifndef MAX +# define MAX(a, b) ((a < b) ? (b) : (a)) +#endif + +#ifndef CANON_ELEMENT +# define CANON_ELEMENT(c) c +#endif +#ifndef CMP_FUNC +# define CMP_FUNC memcmp +#endif + +/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN. + Return the index of the first byte in the right half, and set + *PERIOD to the global period of the right half. + + The global period of a string is the smallest index (possibly its + length) at which all remaining bytes in the string are repetitions + of the prefix (the last repetition may be a subset of the prefix). + + When NEEDLE is factored into two halves, a local period is the + length of the smallest word that shares a suffix with the left half + and shares a prefix with the right half. All factorizations of a + non-empty NEEDLE have a local period of at least 1 and no greater + than NEEDLE_LEN. + + A critical factorization has the property that the local period + equals the global period. All strings have at least one critical + factorization with the left half smaller than the global period. + And while some strings have more than one critical factorization, + it is provable that with an ordered alphabet, at least one of the + critical factorizations corresponds to a maximal suffix. + + Given an ordered alphabet, a critical factorization can be computed + in linear time, with 2 * NEEDLE_LEN comparisons, by computing the + shorter of two ordered maximal suffixes. The ordered maximal + suffixes are determined by lexicographic comparison while tracking + periodicity. */ +static size_t +critical_factorization (const unsigned char *needle, size_t needle_len, + size_t *period) +{ + /* Index of last byte of left half, or SIZE_MAX. */ + size_t max_suffix, max_suffix_rev; + size_t j; /* Index into NEEDLE for current candidate suffix. */ + size_t k; /* Offset into current period. */ + size_t p; /* Intermediate period. */ + unsigned char a, b; /* Current comparison bytes. */ + + /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered + out 0-length needles. */ + if (needle_len < 3) + { + *period = 1; + return needle_len - 1; + } + + /* Invariants: + 0 <= j < NEEDLE_LEN - 1 + -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed) + min(max_suffix, max_suffix_rev) < global period of NEEDLE + 1 <= p <= global period of NEEDLE + p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j] + 1 <= k <= p + */ + + /* Perform lexicographic search. */ + max_suffix = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[max_suffix + k]); + if (a < b) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* b < a */ + { + /* Suffix is larger, start over from current location. */ + max_suffix = j++; + k = p = 1; + } + } + *period = p; + + /* Perform reverse lexicographic search. */ + max_suffix_rev = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[max_suffix_rev + k]); + if (b < a) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix_rev; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* a < b */ + { + /* Suffix is larger, start over from current location. */ + max_suffix_rev = j++; + k = p = 1; + } + } + + /* Choose the shorter suffix. Return the index of the first byte of + the right half, rather than the last byte of the left half. + + For some examples, 'banana' has two critical factorizations, both + exposed by the two lexicographic extreme suffixes of 'anana' and + 'nana', where both suffixes have a period of 2. On the other + hand, with 'aab' and 'bba', both strings have a single critical + factorization of the last byte, with the suffix having a period + of 1. While the maximal lexicographic suffix of 'aab' is 'b', + the maximal lexicographic suffix of 'bba' is 'ba', which is not a + critical factorization. Conversely, the maximal reverse + lexicographic suffix of 'a' works for 'bba', but not 'ab' for + 'aab'. The shorter suffix of the two will always be a critical + factorization. */ + if (max_suffix_rev + 1 < max_suffix + 1) + return max_suffix + 1; + *period = p; + return max_suffix_rev + 1; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD. + Performance is guaranteed to be linear, with an initialization cost + of 2 * NEEDLE_LEN comparisons. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ +static RETURN_TYPE _GL_ATTRIBUTE_PURE +two_way_short_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch in the left half can + only advance by the period, so use memory to avoid rescanning + known occurrences of the period in the right half. */ + size_t memory = 0; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = MAX (suffix, memory); + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = suffix; + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN. + Performance is guaranteed to be linear, with an initialization cost + of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, + and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and + sublinear performance is not possible. */ +static RETURN_TYPE _GL_ATTRIBUTE_PURE +two_way_long_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + size_t shift_table[1U << CHAR_BIT]; /* See below. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Populate shift_table. For each possible byte value c, + shift_table[c] is the distance from the last occurrence of c to + the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE. + shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */ + for (i = 0; i < 1U << CHAR_BIT; i++) + shift_table[i] = needle_len; + for (i = 0; i < needle_len; i++) + shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1; + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch in the left half can + only advance by the period, so use memory to avoid rescanning + known occurrences of the period in the right half. */ + size_t memory = 0; + size_t shift; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + if (memory && shift < period) + { + /* Since needle is periodic, but the last period has + a byte out of place, there can be no match until + after the mismatch. */ + shift = needle_len - period; + } + memory = 0; + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = MAX (suffix, memory); + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + size_t shift; + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = suffix; + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +#undef AVAILABLE +#undef CANON_ELEMENT +#undef CMP_FUNC +#undef MAX +#undef RETURN_TYPE diff --git a/cross/lib/strftime.h b/cross/lib/strftime.h new file mode 100644 index 00000000000..88c1f73928f --- /dev/null +++ b/cross/lib/strftime.h @@ -0,0 +1,38 @@ +/* declarations for strftime.c + + Copyright (C) 2002, 2004, 2008-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Just like strftime, but with two more arguments: + POSIX requires that strftime use the local timezone information. + Use the timezone __TZ instead. Use __NS as the number of + nanoseconds in the %N directive. + + On error, set errno and return 0. Otherwise, return the number of + bytes generated (not counting the trailing NUL), preserving errno + if the number is 0. This errno behavior is in draft POSIX 202x + plus some requested changes to POSIX. */ +size_t nstrftime (char *restrict, size_t, char const *, struct tm const *, + timezone_t __tz, int __ns); + +#ifdef __cplusplus +} +#endif diff --git a/cross/lib/string.in.h b/cross/lib/string.in.h new file mode 100644 index 00000000000..b227a178873 --- /dev/null +++ b/cross/lib/string.in.h @@ -0,0 +1,1323 @@ +/* A GNU-like . + + Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _GL_ALREADY_INCLUDING_STRING_H +/* Special invocation convention: + - On OS X/NetBSD we have a sequence of nested includes + -> -> "string.h" + In this situation system _chk variants due to -D_FORTIFY_SOURCE + might be used after any replacements defined here. */ + +#@INCLUDE_NEXT@ @NEXT_STRING_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_STRING_H + +#define _GL_ALREADY_INCLUDING_STRING_H + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_STRING_H@ + +#undef _GL_ALREADY_INCLUDING_STRING_H + +#ifndef _@GUARD_PREFIX@_STRING_H +#define _@GUARD_PREFIX@_STRING_H + +/* NetBSD 5.0 mis-defines NULL. */ +#include + +/* MirBSD defines mbslen as a macro. */ +#if @GNULIB_MBSLEN@ && defined __MirBSD__ +# include +#endif + +/* NetBSD 5.0 declares strsignal in , not in . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \ + && ! defined __GLIBC__ +# include +#endif + +/* AIX 7.2 and Android 13 declare ffsl and ffsll in , not in + . */ +/* But in any case avoid namespace pollution on glibc systems. */ +#if ((@GNULIB_FFSL@ || @GNULIB_FFSLL@ || defined GNULIB_POSIXCHECK) \ + && (defined _AIX || defined __ANDROID__)) \ + && ! defined __GLIBC__ +# include +#endif + +/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. */ +#ifndef _GL_ATTRIBUTE_DEALLOC +# if __GNUC__ >= 11 +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) +# else +# define _GL_ATTRIBUTE_DEALLOC(f, i) +# endif +#endif + +/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that + can be freed via 'free'; it can be used only after declaring 'free'. */ +/* Applies to: functions. Cannot be used on inline functions. */ +#ifndef _GL_ATTRIBUTE_DEALLOC_FREE +# if defined __cplusplus && defined __GNUC__ && !defined __clang__ +/* Work around GCC bug */ +# define _GL_ATTRIBUTE_DEALLOC_FREE \ + _GL_ATTRIBUTE_DEALLOC ((void (*) (void *)) free, 1) +# else +# define _GL_ATTRIBUTE_DEALLOC_FREE \ + _GL_ATTRIBUTE_DEALLOC (free, 1) +# endif +#endif + +/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly + allocated memory. */ +/* Applies to: functions. */ +#ifndef _GL_ATTRIBUTE_MALLOC +# if __GNUC__ >= 3 || defined __clang__ +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define _GL_ATTRIBUTE_MALLOC +# endif +#endif + +/* The __attribute__ feature is available in gcc versions 2.5 and later. + The attribute __pure__ was added in gcc 2.96. */ +#ifndef _GL_ATTRIBUTE_PURE +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define _GL_ATTRIBUTE_PURE /* empty */ +# endif +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though may not have + been included yet. */ +#if @GNULIB_FREE_POSIX@ +# if (@REPLACE_FREE@ && !defined free \ + && !(defined __cplusplus && defined GNULIB_NAMESPACE)) +/* We can't do '#define free rpl_free' here. */ +_GL_EXTERN_C void rpl_free (void *); +# undef _GL_ATTRIBUTE_DEALLOC_FREE +# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1) +# else +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); +# else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) throw (); +# else +_GL_EXTERN_C void free (void *); +# endif +# endif +# endif +#else +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); +# else +# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) +_GL_EXTERN_C void free (void *) throw (); +# else +_GL_EXTERN_C void free (void *); +# endif +# endif +#endif + +/* Clear a block of memory. The compiler will not delete a call to + this function, even if the block is dead after the call. */ +#if @GNULIB_EXPLICIT_BZERO@ +# if ! @HAVE_EXPLICIT_BZERO@ +_GL_FUNCDECL_SYS (explicit_bzero, void, + (void *__dest, size_t __n) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (explicit_bzero, void, (void *__dest, size_t __n)); +_GL_CXXALIASWARN (explicit_bzero); +#elif defined GNULIB_POSIXCHECK +# undef explicit_bzero +# if HAVE_RAW_DECL_EXPLICIT_BZERO +_GL_WARN_ON_USE (explicit_bzero, "explicit_bzero is unportable - " + "use gnulib module explicit_bzero for portability"); +# endif +#endif + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSL@ +# if !@HAVE_FFSL@ +_GL_FUNCDECL_SYS (ffsl, int, (long int i)); +# endif +_GL_CXXALIAS_SYS (ffsl, int, (long int i)); +_GL_CXXALIASWARN (ffsl); +#elif defined GNULIB_POSIXCHECK +# undef ffsl +# if HAVE_RAW_DECL_FFSL +_GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module"); +# endif +#endif + + +/* Find the index of the least-significant set bit. */ +#if @GNULIB_FFSLL@ +# if @REPLACE_FFSLL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define ffsll rpl_ffsll +# endif +_GL_FUNCDECL_RPL (ffsll, int, (long long int i)); +_GL_CXXALIAS_RPL (ffsll, int, (long long int i)); +# else +# if !@HAVE_FFSLL@ +_GL_FUNCDECL_SYS (ffsll, int, (long long int i)); +# endif +_GL_CXXALIAS_SYS (ffsll, int, (long long int i)); +# endif +_GL_CXXALIASWARN (ffsll); +#elif defined GNULIB_POSIXCHECK +# undef ffsll +# if HAVE_RAW_DECL_FFSLL +_GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module"); +# endif +#endif + + +#if @GNULIB_MDA_MEMCCPY@ +/* On native Windows, map 'memccpy' to '_memccpy', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::memccpy always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef memccpy +# define memccpy _memccpy +# endif +_GL_CXXALIAS_MDA (memccpy, void *, + (void *dest, const void *src, int c, size_t n)); +# else +_GL_CXXALIAS_SYS (memccpy, void *, + (void *dest, const void *src, int c, size_t n)); +# endif +_GL_CXXALIASWARN (memccpy); +#endif + + +/* Return the first instance of C within N bytes of S, or NULL. */ +#if @GNULIB_MEMCHR@ +# if @REPLACE_MEMCHR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef memchr +# define memchr rpl_memchr +# endif +_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n)); +# else + /* On some systems, this function is defined as an overloaded function: + extern "C" { const void * std::memchr (const void *, int, size_t); } + extern "C++" { void * std::memchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memchr, + void *, (void const *__s, int __c, size_t __n), + void const *, (void const *__s, int __c, size_t __n)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ()); +_GL_CXXALIASWARN1 (memchr, void const *, + (void const *__s, int __c, size_t __n) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (memchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memchr +/* Assume memchr is always declared. */ +_GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " + "use gnulib module memchr for portability" ); +#endif + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +#if @GNULIB_MEMMEM@ +# if @REPLACE_MEMMEM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define memmem rpl_memmem +# endif +_GL_FUNCDECL_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# else +# if ! @HAVE_DECL_MEMMEM@ +_GL_FUNCDECL_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (memmem, void *, + (void const *__haystack, size_t __haystack_len, + void const *__needle, size_t __needle_len)); +# endif +_GL_CXXALIASWARN (memmem); +#elif defined GNULIB_POSIXCHECK +# undef memmem +# if HAVE_RAW_DECL_MEMMEM +_GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " + "use gnulib module memmem-simple for portability, " + "and module memmem for speed" ); +# endif +#endif + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +#if @GNULIB_MEMPCPY@ +# if ! @HAVE_MEMPCPY@ +_GL_FUNCDECL_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (mempcpy, void *, + (void *restrict __dest, void const *restrict __src, + size_t __n)); +_GL_CXXALIASWARN (mempcpy); +#elif defined GNULIB_POSIXCHECK +# undef mempcpy +# if HAVE_RAW_DECL_MEMPCPY +_GL_WARN_ON_USE (mempcpy, "mempcpy is unportable - " + "use gnulib module mempcpy for portability"); +# endif +#endif + +/* Search backwards through a block for a byte (specified as an int). */ +#if @GNULIB_MEMRCHR@ +# if ! @HAVE_DECL_MEMRCHR@ +_GL_FUNCDECL_SYS (memrchr, void *, (void const *, int, size_t) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::memrchr (const void *, int, size_t); } + extern "C++" { void * std::memrchr (void *, int, size_t); } */ +_GL_CXXALIAS_SYS_CAST2 (memrchr, + void *, (void const *, int, size_t), + void const *, (void const *, int, size_t)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ()); +_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (memrchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef memrchr +# if HAVE_RAW_DECL_MEMRCHR +_GL_WARN_ON_USE (memrchr, "memrchr is unportable - " + "use gnulib module memrchr for portability"); +# endif +#endif + +/* Overwrite a block of memory. The compiler will not optimize + effects away, even if the block is dead after the call. */ +#if @GNULIB_MEMSET_EXPLICIT@ +# if ! @HAVE_MEMSET_EXPLICIT@ +_GL_FUNCDECL_SYS (memset_explicit, void *, + (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t __n)); +_GL_CXXALIASWARN (memset_explicit); +#elif defined GNULIB_POSIXCHECK +# undef memset_explicit +# if HAVE_RAW_DECL_MEMSET_EXPLICIT +_GL_WARN_ON_USE (memset_explicit, "memset_explicit is unportable - " + "use gnulib module memset_explicit for portability"); +# endif +#endif + +/* Find the first occurrence of C in S. More efficient than + memchr(S,C,N), at the expense of undefined behavior if C does not + occur within N bytes. */ +#if @GNULIB_RAWMEMCHR@ +# if ! @HAVE_RAWMEMCHR@ +_GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const void * std::rawmemchr (const void *, int); } + extern "C++" { void * std::rawmemchr (void *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (rawmemchr, + void *, (void const *__s, int __c_in), + void const *, (void const *__s, int __c_in)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ()); +_GL_CXXALIASWARN1 (rawmemchr, void const *, + (void const *__s, int __c_in) throw ()); +# else +_GL_CXXALIASWARN (rawmemchr); +# endif +#elif defined GNULIB_POSIXCHECK +# undef rawmemchr +# if HAVE_RAW_DECL_RAWMEMCHR +_GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - " + "use gnulib module rawmemchr for portability"); +# endif +#endif + +/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */ +#if @GNULIB_STPCPY@ +# if ! @HAVE_STPCPY@ +_GL_FUNCDECL_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpcpy, char *, + (char *restrict __dst, char const *restrict __src)); +_GL_CXXALIASWARN (stpcpy); +#elif defined GNULIB_POSIXCHECK +# undef stpcpy +# if HAVE_RAW_DECL_STPCPY +_GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " + "use gnulib module stpcpy for portability"); +# endif +#endif + +/* Copy no more than N bytes of SRC to DST, returning a pointer past the + last non-NUL byte written into DST. */ +#if @GNULIB_STPNCPY@ +# if @REPLACE_STPNCPY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef stpncpy +# define stpncpy rpl_stpncpy +# endif +_GL_FUNCDECL_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# else +# if ! @HAVE_STPNCPY@ +_GL_FUNCDECL_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (stpncpy, char *, + (char *restrict __dst, char const *restrict __src, + size_t __n)); +# endif +_GL_CXXALIASWARN (stpncpy); +#elif defined GNULIB_POSIXCHECK +# undef stpncpy +# if HAVE_RAW_DECL_STPNCPY +_GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " + "use gnulib module stpncpy for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strchr +/* Assume strchr is always declared. */ +_GL_WARN_ON_USE_CXX (strchr, + const char *, char *, (const char *, int), + "strchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbschr if you care about internationalization"); +#endif + +/* Find the first occurrence of C in S or the final NUL byte. */ +#if @GNULIB_STRCHRNUL@ +# if @REPLACE_STRCHRNUL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strchrnul rpl_strchrnul +# endif +_GL_FUNCDECL_RPL (strchrnul, char *, (const char *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strchrnul, char *, + (const char *str, int ch)); +# else +# if ! @HAVE_STRCHRNUL@ +_GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * std::strchrnul (const char *, int); } + extern "C++" { char * std::strchrnul (char *, int); } */ +_GL_CXXALIAS_SYS_CAST2 (strchrnul, + char *, (char const *__s, int __c_in), + char const *, (char const *__s, int __c_in)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ()); +_GL_CXXALIASWARN1 (strchrnul, char const *, + (char const *__s, int __c_in) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (strchrnul); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strchrnul +# if HAVE_RAW_DECL_STRCHRNUL +_GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - " + "use gnulib module strchrnul for portability"); +# endif +#endif + +/* Duplicate S, returning an identical malloc'd string. */ +#if @GNULIB_STRDUP@ +# if @REPLACE_STRDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strdup +# define strdup rpl_strdup +# endif +_GL_FUNCDECL_RPL (strdup, char *, + (char const *__s) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (strdup, char *, (char const *__s)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strdup +# define strdup _strdup +# endif +_GL_CXXALIAS_MDA (strdup, char *, (char const *__s)); +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup + /* strdup exists as a function and as a macro. Get rid of the macro. */ +# undef strdup +# endif +# if (!@HAVE_DECL_STRDUP@ || __GNUC__ >= 11) && !defined strdup +_GL_FUNCDECL_SYS (strdup, char *, + (char const *__s) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); +# endif +_GL_CXXALIASWARN (strdup); +#else +# if __GNUC__ >= 11 && !defined strdup +/* For -Wmismatched-dealloc: Associate strdup with free or rpl_free. */ +_GL_FUNCDECL_SYS (strdup, char *, + (char const *__s) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK +# undef strdup +# if HAVE_RAW_DECL_STRDUP +_GL_WARN_ON_USE (strdup, "strdup is unportable - " + "use gnulib module strdup for portability"); +# endif +# elif @GNULIB_MDA_STRDUP@ +/* On native Windows, map 'creat' to '_creat', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::strdup always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strdup +# define strdup _strdup +# endif +_GL_CXXALIAS_MDA (strdup, char *, (char const *__s)); +# else +# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup +# undef strdup +# endif +_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); +# endif +_GL_CXXALIASWARN (strdup); +# endif +#endif + +/* Append no more than N characters from SRC onto DEST. */ +#if @GNULIB_STRNCAT@ +# if @REPLACE_STRNCAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strncat +# define strncat rpl_strncat +# endif +_GL_FUNCDECL_RPL (strncat, char *, + (char *restrict dest, const char *restrict src, size_t n) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strncat, char *, + (char *restrict dest, const char *restrict src, size_t n)); +# else +_GL_CXXALIAS_SYS (strncat, char *, + (char *restrict dest, const char *restrict src, size_t n)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strncat); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strncat +# if HAVE_RAW_DECL_STRNCAT +_GL_WARN_ON_USE (strncat, "strncat is unportable - " + "use gnulib module strncat for portability"); +# endif +#endif + +/* Return a newly allocated copy of at most N bytes of STRING. */ +#if @GNULIB_STRNDUP@ +# if @REPLACE_STRNDUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strndup +# define strndup rpl_strndup +# endif +_GL_FUNCDECL_RPL (strndup, char *, + (char const *__s, size_t __n) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +_GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n)); +# else +# if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup) +_GL_FUNCDECL_SYS (strndup, char *, + (char const *__s, size_t __n) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +_GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); +# endif +_GL_CXXALIASWARN (strndup); +#else +# if __GNUC__ >= 11 && !defined strndup +/* For -Wmismatched-dealloc: Associate strndup with free or rpl_free. */ +_GL_FUNCDECL_SYS (strndup, char *, + (char const *__s, size_t __n) + _GL_ARG_NONNULL ((1)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); +# endif +# if defined GNULIB_POSIXCHECK +# undef strndup +# if HAVE_RAW_DECL_STRNDUP +_GL_WARN_ON_USE (strndup, "strndup is unportable - " + "use gnulib module strndup for portability"); +# endif +# endif +#endif + +/* Find the length (number of bytes) of STRING, but scan at most + MAXLEN bytes. If no '\0' terminator is found in that many bytes, + return MAXLEN. */ +#if @GNULIB_STRNLEN@ +# if @REPLACE_STRNLEN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strnlen +# define strnlen rpl_strnlen +# endif +_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__s, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__s, size_t __maxlen)); +# else +# if ! @HAVE_DECL_STRNLEN@ +_GL_FUNCDECL_SYS (strnlen, size_t, (char const *__s, size_t __maxlen) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (strnlen, size_t, (char const *__s, size_t __maxlen)); +# endif +_GL_CXXALIASWARN (strnlen); +#elif defined GNULIB_POSIXCHECK +# undef strnlen +# if HAVE_RAW_DECL_STRNLEN +_GL_WARN_ON_USE (strnlen, "strnlen is unportable - " + "use gnulib module strnlen for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strcspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strcspn +/* Assume strcspn is always declared. */ +_GL_WARN_ON_USE (strcspn, "strcspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbscspn if you care about internationalization"); +#endif + +/* Find the first occurrence in S of any character in ACCEPT. */ +#if @GNULIB_STRPBRK@ +# if ! @HAVE_STRPBRK@ +_GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C" { const char * strpbrk (const char *, const char *); } + extern "C++" { char * strpbrk (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strpbrk, + char *, (char const *__s, char const *__accept), + const char *, (char const *__s, char const *__accept)); +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw ()); +_GL_CXXALIASWARN1 (strpbrk, char const *, + (char const *__s, char const *__accept) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (strpbrk); +# endif +# if defined GNULIB_POSIXCHECK +/* strpbrk() assumes the second argument is a list of single-byte characters. + Even in this simple case, it does not work with multibyte strings if the + locale encoding is GB18030 and one of the characters to be searched is a + digit. */ +# undef strpbrk +_GL_WARN_ON_USE_CXX (strpbrk, + const char *, char *, (const char *, const char *), + "strpbrk cannot work correctly on character strings " + "in multibyte locales - " + "use mbspbrk if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strpbrk +# if HAVE_RAW_DECL_STRPBRK +_GL_WARN_ON_USE_CXX (strpbrk, + const char *, char *, (const char *, const char *), + "strpbrk is unportable - " + "use gnulib module strpbrk for portability"); +# endif +#endif + +#if defined GNULIB_POSIXCHECK +/* strspn() assumes the second argument is a list of single-byte characters. + Even in this simple case, it cannot work with multibyte strings. */ +# undef strspn +/* Assume strspn is always declared. */ +_GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " + "in multibyte locales - " + "use mbsspn if you care about internationalization"); +#endif + +#if defined GNULIB_POSIXCHECK +/* strrchr() does not work with multibyte strings if the locale encoding is + GB18030 and the character to be searched is a digit. */ +# undef strrchr +/* Assume strrchr is always declared. */ +_GL_WARN_ON_USE_CXX (strrchr, + const char *, char *, (const char *, int), + "strrchr cannot work correctly on character strings " + "in some multibyte locales - " + "use mbsrchr if you care about internationalization"); +#endif + +/* Search the next delimiter (char listed in DELIM) starting at *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP + to point to the next char after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of strtok() that is multithread-safe and supports + empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strtok_r(). */ +#if @GNULIB_STRSEP@ +# if ! @HAVE_STRSEP@ +_GL_FUNCDECL_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strsep, char *, + (char **restrict __stringp, char const *restrict __delim)); +_GL_CXXALIASWARN (strsep); +# if defined GNULIB_POSIXCHECK +# undef strsep +_GL_WARN_ON_USE (strsep, "strsep cannot work correctly on character strings " + "in multibyte locales - " + "use mbssep if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strsep +# if HAVE_RAW_DECL_STRSEP +_GL_WARN_ON_USE (strsep, "strsep is unportable - " + "use gnulib module strsep for portability"); +# endif +#endif + +#if @GNULIB_STRSTR@ +# if @REPLACE_STRSTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strstr rpl_strstr +# endif +_GL_FUNCDECL_RPL (strstr, char *, (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strstr, char *, (const char *haystack, const char *needle)); +# else + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strstr (const char *, const char *); } + extern "C++" { char * strstr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strstr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strstr, char *, + (char *haystack, const char *needle) throw ()); +_GL_CXXALIASWARN1 (strstr, const char *, + (const char *haystack, const char *needle) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (strstr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strstr() does not work with multibyte strings if the locale encoding is + different from UTF-8: + POSIX says that it operates on "strings", and "string" in POSIX is defined + as a sequence of bytes, not of characters. */ +# undef strstr +/* Assume strstr is always declared. */ +_GL_WARN_ON_USE (strstr, "strstr is quadratic on many systems, and cannot " + "work correctly on character strings in most " + "multibyte locales - " + "use mbsstr if you care about internationalization, " + "or use strstr if you care about speed"); +#endif + +/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive + comparison. */ +#if @GNULIB_STRCASESTR@ +# if @REPLACE_STRCASESTR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strcasestr rpl_strcasestr +# endif +_GL_FUNCDECL_RPL (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strcasestr, char *, + (const char *haystack, const char *needle)); +# else +# if ! @HAVE_STRCASESTR@ +_GL_FUNCDECL_SYS (strcasestr, char *, + (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif + /* On some systems, this function is defined as an overloaded function: + extern "C++" { const char * strcasestr (const char *, const char *); } + extern "C++" { char * strcasestr (char *, const char *); } */ +_GL_CXXALIAS_SYS_CAST2 (strcasestr, + char *, (const char *haystack, const char *needle), + const char *, (const char *haystack, const char *needle)); +# endif +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ + || defined __clang__) +_GL_CXXALIASWARN1 (strcasestr, char *, + (char *haystack, const char *needle) throw ()); +_GL_CXXALIASWARN1 (strcasestr, const char *, + (const char *haystack, const char *needle) throw ()); +# elif __GLIBC__ >= 2 +_GL_CXXALIASWARN (strcasestr); +# endif +#elif defined GNULIB_POSIXCHECK +/* strcasestr() does not work with multibyte strings: + It is a glibc extension, and glibc implements it only for unibyte + locales. */ +# undef strcasestr +# if HAVE_RAW_DECL_STRCASESTR +_GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " + "strings in multibyte locales - " + "use mbscasestr if you care about " + "internationalization, or use c-strcasestr if you want " + "a locale independent function"); +# endif +#endif + +/* Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = strtok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + This is a variant of strtok() that is multithread-safe. + + For the POSIX documentation for this function, see: + https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + Caveat: It doesn't work with multibyte strings unless all of the delimiter + characters are ASCII characters < 0x30. + + See also strsep(). */ +#if @GNULIB_STRTOK_R@ +# if @REPLACE_STRTOK_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strtok_r +# define strtok_r rpl_strtok_r +# endif +_GL_FUNCDECL_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# else +# if @UNDEFINE_STRTOK_R@ || defined GNULIB_POSIXCHECK +# undef strtok_r +# endif +# if ! @HAVE_DECL_STRTOK_R@ +_GL_FUNCDECL_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (strtok_r, char *, + (char *restrict s, char const *restrict delim, + char **restrict save_ptr)); +# endif +_GL_CXXALIASWARN (strtok_r); +# if defined GNULIB_POSIXCHECK +_GL_WARN_ON_USE (strtok_r, "strtok_r cannot work correctly on character " + "strings in multibyte locales - " + "use mbstok_r if you care about internationalization"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strtok_r +# if HAVE_RAW_DECL_STRTOK_R +_GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " + "use gnulib module strtok_r for portability"); +# endif +#endif + + +/* The following functions are not specified by POSIX. They are gnulib + extensions. */ + +#if @GNULIB_MBSLEN@ +/* Return the number of multibyte characters in the character string STRING. + This considers multibyte characters, unlike strlen, which counts bytes. */ +# ifdef __MirBSD__ /* MirBSD defines mbslen as a macro. Override it. */ +# undef mbslen +# endif +# if @HAVE_MBSLEN@ /* AIX, OSF/1, MirBSD define mbslen already in libc. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbslen rpl_mbslen +# endif +_GL_FUNCDECL_RPL (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbslen, size_t, (const char *string)); +# else +_GL_FUNCDECL_SYS (mbslen, size_t, (const char *string) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (mbslen); +# endif +#endif + +#if @GNULIB_MBSNLEN@ +/* Return the number of multibyte characters in the character string starting + at STRING and ending at STRING + LEN. */ +_GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1)); +#endif + +#if @GNULIB_MBSCHR@ +/* Locate the first single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbschr rpl_mbschr /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbschr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbschr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbschr); +#endif + +#if @GNULIB_MBSRCHR@ +/* Locate the last single-byte character C in the character string STRING, + and return a pointer to it. Return NULL if C is not found in STRING. + Unlike strrchr(), this function works correctly in multibyte locales with + encodings such as GB18030. */ +# if defined __hpux || defined __INTERIX +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbsrchr rpl_mbsrchr /* avoid collision with system function */ +# endif +_GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mbsrchr, char *, (const char *string, int c)); +# else +_GL_FUNCDECL_SYS (mbsrchr, char *, (const char *string, int c) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); +# endif +_GL_CXXALIASWARN (mbsrchr); +#endif + +#if @GNULIB_MBSSTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. + Unlike strstr(), this function works correctly in multibyte locales with + encodings different from UTF-8. */ +_GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASECMP@ +/* Compare the character strings S1 and S2, ignoring case, returning less than, + equal to or greater than zero if S1 is lexicographically less than, equal to + or greater than S2. + Note: This function may, in multibyte locales, return 0 for strings of + different lengths! + Unlike strcasecmp(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSNCASECMP@ +/* Compare the initial segment of the character string S1 consisting of at most + N characters with the initial segment of the character string S2 consisting + of at most N characters, ignoring case, returning less than, equal to or + greater than zero if the initial segment of S1 is lexicographically less + than, equal to or greater than the initial segment of S2. + Note: This function may, in multibyte locales, return 0 for initial segments + of different lengths! + Unlike strncasecmp(), this function works correctly in multibyte locales. + But beware that N is not a byte count but a character count! */ +_GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPCASECMP@ +/* Compare the initial segment of the character string STRING consisting of + at most mbslen (PREFIX) characters with the character string PREFIX, + ignoring case. If the two match, return a pointer to the first byte + after this prefix in STRING. Otherwise, return NULL. + Note: This function may, in multibyte locales, return non-NULL if STRING + is of smaller length than PREFIX! + Unlike strncasecmp(), this function works correctly in multibyte + locales. */ +_GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCASESTR@ +/* Find the first occurrence of the character string NEEDLE in the character + string HAYSTACK, using case-insensitive comparison. + Note: This function may, in multibyte locales, return success even if + strlen (haystack) < strlen (needle) ! + Unlike strcasestr(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSCSPN@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strcspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSPBRK@ +/* Find the first occurrence in the character string STRING of any character + in the character string ACCEPT. Return the pointer to it, or NULL if none + exists. + Unlike strpbrk(), this function works correctly in multibyte locales. */ +# if defined __hpux +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ +# endif +_GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (mbspbrk, char *, (const char *string, const char *accept)); +# else +_GL_FUNCDECL_SYS (mbspbrk, char *, (const char *string, const char *accept) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); +# endif +_GL_CXXALIASWARN (mbspbrk); +#endif + +#if @GNULIB_MBSSPN@ +/* Find the first occurrence in the character string STRING of any character + not in the character string REJECT. Return the number of bytes from the + beginning of the string to this occurrence, or to the end of the string + if none exists. + Unlike strspn(), this function works correctly in multibyte locales. */ +_GL_EXTERN_C size_t mbsspn (const char *string, const char *reject) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSSEP@ +/* Search the next delimiter (multibyte character listed in the character + string DELIM) starting at the character string *STRINGP. + If one is found, overwrite it with a NUL, and advance *STRINGP to point + to the next multibyte character after it. Otherwise, set *STRINGP to NULL. + If *STRINGP was already NULL, nothing happens. + Return the old value of *STRINGP. + + This is a variant of mbstok_r() that supports empty fields. + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbstok_r(). */ +_GL_EXTERN_C char * mbssep (char **stringp, const char *delim) + _GL_ARG_NONNULL ((1, 2)); +#endif + +#if @GNULIB_MBSTOK_R@ +/* Parse the character string STRING into tokens separated by characters in + the character string DELIM. + If STRING is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = mbstok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" + + Caveat: It modifies the original string. + Caveat: These functions cannot be used on constant strings. + Caveat: The identity of the delimiting character is lost. + + See also mbssep(). */ +_GL_EXTERN_C char * mbstok_r (char *restrict string, const char *delim, + char **save_ptr) + _GL_ARG_NONNULL ((2, 3)); +#endif + +/* Map any int, typically from errno, into an error message. */ +#if @GNULIB_STRERROR@ +# if @REPLACE_STRERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror +# define strerror rpl_strerror +# endif +_GL_FUNCDECL_RPL (strerror, char *, (int)); +_GL_CXXALIAS_RPL (strerror, char *, (int)); +# else +_GL_CXXALIAS_SYS (strerror, char *, (int)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strerror); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror +/* Assume strerror is always declared. */ +_GL_WARN_ON_USE (strerror, "strerror is unportable - " + "use gnulib module strerror to guarantee non-NULL result"); +#endif + +/* Map any int, typically from errno, into an error message. Multithread-safe. + Uses the POSIX declaration, not the glibc declaration. */ +#if @GNULIB_STRERROR_R@ +# if @REPLACE_STRERROR_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerror_r +# define strerror_r rpl_strerror_r +# endif +_GL_FUNCDECL_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_STRERROR_R@ +_GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen)); +# endif +# if @HAVE_DECL_STRERROR_R@ +_GL_CXXALIASWARN (strerror_r); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror_r +# if HAVE_RAW_DECL_STRERROR_R +_GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - " + "use gnulib module strerror_r-posix for portability"); +# endif +#endif + +/* Return the name of the system error code ERRNUM. */ +#if @GNULIB_STRERRORNAME_NP@ +# if @REPLACE_STRERRORNAME_NP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strerrorname_np +# define strerrorname_np rpl_strerrorname_np +# endif +_GL_FUNCDECL_RPL (strerrorname_np, const char *, (int errnum)); +_GL_CXXALIAS_RPL (strerrorname_np, const char *, (int errnum)); +# else +# if !@HAVE_STRERRORNAME_NP@ +_GL_FUNCDECL_SYS (strerrorname_np, const char *, (int errnum)); +# endif +_GL_CXXALIAS_SYS (strerrorname_np, const char *, (int errnum)); +# endif +_GL_CXXALIASWARN (strerrorname_np); +#elif defined GNULIB_POSIXCHECK +# undef strerrorname_np +# if HAVE_RAW_DECL_STRERRORNAME_NP +_GL_WARN_ON_USE (strerrorname_np, "strerrorname_np is unportable - " + "use gnulib module strerrorname_np for portability"); +# endif +#endif + +/* Return an abbreviation string for the signal number SIG. */ +#if @GNULIB_SIGABBREV_NP@ +# if ! @HAVE_SIGABBREV_NP@ +_GL_FUNCDECL_SYS (sigabbrev_np, const char *, (int sig)); +# endif +_GL_CXXALIAS_SYS (sigabbrev_np, const char *, (int sig)); +_GL_CXXALIASWARN (sigabbrev_np); +#elif defined GNULIB_POSIXCHECK +# undef sigabbrev_np +# if HAVE_RAW_DECL_SIGABBREV_NP +_GL_WARN_ON_USE (sigabbrev_np, "sigabbrev_np is unportable - " + "use gnulib module sigabbrev_np for portability"); +# endif +#endif + +/* Return an English description string for the signal number SIG. */ +#if @GNULIB_SIGDESCR_NP@ +# if ! @HAVE_SIGDESCR_NP@ +_GL_FUNCDECL_SYS (sigdescr_np, const char *, (int sig)); +# endif +_GL_CXXALIAS_SYS (sigdescr_np, const char *, (int sig)); +_GL_CXXALIASWARN (sigdescr_np); +#elif defined GNULIB_POSIXCHECK +# undef sigdescr_np +# if HAVE_RAW_DECL_SIGDESCR_NP +_GL_WARN_ON_USE (sigdescr_np, "sigdescr_np is unportable - " + "use gnulib module sigdescr_np for portability"); +# endif +#endif + +#if @GNULIB_STRSIGNAL@ +# if @REPLACE_STRSIGNAL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strsignal rpl_strsignal +# endif +_GL_FUNCDECL_RPL (strsignal, char *, (int __sig)); +_GL_CXXALIAS_RPL (strsignal, char *, (int __sig)); +# else +# if ! @HAVE_DECL_STRSIGNAL@ +_GL_FUNCDECL_SYS (strsignal, char *, (int __sig)); +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is + 'const char *'. */ +_GL_CXXALIAS_SYS_CAST (strsignal, char *, (int __sig)); +# endif +_GL_CXXALIASWARN (strsignal); +#elif defined GNULIB_POSIXCHECK +# undef strsignal +# if HAVE_RAW_DECL_STRSIGNAL +_GL_WARN_ON_USE (strsignal, "strsignal is unportable - " + "use gnulib module strsignal for portability"); +# endif +#endif + +#if @GNULIB_STRVERSCMP@ +# if !@HAVE_STRVERSCMP@ +_GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); +_GL_CXXALIASWARN (strverscmp); +#elif defined GNULIB_POSIXCHECK +# undef strverscmp +# if HAVE_RAW_DECL_STRVERSCMP +_GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " + "use gnulib module strverscmp for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif /* _@GUARD_PREFIX@_STRING_H */ +#endif diff --git a/cross/lib/strnlen.c b/cross/lib/strnlen.c new file mode 100644 index 00000000000..09c010eac42 --- /dev/null +++ b/cross/lib/strnlen.c @@ -0,0 +1,30 @@ +/* Find the length of STRING, but scan at most MAXLEN characters. + Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#include + +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ + +size_t +strnlen (const char *string, size_t maxlen) +{ + const char *end = memchr (string, '\0', maxlen); + return end ? (size_t) (end - string) : maxlen; +} diff --git a/cross/lib/strtoimax.c b/cross/lib/strtoimax.c new file mode 100644 index 00000000000..f7977e28e64 --- /dev/null +++ b/cross/lib/strtoimax.c @@ -0,0 +1,70 @@ +/* Convert string representation of a number into an intmax_t value. + + Copyright (C) 1999, 2001-2004, 2006, 2009-2023 Free Software Foundation, + Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +/* Verify interface. */ +#include + +#include + +#ifdef UNSIGNED +# ifndef HAVE_DECL_STRTOULL +"this configure-time declaration test was not run" +# endif +# if !HAVE_DECL_STRTOULL +unsigned long long int strtoull (char const *, char **, int); +# endif + +#else + +# ifndef HAVE_DECL_STRTOLL +"this configure-time declaration test was not run" +# endif +# if !HAVE_DECL_STRTOLL +long long int strtoll (char const *, char **, int); +# endif +#endif + +#ifdef UNSIGNED +# define Int uintmax_t +# define Strtoimax strtoumax +# define Strtol strtoul +# define Strtoll strtoull +# define Unsigned unsigned +#else +# define Int intmax_t +# define Strtoimax strtoimax +# define Strtol strtol +# define Strtoll strtoll +# define Unsigned +#endif + +Int +Strtoimax (char const *ptr, char **endptr, int base) +{ + static_assert (sizeof (Int) == sizeof (Unsigned long int) + || sizeof (Int) == sizeof (Unsigned long long int)); + + if (sizeof (Int) != sizeof (Unsigned long int)) + return Strtoll (ptr, endptr, base); + + return Strtol (ptr, endptr, base); +} diff --git a/cross/lib/strtol.c b/cross/lib/strtol.c new file mode 100644 index 00000000000..d11269b2622 --- /dev/null +++ b/cross/lib/strtol.c @@ -0,0 +1,408 @@ +/* Convert string representation of a number into an integer value. + + Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2023 Free Software + Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@gnu.org. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#ifdef _LIBC +# define USE_NUMBER_GROUPING +#else +# include +#endif + +#include +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#include +#include +#include + +#ifdef USE_NUMBER_GROUPING +# include "../locale/localeinfo.h" +#endif + +/* Nonzero if we are defining 'strtoul' or 'strtoull', operating on + unsigned integers. */ +#ifndef UNSIGNED +# define UNSIGNED 0 +# define INT LONG int +#else +# define INT unsigned LONG int +#endif + +/* Determine the name. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef strtol +# if UNSIGNED +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoull_l +# else +# define strtol __wcstoul_l +# endif +# else +# ifdef QUAD +# define strtol __strtoull_l +# else +# define strtol __strtoul_l +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol __wcstoll_l +# else +# define strtol __wcstol_l +# endif +# else +# ifdef QUAD +# define strtol __strtoll_l +# else +# define strtol __strtol_l +# endif +# endif +# endif +#else +# if UNSIGNED +# undef strtol +# ifdef USE_WIDE_CHAR +# ifdef QUAD +# define strtol wcstoull +# else +# define strtol wcstoul +# endif +# else +# ifdef QUAD +# define strtol strtoull +# else +# define strtol strtoul +# endif +# endif +# else +# ifdef USE_WIDE_CHAR +# undef strtol +# ifdef QUAD +# define strtol wcstoll +# else +# define strtol wcstol +# endif +# else +# ifdef QUAD +# undef strtol +# define strtol strtoll +# endif +# endif +# endif +#endif + +/* If QUAD is defined, we are defining 'strtoll' or 'strtoull', + operating on 'long long int's. */ +#ifdef QUAD +# define LONG long long +# define STRTOL_LONG_MIN LLONG_MIN +# define STRTOL_LONG_MAX LLONG_MAX +# define STRTOL_ULONG_MAX ULLONG_MAX +# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 + /* Work around gcc bug with using this constant. */ + static const unsigned long long int maxquad = ULLONG_MAX; +# undef STRTOL_ULONG_MAX +# define STRTOL_ULONG_MAX maxquad +# endif +#else +# define LONG long +# define STRTOL_LONG_MIN LONG_MIN +# define STRTOL_LONG_MAX LONG_MAX +# define STRTOL_ULONG_MAX ULONG_MAX +#endif + + +#ifdef USE_NUMBER_GROUPING +# define GROUP_PARAM_PROTO , int group +#else +# define GROUP_PARAM_PROTO +#endif + +/* We use this code also for the extended locale handling where the + function gets as an additional argument the locale which has to be + used. To access the values we have to redefine the _NL_CURRENT + macro. */ +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +# undef _NL_CURRENT +# define _NL_CURRENT(category, item) \ + (current->values[_NL_ITEM_INDEX (item)].string) +# define LOCALE_PARAM , loc +# define LOCALE_PARAM_PROTO , __locale_t loc +#else +# define LOCALE_PARAM +# define LOCALE_PARAM_PROTO +#endif + +#ifdef USE_WIDE_CHAR +# include +# include +# define L_(Ch) L##Ch +# define UCHAR_TYPE wint_t +# define STRING_TYPE wchar_t +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __iswspace_l ((Ch), loc) +# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) +# define TOUPPER(Ch) __towupper_l ((Ch), loc) +# else +# define ISSPACE(Ch) iswspace (Ch) +# define ISALPHA(Ch) iswalpha (Ch) +# define TOUPPER(Ch) towupper (Ch) +# endif +#else +# define L_(Ch) Ch +# define UCHAR_TYPE unsigned char +# define STRING_TYPE char +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc) +# define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc) +# define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc) +# else +# define ISSPACE(Ch) isspace ((unsigned char) (Ch)) +# define ISALPHA(Ch) isalpha ((unsigned char) (Ch)) +# define TOUPPER(Ch) toupper ((unsigned char) (Ch)) +# endif +#endif + +#ifdef USE_NUMBER_GROUPING +# define INTERNAL(X) INTERNAL1(X) +# define INTERNAL1(X) __##X##_internal +# define WEAKNAME(X) WEAKNAME1(X) +#else +# define INTERNAL(X) X +#endif + +#ifdef USE_NUMBER_GROUPING +/* This file defines a function to check for correct grouping. */ +# include "grouping.h" +#endif + + + +/* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE. + If BASE is 0 the base is determined by the presence of a leading + zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. + If BASE is < 2 or > 36, it is reset to 10. + If ENDPTR is not NULL, a pointer to the character after the last + one converted is stored in *ENDPTR. */ + +INT +INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, + int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO) +{ + int negative; + register unsigned LONG int cutoff; + register unsigned int cutlim; + register unsigned LONG int i; + register const STRING_TYPE *s; + register UCHAR_TYPE c; + const STRING_TYPE *save, *end; + int overflow; + +#ifdef USE_NUMBER_GROUPING +# ifdef USE_IN_EXTENDED_LOCALE_MODEL + struct locale_data *current = loc->__locales[LC_NUMERIC]; +# endif + /* The thousands character of the current locale. */ + wchar_t thousands = L'\0'; + /* The numeric grouping specification of the current locale, + in the format described in . */ + const char *grouping; + + if (group) + { + grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); + if (*grouping <= 0 || *grouping == CHAR_MAX) + grouping = NULL; + else + { + /* Figure out the thousands separator character. */ +# if defined _LIBC || defined _HAVE_BTOWC + thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); + if (thousands == WEOF) + thousands = L'\0'; +# endif + if (thousands == L'\0') + grouping = NULL; + } + } + else + grouping = NULL; +#endif + + if (base < 0 || base == 1 || base > 36) + { + __set_errno (EINVAL); + return 0; + } + + save = s = nptr; + + /* Skip white space. */ + while (ISSPACE (*s)) + ++s; + if (*s == L_('\0')) + goto noconv; + + /* Check for a sign. */ + if (*s == L_('-')) + { + negative = 1; + ++s; + } + else if (*s == L_('+')) + { + negative = 0; + ++s; + } + else + negative = 0; + + /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ + if (*s == L_('0')) + { + if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) + { + s += 2; + base = 16; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + /* Save the pointer so we can check later if anything happened. */ + save = s; + +#ifdef USE_NUMBER_GROUPING + if (group) + { + /* Find the end of the digit string and check its grouping. */ + end = s; + for (c = *end; c != L_('\0'); c = *++end) + if ((wchar_t) c != thousands + && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) + && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) + break; + if (*s == thousands) + end = s; + else + end = correctly_grouped_prefix (s, end, thousands, grouping); + } + else +#endif + end = NULL; + + cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; + cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; + + overflow = 0; + i = 0; + for (c = *s; c != L_('\0'); c = *++s) + { + if (s == end) + break; + if (c >= L_('0') && c <= L_('9')) + c -= L_('0'); + else if (ISALPHA (c)) + c = TOUPPER (c) - L_('A') + 10; + else + break; + if ((int) c >= base) + break; + /* Check for overflow. */ + if (i > cutoff || (i == cutoff && c > cutlim)) + overflow = 1; + else + { + i *= (unsigned LONG int) base; + i += c; + } + } + + /* Check if anything actually happened. */ + if (s == save) + goto noconv; + + /* Store in ENDPTR the address of one character + past the last character we converted. */ + if (endptr != NULL) + *endptr = (STRING_TYPE *) s; + +#if !UNSIGNED + /* Check for a value that is within the range of + 'unsigned LONG int', but outside the range of 'LONG int'. */ + if (overflow == 0 + && i > (negative + ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 + : (unsigned LONG int) STRTOL_LONG_MAX)) + overflow = 1; +#endif + + if (overflow) + { + __set_errno (ERANGE); +#if UNSIGNED + return STRTOL_ULONG_MAX; +#else + return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; +#endif + } + + /* Return the result of the appropriate sign. */ + return negative ? -i : i; + +noconv: + /* We must handle a special case here: the base is 0 or 16 and the + first two characters are '0' and 'x', but the rest are no + hexadecimal digits. This is no error case. We return 0 and + ENDPTR points to the 'x'. */ + if (endptr != NULL) + { + if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') + && save[-2] == L_('0')) + *endptr = (STRING_TYPE *) &save[-1]; + else + /* There was no number to convert. */ + *endptr = (STRING_TYPE *) nptr; + } + + return 0L; +} + +#ifdef USE_NUMBER_GROUPING +/* External user entry point. */ + +INT +# ifdef weak_function +weak_function +# endif +strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, + int base LOCALE_PARAM_PROTO) +{ + return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); +} +#endif diff --git a/cross/lib/strtoll.c b/cross/lib/strtoll.c new file mode 100644 index 00000000000..9fdfa19b220 --- /dev/null +++ b/cross/lib/strtoll.c @@ -0,0 +1,33 @@ +/* Function to parse a 'long long int' from text. + Copyright (C) 1995-1997, 1999, 2001, 2009-2023 Free Software Foundation, + Inc. + This file is part of the GNU C Library. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#define QUAD 1 + +#include + +#ifdef _LIBC +# ifdef SHARED +# include + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2) +compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0); +# endif + +# endif +weak_alias (strtoll, strtoq) +#endif diff --git a/cross/lib/symlink.c b/cross/lib/symlink.c new file mode 100644 index 00000000000..b5009ae8355 --- /dev/null +++ b/cross/lib/symlink.c @@ -0,0 +1,57 @@ +/* Stub for symlink(). + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#include + +/* Specification. */ +#include + +#include +#include +#include + + +#if HAVE_SYMLINK + +# undef symlink + +/* Create a symlink, but reject trailing slash. */ +int +rpl_symlink (char const *contents, char const *name) +{ + size_t len = strlen (name); + if (len && name[len - 1] == '/') + { + struct stat st; + if (lstat (name, &st) == 0 || errno == EOVERFLOW) + errno = EEXIST; + return -1; + } + return symlink (contents, name); +} + +#else /* !HAVE_SYMLINK */ + +/* The system does not support symlinks. */ +int +symlink (_GL_UNUSED char const *contents, + _GL_UNUSED char const *name) +{ + errno = ENOSYS; + return -1; +} + +#endif /* !HAVE_SYMLINK */ diff --git a/cross/lib/sys_random.in.h b/cross/lib/sys_random.in.h new file mode 100644 index 00000000000..8dca1326837 --- /dev/null +++ b/cross/lib/sys_random.in.h @@ -0,0 +1,100 @@ +/* Substitute for . + Copyright (C) 2020-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +# if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +# endif +@PRAGMA_COLUMNS@ + +#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H + +#if @HAVE_SYS_RANDOM_H@ + +/* On uClibc < 1.0.35, assumes prior inclusion of . + Do not use __UCLIBC__ here, as it might not be defined yet. + But avoid namespace pollution on glibc systems. */ +# ifndef __GLIBC__ +# include +# endif +/* On Mac OS X 10.5, assumes prior inclusion of . + On Max OS X 10.13, assumes prior inclusion of a file that + includes , such as or . */ +# if defined __APPLE__ && defined __MACH__ /* Mac OS X */ +# include +# include +# endif + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYS_RANDOM_H@ + +#endif + +#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H +#define _@GUARD_PREFIX@_SYS_RANDOM_H + +#include + +/* Define the GRND_* constants. */ +#ifndef GRND_NONBLOCK +# define GRND_NONBLOCK 1 +# define GRND_RANDOM 2 +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Declare overridden functions. */ + + +#if @GNULIB_GETRANDOM@ +/* Fill a buffer with random bytes. */ +# if @REPLACE_GETRANDOM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getrandom +# define getrandom rpl_getrandom +# endif +_GL_FUNCDECL_RPL (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags)); +# else +# if !@HAVE_GETRANDOM@ +_GL_FUNCDECL_SYS (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags)); +# endif +# if __GLIBC__ + (__GLIBC_MINOR__ >= 25) > 2 +_GL_CXXALIASWARN (getrandom); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getrandom +# if HAVE_RAW_DECL_GETRANDOM +_GL_WARN_ON_USE (getrandom, "getrandom is unportable - " + "use gnulib module getrandom for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */ +#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */ diff --git a/cross/lib/sys_select.in.h b/cross/lib/sys_select.in.h new file mode 100644 index 00000000000..13440fa6f0a --- /dev/null +++ b/cross/lib/sys_select.in.h @@ -0,0 +1,334 @@ +/* Substitute for . + Copyright (C) 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +# if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +# endif +@PRAGMA_COLUMNS@ + +/* On OSF/1 and Solaris 2.6, and + both include . + On Cygwin and OpenBSD, includes . + Simply delegate to the system's header in this case. */ +#if (@HAVE_SYS_SELECT_H@ \ + && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H \ + && ((defined __osf__ && defined _SYS_TYPES_H_ \ + && defined _OSF_SOURCE) \ + || (defined __sun && defined _SYS_TYPES_H \ + && (! (defined _XOPEN_SOURCE || defined _POSIX_C_SOURCE) \ + || defined __EXTENSIONS__)))) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#elif (@HAVE_SYS_SELECT_H@ \ + && (defined _CYGWIN_SYS_TIME_H \ + || (!defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H \ + && ((defined __osf__ && defined _SYS_TIME_H_ \ + && defined _OSF_SOURCE) \ + || (defined __OpenBSD__ && defined _SYS_TIME_H_) \ + || (defined __sun && defined _SYS_TIME_H \ + && (! (defined _XOPEN_SOURCE \ + || defined _POSIX_C_SOURCE) \ + || defined __EXTENSIONS__)))))) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +/* On IRIX 6.5, includes , which includes + , which includes . At this point we cannot + include , because that includes , which + gives a syntax error because has not been completely + processed. Simply delegate to the system's header in this case. */ +#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H) + +# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +/* On OpenBSD 5.0, includes , which includes + . At this point we cannot include , because that + includes gnulib's pthread.h override, which gives a syntax error because + /usr/include/pthread.h has not been completely processed. Simply delegate + to the system's header in this case. */ +#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER) + +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#else + +#ifndef _@GUARD_PREFIX@_SYS_SELECT_H + +/* On many platforms, assumes prior inclusion of + . Also, mingw defines sigset_t there, instead of + in where it belongs. */ +#include + +#if @HAVE_SYS_SELECT_H@ + +/* On OSF/1 4.0, provides only a forward declaration + of 'struct timeval', and no definition of this type. + Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select() + in . + But avoid namespace pollution on glibc systems, a circular include + -> -> on FreeBSD 13.1, and + "unknown type name" problems on Cygwin. */ +# if !(defined __GLIBC__ || defined __FreeBSD__ || defined __CYGWIN__) +# include +# endif + +/* On AIX 7 and Solaris 10, provides an FD_ZERO implementation + that relies on memset(), but without including . + But in any case avoid namespace pollution on glibc systems. */ +# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \ + && ! defined __GLIBC__ +# include +# endif + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ + +#endif + +/* Get definition of 'sigset_t'. + But avoid namespace pollution on glibc systems and "unknown type + name" problems on Cygwin. + On OS/2 kLIBC, sigset_t is defined in , too. In addition, + if is included, -> -> + are included. Then -> are included by GNULIB. By the + way, requires PAGE_SIZE defined in . However, + has not been processed, yet. As a result, 'PAGE_SIZE' + undeclared error occurs in . + Do this after the include_next (for the sake of OpenBSD 5.0) but before + the split double-inclusion guard (for the sake of Solaris). */ +#if !((defined __GLIBC__ || defined __CYGWIN__ || defined __KLIBC__) \ + && !defined __UCLIBC__) +# include +#endif + +#ifndef _@GUARD_PREFIX@_SYS_SELECT_H +#define _@GUARD_PREFIX@_SYS_SELECT_H + +#if !@HAVE_SYS_SELECT_H@ +/* A platform that lacks . */ +/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros + on most platforms. */ +# include +/* On HP-UX 11, provides an FD_ZERO implementation + that relies on memset(), but without including . */ +# if defined __hpux +# include +# endif +/* On native Windows platforms: + Get the 'fd_set' type. + Get the close() declaration before we override it. */ +# if @HAVE_WINSOCK2_H@ +# if !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +# endif +# include +# endif +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Fix some definitions from . */ + +#if @HAVE_WINSOCK2_H@ + +# if !GNULIB_defined_rpl_fd_isset + +/* Re-define FD_ISSET to avoid a WSA call while we are not using + network sockets. */ +static int +rpl_fd_isset (SOCKET fd, fd_set * set) +{ + u_int i; + if (set == NULL) + return 0; + + for (i = 0; i < set->fd_count; i++) + if (set->fd_array[i] == fd) + return 1; + + return 0; +} + +# define GNULIB_defined_rpl_fd_isset 1 +# endif + +# undef FD_ISSET +# define FD_ISSET(fd, set) rpl_fd_isset(fd, set) + +#endif + +/* Hide some function declarations from . */ + +#if @HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_UNISTD_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef close +# define close close_used_without_including_unistd_h +# elif !defined __clang__ + _GL_WARN_ON_USE (close, + "close() used without including "); +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname gethostname_used_without_including_unistd_h +# elif !defined __clang__ + _GL_WARN_ON_USE (gethostname, + "gethostname() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# elif !defined __clang__ + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +#endif + + +#if @GNULIB_PSELECT@ +# if @REPLACE_PSELECT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pselect +# define pselect rpl_pselect +# endif +_GL_FUNCDECL_RPL (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +_GL_CXXALIAS_RPL (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +# else +# if !@HAVE_PSELECT@ +_GL_FUNCDECL_SYS (pselect, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, const sigset_t *restrict)); +# endif +/* Need to cast, because on AIX 7, the second, third, fourth argument may be + void *restrict, void *restrict, void *restrict. */ +_GL_CXXALIAS_SYS_CAST (pselect, int, + (int, + fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timespec const *restrict, + const sigset_t *restrict)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (pselect); +# endif +#elif defined GNULIB_POSIXCHECK +# undef pselect +# if HAVE_RAW_DECL_PSELECT +_GL_WARN_ON_USE (pselect, "pselect is not portable - " + "use gnulib module pselect for portability"); +# endif +#endif + +#if @GNULIB_SELECT@ +# if @REPLACE_SELECT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select rpl_select +# endif +_GL_FUNCDECL_RPL (select, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + struct timeval *restrict)); +_GL_CXXALIAS_RPL (select, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + timeval *restrict)); +# else +_GL_CXXALIAS_SYS (select, int, + (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, + timeval *restrict)); +# endif +_GL_CXXALIASWARN (select); +#elif @HAVE_WINSOCK2_H@ +# undef select +# define select select_used_without_requesting_gnulib_module_select +#elif defined GNULIB_POSIXCHECK +# undef select +# if HAVE_RAW_DECL_SELECT +_GL_WARN_ON_USE (select, "select is not always POSIX compliant - " + "use gnulib module select for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ +#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ +#endif /* OSF/1 */ diff --git a/cross/lib/sys_stat.in.h b/cross/lib/sys_stat.in.h new file mode 100644 index 00000000000..096887c0162 --- /dev/null +++ b/cross/lib/sys_stat.in.h @@ -0,0 +1,954 @@ +/* Provide a more complete sys/stat.h header file. + Copyright (C) 2005-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ + +/* This file is supposed to be used on platforms where is + incomplete. It is intended to provide definitions and prototypes + needed by an application. Start with what the system provides. */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined __need_system_sys_stat_h +/* Special invocation convention. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H + +/* Get nlink_t. + May also define off_t to a 64-bit type on native Windows. */ +#include + +/* Get struct timespec. */ +#include + +/* The include_next requires a split double-inclusion guard. */ +#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ + +#ifndef _@GUARD_PREFIX@_SYS_STAT_H +#define _@GUARD_PREFIX@_SYS_STAT_H + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Before doing "#define mknod rpl_mknod" below, we need to include all + headers that may declare mknod(). OS/2 kLIBC declares mknod() in + , not in . */ +#ifdef __KLIBC__ +# include +#endif + +/* Before doing "#define mkdir rpl_mkdir" below, we need to include all + headers that may declare mkdir(). Native Windows platforms declare mkdir + in and/or , not in . */ +#if defined _WIN32 && ! defined __CYGWIN__ +# include /* mingw32, mingw64 */ +# include /* mingw64, MSVC 9 */ +#endif + +/* Native Windows platforms declare umask() in . */ +#if 0 && (defined _WIN32 && ! defined __CYGWIN__) +# include +#endif + +/* Large File Support on native Windows. */ +#if @WINDOWS_64_BIT_ST_SIZE@ +# define stat _stati64 +#endif + +/* Optionally, override 'struct stat' on native Windows. */ +#if @GNULIB_OVERRIDES_STRUCT_STAT@ + +# undef stat +# if @GNULIB_STAT@ +# define stat rpl_stat +# else + /* Provoke a clear link error if stat() is used as a function and + module 'stat' is not in use. */ +# define stat stat_used_without_requesting_gnulib_module_stat +# endif + +# if !GNULIB_defined_struct_stat +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; +# if 0 + uid_t st_uid; +# else /* uid_t is not defined by default on native Windows. */ + short st_uid; +# endif +# if 0 + gid_t st_gid; +# else /* gid_t is not defined by default on native Windows. */ + short st_gid; +# endif + dev_t st_rdev; + off_t st_size; +# if 0 + blksize_t st_blksize; + blkcnt_t st_blocks; +# endif + +# if @WINDOWS_STAT_TIMESPEC@ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# else + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +# endif +}; +# if @WINDOWS_STAT_TIMESPEC@ +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec + /* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_TIMESPEC 1 +# endif +# define GNULIB_defined_struct_stat 1 +# endif + +/* Other possible values of st_mode. */ +# if 0 +# define _S_IFBLK 0x6000 +# endif +# if 0 +# define _S_IFLNK 0xA000 +# endif +# if 0 +# define _S_IFSOCK 0xC000 +# endif + +#endif + +#ifndef S_IFIFO +# ifdef _S_IFIFO +# define S_IFIFO _S_IFIFO +# endif +#endif + +#ifndef S_IFMT +# define S_IFMT 0170000 +#endif + +#if STAT_MACROS_BROKEN +# undef S_ISBLK +# undef S_ISCHR +# undef S_ISDIR +# undef S_ISFIFO +# undef S_ISLNK +# undef S_ISNAM +# undef S_ISMPB +# undef S_ISMPC +# undef S_ISNWK +# undef S_ISREG +# undef S_ISSOCK +#endif + +#ifndef S_ISBLK +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) 0 +# endif +#endif + +#ifndef S_ISCHR +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) 0 +# endif +#endif + +#ifndef S_ISDIR +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) 0 +# endif +#endif + +#ifndef S_ISDOOR /* Solaris 2.5 and up */ +# define S_ISDOOR(m) 0 +#endif + +#ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +#endif + +#ifndef S_ISLNK +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) 0 +# endif +#endif + +#ifndef S_ISMPB /* V7 */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPB(m) 0 +# define S_ISMPC(m) 0 +# endif +#endif + +#ifndef S_ISMPX /* AIX */ +# define S_ISMPX(m) 0 +#endif + +#ifndef S_ISNAM /* Xenix */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) 0 +# endif +#endif + +#ifndef S_ISNWK /* HP/UX */ +# ifdef S_IFNWK +# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) +# else +# define S_ISNWK(m) 0 +# endif +#endif + +#ifndef S_ISPORT /* Solaris 10 and up */ +# define S_ISPORT(m) 0 +#endif + +#ifndef S_ISREG +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) 0 +# endif +#endif + +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +#endif + + +#ifndef S_TYPEISMQ +# define S_TYPEISMQ(p) 0 +#endif + +#ifndef S_TYPEISTMO +# define S_TYPEISTMO(p) 0 +#endif + + +#ifndef S_TYPEISSEM +# ifdef S_INSEM +# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) +# else +# define S_TYPEISSEM(p) 0 +# endif +#endif + +#ifndef S_TYPEISSHM +# ifdef S_INSHD +# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) +# else +# define S_TYPEISSHM(p) 0 +# endif +#endif + +/* high performance ("contiguous data") */ +#ifndef S_ISCTG +# define S_ISCTG(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with data */ +#ifndef S_ISOFD +# define S_ISOFD(p) 0 +#endif + +/* Cray DMF (data migration facility): off line, with no data */ +#ifndef S_ISOFL +# define S_ISOFL(p) 0 +#endif + +/* 4.4BSD whiteout */ +#ifndef S_ISWHT +# define S_ISWHT(m) 0 +#endif + +/* If any of the following are undefined, + define them to their de facto standard values. */ +#if !S_ISUID +# define S_ISUID 04000 +#endif +#if !S_ISGID +# define S_ISGID 02000 +#endif + +/* S_ISVTX is a common extension to POSIX. */ +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif + +#if !S_IRUSR && S_IREAD +# define S_IRUSR S_IREAD +#endif +#if !S_IRUSR +# define S_IRUSR 00400 +#endif +#if !S_IRGRP +# define S_IRGRP (S_IRUSR >> 3) +#endif +#if !S_IROTH +# define S_IROTH (S_IRUSR >> 6) +#endif + +#if !S_IWUSR && S_IWRITE +# define S_IWUSR S_IWRITE +#endif +#if !S_IWUSR +# define S_IWUSR 00200 +#endif +#if !S_IWGRP +# define S_IWGRP (S_IWUSR >> 3) +#endif +#if !S_IWOTH +# define S_IWOTH (S_IWUSR >> 6) +#endif + +#if !S_IXUSR && S_IEXEC +# define S_IXUSR S_IEXEC +#endif +#if !S_IXUSR +# define S_IXUSR 00100 +#endif +#if !S_IXGRP +# define S_IXGRP (S_IXUSR >> 3) +#endif +#if !S_IXOTH +# define S_IXOTH (S_IXUSR >> 6) +#endif + +#if !S_IRWXU +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif +#if !S_IRWXG +# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#if !S_IRWXO +# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif + +/* Although S_IXUGO and S_IRWXUGO are not specified by POSIX and are + not implemented in GNU/Linux, some Gnulib-using apps use the macros. */ +#if !S_IXUGO +# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) +#endif +#ifndef S_IRWXUGO +# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + +/* Macros for futimens and utimensat. */ +#ifndef UTIME_NOW +# define UTIME_NOW (-1) +# define UTIME_OMIT (-2) +#endif + + +#if @GNULIB_CHMOD@ +# if @REPLACE_CHMOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod rpl_chmod +# endif +_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod _chmod +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (chmod); +#elif defined GNULIB_POSIXCHECK +# undef chmod +# if HAVE_RAW_DECL_CHMOD +_GL_WARN_ON_USE (chmod, "chmod has portability problems - " + "use gnulib module chmod for portability"); +# endif +#elif @GNULIB_MDA_CHMOD@ +/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::chmod always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod _chmod +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (chmod); +#endif + + +#if @GNULIB_FCHMODAT@ +# if @REPLACE_FCHMODAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fchmodat +# define fchmodat rpl_fchmodat +# endif +_GL_FUNCDECL_RPL (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag)); +# else +# if !@HAVE_FCHMODAT@ +_GL_FUNCDECL_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchmodat, int, + (int fd, char const *file, mode_t mode, int flag)); +# endif +_GL_CXXALIASWARN (fchmodat); +#elif defined GNULIB_POSIXCHECK +# undef fchmodat +# if HAVE_RAW_DECL_FCHMODAT +_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FSTAT@ +# if @REPLACE_FSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstat +# define fstat rpl_fstat +# endif +_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); +# else +_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (fstat); +# endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstat +# define fstat fstat_used_without_requesting_gnulib_module_fstat +#elif @WINDOWS_64_BIT_ST_SIZE@ +/* Above, we define stat to _stati64. */ +# define fstat _fstati64 +#elif defined GNULIB_POSIXCHECK +# undef fstat +# if HAVE_RAW_DECL_FSTAT +_GL_WARN_ON_USE (fstat, "fstat has portability problems - " + "use gnulib module fstat for portability"); +# endif +#endif + + +#if @GNULIB_FSTATAT@ +# if @REPLACE_FSTATAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstatat +# define fstatat rpl_fstatat +# endif +_GL_FUNCDECL_RPL (fstatat, int, + (int fd, char const *restrict name, struct stat *restrict st, + int flags) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (fstatat, int, + (int fd, char const *restrict name, struct stat *restrict st, + int flags)); +# else +# if !@HAVE_FSTATAT@ +_GL_FUNCDECL_SYS (fstatat, int, + (int fd, char const *restrict name, struct stat *restrict st, + int flags) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (fstatat, int, + (int fd, char const *restrict name, struct stat *restrict st, + int flags)); +# endif +_GL_CXXALIASWARN (fstatat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstatat +# define fstatat fstatat_used_without_requesting_gnulib_module_fstatat +#elif defined GNULIB_POSIXCHECK +# undef fstatat +# if HAVE_RAW_DECL_FSTATAT +_GL_WARN_ON_USE (fstatat, "fstatat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_FUTIMENS@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens + implementation relies on futimesat, which on Solaris 10 makes an invocation + to futimens that is meant to invoke the libc's futimens(), not gnulib's + futimens(). */ +# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef futimens +# define futimens rpl_futimens +# endif +_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2])); +_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2])); +# else +# if !@HAVE_FUTIMENS@ +_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2])); +# endif +# if @HAVE_FUTIMENS@ +_GL_CXXALIASWARN (futimens); +# endif +#elif defined GNULIB_POSIXCHECK +# undef futimens +# if HAVE_RAW_DECL_FUTIMENS +_GL_WARN_ON_USE (futimens, "futimens is not portable - " + "use gnulib module futimens for portability"); +# endif +#endif + + +#if @GNULIB_GETUMASK@ +# if !@HAVE_GETUMASK@ +_GL_FUNCDECL_SYS (getumask, mode_t, (void)); +# endif +_GL_CXXALIAS_SYS (getumask, mode_t, (void)); +# if @HAVE_GETUMASK@ +_GL_CXXALIASWARN (getumask); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getumask +# if HAVE_RAW_DECL_GETUMASK +_GL_WARN_ON_USE (getumask, "getumask is not portable - " + "use gnulib module getumask for portability"); +# endif +#endif + + +#if @GNULIB_LCHMOD@ +/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME + denotes a symbolic link. */ +# if !@HAVE_LCHMOD@ || defined __hpux +_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode)); +_GL_CXXALIASWARN (lchmod); +#elif defined GNULIB_POSIXCHECK +# undef lchmod +# if HAVE_RAW_DECL_LCHMOD +_GL_WARN_ON_USE (lchmod, "lchmod is unportable - " + "use gnulib module lchmod for portability"); +# endif +#endif + + +#if @GNULIB_MKDIR@ +# if @REPLACE_MKDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkdir +# define mkdir rpl_mkdir +# endif +_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. + Additionally, it declares _mkdir (and depending on compile flags, an + alias mkdir), only in the nonstandard includes and , + which are included above. */ +# if !GNULIB_defined_rpl_mkdir +static int +rpl_mkdir (char const *name, mode_t mode) +{ + return _mkdir (name); +} +# define GNULIB_defined_rpl_mkdir 1 +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkdir +# define mkdir rpl_mkdir +# endif +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +# else +_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkdir); +#elif defined GNULIB_POSIXCHECK +# undef mkdir +# if HAVE_RAW_DECL_MKDIR +_GL_WARN_ON_USE (mkdir, "mkdir does not always support two parameters - " + "use gnulib module mkdir for portability"); +# endif +#elif @GNULIB_MDA_MKDIR@ +/* On native Windows, map 'mkdir' to '_mkdir', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::mkdir always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !GNULIB_defined_rpl_mkdir +static int +rpl_mkdir (char const *name, mode_t mode) +{ + return _mkdir (name); +} +# define GNULIB_defined_rpl_mkdir 1 +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkdir +# define mkdir rpl_mkdir +# endif +_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); +# else +_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkdir); +#endif + + +#if @GNULIB_MKDIRAT@ +# if !@HAVE_MKDIRAT@ +_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)); +_GL_CXXALIASWARN (mkdirat); +#elif defined GNULIB_POSIXCHECK +# undef mkdirat +# if HAVE_RAW_DECL_MKDIRAT +_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - " + "use gnulib module openat for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFO@ +# if @REPLACE_MKFIFO@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkfifo +# define mkfifo rpl_mkfifo +# endif +_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode)); +# else +# if !@HAVE_MKFIFO@ +_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkfifo); +#elif defined GNULIB_POSIXCHECK +# undef mkfifo +# if HAVE_RAW_DECL_MKFIFO +_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - " + "use gnulib module mkfifo for portability"); +# endif +#endif + + +#if @GNULIB_MKFIFOAT@ +# if @REPLACE_MKFIFOAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mkfifoat +# define mkfifoat rpl_mkfifoat +# endif +_GL_FUNCDECL_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode)); +# else +# if !@HAVE_MKFIFOAT@ +_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)); +# endif +_GL_CXXALIASWARN (mkfifoat); +#elif defined GNULIB_POSIXCHECK +# undef mkfifoat +# if HAVE_RAW_DECL_MKFIFOAT +_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_MKNOD@ +# if @REPLACE_MKNOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mknod +# define mknod rpl_mknod +# endif +_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# else +# if !@HAVE_MKNOD@ +_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on OSF/1 5.1, the third parameter is '...'. */ +_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev)); +# endif +_GL_CXXALIASWARN (mknod); +#elif defined GNULIB_POSIXCHECK +# undef mknod +# if HAVE_RAW_DECL_MKNOD +_GL_WARN_ON_USE (mknod, "mknod is not portable - " + "use gnulib module mknod for portability"); +# endif +#endif + + +#if @GNULIB_MKNODAT@ +# if @REPLACE_MKNODAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef mknodat +# define mknodat rpl_mknodat +# endif +_GL_FUNCDECL_RPL (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev)); +# else +# if !@HAVE_MKNODAT@ +_GL_FUNCDECL_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (mknodat, int, + (int fd, char const *file, mode_t mode, dev_t dev)); +# endif +_GL_CXXALIASWARN (mknodat); +#elif defined GNULIB_POSIXCHECK +# undef mknodat +# if HAVE_RAW_DECL_MKNODAT +_GL_WARN_ON_USE (mknodat, "mknodat is not portable - " + "use gnulib module mkfifoat for portability"); +# endif +#endif + + +#if @GNULIB_STAT@ +# if @REPLACE_STAT@ +# if !@GNULIB_OVERRIDES_STRUCT_STAT@ + /* We can't use the object-like #define stat rpl_stat, because of + struct stat. This means that rpl_stat will not be used if the user + does (stat)(a,b). Oh well. */ +# if defined _AIX && defined stat && defined _LARGE_FILES + /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, + so we have to replace stat64() instead of stat(). */ +# undef stat64 +# define stat64(name, st) rpl_stat (name, st) +# elif @WINDOWS_64_BIT_ST_SIZE@ + /* Above, we define stat to _stati64. */ +# if defined __MINGW32__ && defined _stati64 +# ifndef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined _stati64 +# ifdef _USE_32BIT_TIME_T + /* The system headers define _stati64 to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define _stati64 to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# else +# undef _stati64 +# define _stati64(name, st) rpl_stat (name, st) +# endif +# elif defined __MINGW32__ && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64. */ +# undef _stat64 +# define _stat64(name, st) rpl_stat (name, st) +# endif +# elif defined _MSC_VER && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32. */ +# undef _stat32 +# define _stat32(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64i32. */ +# undef _stat64i32 +# define _stat64i32(name, st) rpl_stat (name, st) +# endif +# else /* !(_AIX || __MINGW32__ || _MSC_VER) */ +# undef stat +# define stat(name, st) rpl_stat (name, st) +# endif /* !_LARGE_FILES */ +# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */ +_GL_EXTERN_C int stat (const char *restrict name, struct stat *restrict buf) + _GL_ARG_NONNULL ((1, 2)); +# endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +/* see above: + #define stat stat_used_without_requesting_gnulib_module_stat + */ +#elif defined GNULIB_POSIXCHECK +# undef stat +# if HAVE_RAW_DECL_STAT +_GL_WARN_ON_USE (stat, "stat is unportable - " + "use gnulib module stat for portability"); +# endif +#endif + + +#if @GNULIB_LSTAT@ +# if ! @HAVE_LSTAT@ +/* mingw does not support symlinks, therefore it does not have lstat. But + without links, stat does just fine. */ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lstat stat +# endif +_GL_CXXALIAS_RPL_1 (lstat, stat, int, + (const char *restrict name, struct stat *restrict buf)); +# elif @REPLACE_LSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lstat +# define lstat rpl_lstat +# endif +_GL_FUNCDECL_RPL (lstat, int, + (const char *restrict name, struct stat *restrict buf) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (lstat, int, + (const char *restrict name, struct stat *restrict buf)); +# else +_GL_CXXALIAS_SYS (lstat, int, + (const char *restrict name, struct stat *restrict buf)); +# endif +# if @HAVE_LSTAT@ +_GL_CXXALIASWARN (lstat); +# endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef lstat +# define lstat lstat_used_without_requesting_gnulib_module_lstat +#elif defined GNULIB_POSIXCHECK +# undef lstat +# if HAVE_RAW_DECL_LSTAT +_GL_WARN_ON_USE (lstat, "lstat is unportable - " + "use gnulib module lstat for portability"); +# endif +#endif + + +#if @GNULIB_MDA_UMASK@ +/* On native Windows, map 'umask' to '_umask', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::umask always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef umask +# define umask _umask +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (umask, mode_t, (mode_t mask)); +# else +_GL_CXXALIAS_SYS (umask, mode_t, (mode_t mask)); +# endif +_GL_CXXALIASWARN (umask); +#endif + + +#if @GNULIB_UTIMENSAT@ +/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat + implementation relies on futimesat, which on Solaris 10 makes an invocation + to utimensat that is meant to invoke the libc's utimensat(), not gnulib's + utimensat(). */ +# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef utimensat +# define utimensat rpl_utimensat +# endif +_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# else +# if !@HAVE_UTIMENSAT@ +_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name, + struct timespec const times[2], int flag)); +# endif +# if @HAVE_UTIMENSAT@ +_GL_CXXALIASWARN (utimensat); +# endif +#elif defined GNULIB_POSIXCHECK +# undef utimensat +# if HAVE_RAW_DECL_UTIMENSAT +_GL_WARN_ON_USE (utimensat, "utimensat is not portable - " + "use gnulib module utimensat for portability"); +# endif +#endif + + +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ +#endif diff --git a/cross/lib/sys_time.in.h b/cross/lib/sys_time.in.h new file mode 100644 index 00000000000..e833d551677 --- /dev/null +++ b/cross/lib/sys_time.in.h @@ -0,0 +1,224 @@ +/* Provide a more complete sys/time.h. + + Copyright (C) 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#ifndef _@GUARD_PREFIX@_SYS_TIME_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* On Cygwin and on many BSDish systems, includes itself + recursively via . + Simply delegate to the system's header in this case; it is a no-op. + Without this extra ifdef, the C++ gettimeofday declaration below + would be a forward declaration in gnulib's nested . */ +#if defined _CYGWIN_SYS_TIME_H || defined _SYS_TIME_H || defined _SYS_TIME_H_ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +#else + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_SYS_TIME_H@ +# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ +#endif + +#ifndef _@GUARD_PREFIX@_SYS_TIME_H +#define _@GUARD_PREFIX@_SYS_TIME_H + +#if ! @HAVE_SYS_TIME_H@ +# include +#endif + +/* On native Windows with MSVC, get the 'struct timeval' type. + Also, on native Windows with a 64-bit time_t, where we are overriding the + 'struct timeval' type, get all declarations of system functions whose + signature contains 'struct timeval'. */ +#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +#endif + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@ + +# if @REPLACE_STRUCT_TIMEVAL@ +# define timeval rpl_timeval +# endif + +# if !GNULIB_defined_struct_timeval +struct timeval +{ + time_t tv_sec; + long int tv_usec; +}; +# define GNULIB_defined_struct_timeval 1 +# endif + +#endif + +#ifdef __cplusplus +} +#endif + +#if @GNULIB_GETTIMEOFDAY@ +# if @REPLACE_GETTIMEOFDAY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gettimeofday +# define gettimeofday rpl_gettimeofday +# endif +_GL_FUNCDECL_RPL (gettimeofday, int, + (struct timeval *restrict, void *restrict) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gettimeofday, int, + (struct timeval *restrict, void *restrict)); +# else +# if !@HAVE_GETTIMEOFDAY@ +_GL_FUNCDECL_SYS (gettimeofday, int, + (struct timeval *restrict, void *restrict) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on glibc systems, by default, the second argument is + struct timezone *. */ +_GL_CXXALIAS_SYS_CAST (gettimeofday, int, + (struct timeval *restrict, void *restrict)); +# endif +_GL_CXXALIASWARN (gettimeofday); +# if defined __cplusplus && defined GNULIB_NAMESPACE +namespace GNULIB_NAMESPACE { + typedef ::timeval +# undef timeval + timeval; +# if @REPLACE_STRUCT_TIMEVAL@ +# define timeval rpl_timeval + typedef ::timeval timeval; +# endif +} +# endif +#elif defined GNULIB_POSIXCHECK +# undef gettimeofday +# if HAVE_RAW_DECL_GETTIMEOFDAY +_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - " + "use gnulib module gettimeofday for portability"); +# endif +#endif + +/* Hide some function declarations from . */ + +#if defined _MSC_VER && @HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_UNISTD_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef close +# define close close_used_without_including_unistd_h +# elif !defined __clang__ + _GL_WARN_ON_USE (close, + "close() used without including "); +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname gethostname_used_without_including_unistd_h +# else + _GL_WARN_ON_USE (gethostname, + "gethostname() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including "); +# endif +# endif +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ +#endif /* _CYGWIN_SYS_TIME_H */ +#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ diff --git a/cross/lib/sys_types.in.h b/cross/lib/sys_types.in.h new file mode 100644 index 00000000000..082a6c674de --- /dev/null +++ b/cross/lib/sys_types.in.h @@ -0,0 +1,106 @@ +/* Provide a more complete sys/types.h. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if defined _WIN32 && !defined __CYGWIN__ \ + && (defined __need_off_t || defined __need___off64_t \ + || defined __need_ssize_t || defined __need_time_t) + +/* Special invocation convention inside mingw header files. */ + +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ + +#else +/* Normal invocation convention. */ + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H + +/* The include_next requires a split double-inclusion guard. */ +# define _GL_INCLUDING_SYS_TYPES_H +#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ +# undef _GL_INCLUDING_SYS_TYPES_H + +#ifndef _@GUARD_PREFIX@_SYS_TYPES_H +#define _@GUARD_PREFIX@_SYS_TYPES_H + +/* Override off_t if Large File Support is requested on native Windows. */ +#if @WINDOWS_64_BIT_OFF_T@ +/* Same as int64_t in . */ +# if defined _MSC_VER +# define off_t __int64 +# else +# define off_t long long int +# endif +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_64_BIT_OFF_T 1 +#endif + +/* Override dev_t and ino_t if distinguishable inodes support is requested + on native Windows. */ +#if @WINDOWS_STAT_INODES@ + +# if @WINDOWS_STAT_INODES@ == 2 +/* Experimental, not useful in Windows 10. */ + +/* Define dev_t to a 64-bit type. */ +# if !defined GNULIB_defined_dev_t +typedef unsigned long long int rpl_dev_t; +# undef dev_t +# define dev_t rpl_dev_t +# define GNULIB_defined_dev_t 1 +# endif + +/* Define ino_t to a 128-bit type. */ +# if !defined GNULIB_defined_ino_t +/* MSVC does not have a 128-bit integer type. + GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ +typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# else /* @WINDOWS_STAT_INODES@ == 1 */ + +/* Define ino_t to a 64-bit type. */ +# if !defined GNULIB_defined_ino_t +typedef unsigned long long int rpl_ino_t; +# undef ino_t +# define ino_t rpl_ino_t +# define GNULIB_defined_ino_t 1 +# endif + +# endif + +/* Indicator, for gnulib internal purposes. */ +# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ + +#endif + +/* MSVC 9 defines size_t in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (defined _WIN32 && ! defined __CYGWIN__) && ! defined __GLIBC__ +# include +#endif + +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ +#endif /* __need_XXX */ diff --git a/cross/lib/tempname.c b/cross/lib/tempname.c new file mode 100644 index 00000000000..bf362db6e17 --- /dev/null +++ b/cross/lib/tempname.c @@ -0,0 +1,286 @@ +/* Copyright (C) 1991-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#if !_LIBC +# include +# include "tempname.h" +#endif + +#include + +#include +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif +#ifndef __GT_FILE +# define __GT_FILE 0 +# define __GT_DIR 1 +# define __GT_NOCREATE 2 +#endif +#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ + || GT_NOCREATE != __GT_NOCREATE) +# error report this to bug-gnulib@gnu.org +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#if _LIBC +# define struct_stat64 struct __stat64_t64 +#else +# define struct_stat64 struct stat +# define __gen_tempname gen_tempname +# define __mkdir mkdir +# define __open open +# define __lstat64_time64(file, buf) lstat (file, buf) +# define __getrandom getrandom +# define __clock_gettime64 clock_gettime +# define __timespec64 timespec +#endif + +/* Use getrandom if it works, falling back on a 64-bit linear + congruential generator that starts with Var's value + mixed in with a clock's low-order bits if available. */ +typedef uint_fast64_t random_value; +#define RANDOM_VALUE_MAX UINT_FAST64_MAX +#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ +#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) + +/* Return the result of mixing the entropy from R and S. + Assume that R and S are not particularly random, + and that the result should look randomish to an untrained eye. */ + +static random_value +mix_random_values (random_value r, random_value s) +{ + /* As this code is used only when high-quality randomness is neither + available nor necessary, there is no need for fancier polynomials + such as those in the Linux kernel's 'random' driver. */ + return (2862933555777941757 * r + 3037000493) ^ s; +} + +/* Set *R to a random value. + Return true if *R is set to high-quality value taken from getrandom. + Otherwise return false, falling back to a low-quality *R that might + depend on S. + + This function returns false only when getrandom fails. + On GNU systems this should happen only early in the boot process, + when the fallback should be good enough for programs using tempname + because any attacker likely has root privileges already. */ + +static bool +random_bits (random_value *r, random_value s) +{ + /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ + if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r) + return true; + + /* If getrandom did not work, use ersatz entropy based on low-order + clock bits. On GNU systems getrandom should fail only + early in booting, when ersatz should be good enough. + Do not use ASLR-based entropy, as that would leak ASLR info into + the resulting file name which is typically public. + + Of course we are in a state of sin here. */ + + random_value v = s; + +#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME) + struct __timespec64 tv; + __clock_gettime64 (CLOCK_REALTIME, &tv); + v = mix_random_values (v, tv.tv_sec); + v = mix_random_values (v, tv.tv_nsec); +#endif + + *r = mix_random_values (v, clock ()); + return false; +} + +#if _LIBC +static int try_tempname_len (char *, int, void *, int (*) (char *, void *), + size_t); +#endif + +static int +try_file (char *tmpl, void *flags) +{ + int *openflags = flags; + return __open (tmpl, + (*openflags & ~O_ACCMODE) + | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +} + +static int +try_dir (char *tmpl, _GL_UNUSED void *flags) +{ + return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); +} + +static int +try_nocreate (char *tmpl, _GL_UNUSED void *flags) +{ + struct_stat64 st; + + if (__lstat64_time64 (tmpl, &st) == 0 || errno == EOVERFLOW) + __set_errno (EEXIST); + return errno == ENOENT ? 0 : -1; +} + +/* These are the characters used in temporary file names. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s, + possibly with a suffix). + The name constructed does not exist at the time of the call to + this function. TMPL is overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + __GT_DIR: create a directory, which will be mode 0700. + + */ +#ifdef _LIBC +static +#endif +int +gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, + size_t x_suffix_len) +{ + static int (*const tryfunc[]) (char *, void *) = + { + [__GT_FILE] = try_file, + [__GT_DIR] = try_dir, + [__GT_NOCREATE] = try_nocreate + }; + return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind], + x_suffix_len); +} + +#ifdef _LIBC +static +#endif +int +try_tempname_len (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *), size_t x_suffix_len) +{ + size_t len; + char *XXXXXX; + unsigned int count; + int fd = -1; + int save_errno = errno; + + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all of these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. + This value requires that X_SUFFIX_LEN be at least 3. */ +#define ATTEMPTS_MIN (62 * 62 * 62) + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ +#if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; +#else + unsigned int attempts = ATTEMPTS_MIN; +#endif + + /* A random variable. */ + random_value v = 0; + + /* A value derived from the random variable, and how many random + base-62 digits can currently be extracted from VDIGBUF. */ + random_value vdigbuf; + int vdigits = 0; + + /* Least biased value for V. If V is less than this, V can generate + BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */ + random_value const biased_min + = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; + + len = strlen (tmpl); + if (len < x_suffix_len + suffixlen + || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; + + for (count = 0; count < attempts; ++count) + { + for (size_t i = 0; i < x_suffix_len; i++) + { + if (vdigits == 0) + { + /* Worry about bias only if the bits are high quality. */ + while (random_bits (&v, v) && biased_min <= v) + continue; + + vdigbuf = v; + vdigits = BASE_62_DIGITS; + } + + XXXXXX[i] = letters[vdigbuf % 62]; + vdigbuf /= 62; + vdigits--; + } + + fd = tryfunc (tmpl, args); + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} + +int +__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +{ + return gen_tempname_len (tmpl, suffixlen, flags, kind, 6); +} + +#if !_LIBC +int +try_tempname (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *)) +{ + return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6); +} +#endif diff --git a/cross/lib/tempname.h b/cross/lib/tempname.h new file mode 100644 index 00000000000..36a51381548 --- /dev/null +++ b/cross/lib/tempname.h @@ -0,0 +1,72 @@ +/* Create a temporary file or directory. + + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* header written by Eric Blake */ + +#ifndef GL_TEMPNAME_H +# define GL_TEMPNAME_H + +# include + +# ifdef __GT_FILE +# define GT_FILE __GT_FILE +# define GT_DIR __GT_DIR +# define GT_NOCREATE __GT_NOCREATE +# else +# define GT_FILE 0 +# define GT_DIR 1 +# define GT_NOCREATE 2 +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + The name constructed does not exist at the time of the call to + gen_tempname. TMPL is overwritten with the result. + + KIND may be one of: + GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + GT_FILE: create a large file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + GT_DIR: create a directory, which will be mode 0700. + + */ +extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); +/* Similar, except X_SUFFIX_LEN gives the number of Xs. */ +extern int gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, + size_t x_suffix_len); + +/* Similar to gen_tempname, but TRYFUNC is called for each temporary + name to try. If TRYFUNC returns a non-negative number, TRY_GEN_TEMPNAME + returns with this value. Otherwise, if errno is set to EEXIST, another + name is tried, or else TRY_GEN_TEMPNAME returns -1. */ +extern int try_tempname (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *)); +/* Similar, except X_SUFFIX_LEN gives the number of Xs. */ +extern int try_tempname_len (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *), + size_t x_suffix_len); + +#ifdef __cplusplus +} +#endif + +#endif /* GL_TEMPNAME_H */ diff --git a/cross/lib/time-internal.h b/cross/lib/time-internal.h new file mode 100644 index 00000000000..51423c94ca9 --- /dev/null +++ b/cross/lib/time-internal.h @@ -0,0 +1,49 @@ +/* Time internal interface + + Copyright 2015-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +/* A time zone rule. */ +struct tm_zone +{ + /* More abbreviations, should they be needed. Their TZ_IS_SET + members are zero. */ + struct tm_zone *next; + +#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE + /* Copies of recent strings taken from tzname[0] and tzname[1]. + The copies are in ABBRS, so that they survive tzset. Null if unknown. */ + char *tzname_copy[2]; +#endif + + /* If nonzero, the rule represents the TZ environment variable set + to the first "abbreviation" (this may be the empty string). + Otherwise, it represents an unset TZ. */ + char tz_is_set; + + /* A sequence of null-terminated strings packed next to each other. + The strings are followed by an extra null byte. If TZ_IS_SET, + there must be at least one string and the first string (which is + actually a TZ environment value) may be empty. Otherwise all + strings must be nonempty. + + Abbreviations are stored here because otherwise the values of + tm_zone and/or tzname would be dead after changing TZ and calling + tzset. Abbreviations never move once allocated, and are live + until tzfree is called. */ + char abbrs[FLEXIBLE_ARRAY_MEMBER]; +}; diff --git a/cross/lib/time.in.h b/cross/lib/time.in.h new file mode 100644 index 00000000000..50c9b30b6b3 --- /dev/null +++ b/cross/lib/time.in.h @@ -0,0 +1,457 @@ +/* A more-standard . + + Copyright (C) 2007-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +/* Don't get in the way of glibc when it includes time.h merely to + declare a few standard symbols, rather than to declare all the + symbols. (However, skip this for MinGW as it treats __need_time_t + incompatibly.) Also, Solaris 8 eventually includes itself + recursively; if that is happening, just include the system + without adding our own declarations. */ +#if (((defined __need_time_t || defined __need_clock_t \ + || defined __need_timespec) \ + && !defined __MINGW32__) \ + || defined _@GUARD_PREFIX@_TIME_H) + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +#else + +# define _@GUARD_PREFIX@_TIME_H + +/* mingw's provides the functions asctime_r, ctime_r, gmtime_r, + localtime_r only if or has been included before. */ +# if defined __MINGW32__ +# include +# endif + +# @INCLUDE_NEXT@ @NEXT_TIME_H@ + +/* NetBSD 5.0 mis-defines NULL. */ +# include + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + +/* Some systems don't define struct timespec (e.g., AIX 4.1). + Or they define it with the wrong member names or define it in + (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, + but the pthreads-win32 library defines it in . */ +# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ +# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +# include +# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +# include +# elif @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +# include +# else + +# ifdef __cplusplus +extern "C" { +# endif + +# if !GNULIB_defined_struct_timespec +# undef timespec +# define timespec rpl_timespec +struct timespec +{ + time_t tv_sec; + long int tv_nsec; +}; +# define GNULIB_defined_struct_timespec 1 +# endif + +# ifdef __cplusplus +} +# endif + +# endif +# endif + +# if !GNULIB_defined_struct_time_t_must_be_integral +/* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html + requires time_t to be an integer type, even though C99 permits floating + point. We don't know of any implementation that uses floating + point, and it is much easier to write code that doesn't have to + worry about that corner case, so we force the issue. */ +struct __time_t_must_be_integral { + unsigned int __floating_time_t_unsupported : (time_t) 1; +}; +# define GNULIB_defined_struct_time_t_must_be_integral 1 +# endif + +/* Define TIME_UTC, a positive integer constant used for timespec_get(). */ +# if ! @TIME_H_DEFINES_TIME_UTC@ +# if !GNULIB_defined_TIME_UTC +# define TIME_UTC 1 +# define GNULIB_defined_TIME_UTC 1 +# endif +# endif + +/* Set *TS to the current time, and return BASE. + Upon failure, return 0. */ +# if @GNULIB_TIMESPEC_GET@ +# if ! @HAVE_TIMESPEC_GET@ +_GL_FUNCDECL_SYS (timespec_get, int, (struct timespec *ts, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (timespec_get, int, (struct timespec *ts, int base)); +_GL_CXXALIASWARN (timespec_get); +# endif + +/* Set *TS to the current time resolution, and return BASE. + Upon failure, return 0. */ +# if @GNULIB_TIMESPEC_GETRES@ +# if ! @HAVE_TIMESPEC_GETRES@ +_GL_FUNCDECL_SYS (timespec_getres, int, (struct timespec *ts, int base) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (timespec_getres, int, (struct timespec *ts, int base)); +_GL_CXXALIASWARN (timespec_getres); +# endif + +/* Sleep for at least RQTP seconds unless interrupted, If interrupted, + return -1 and store the remaining time into RMTP. See + . */ +# if @GNULIB_NANOSLEEP@ +# if @REPLACE_NANOSLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define nanosleep rpl_nanosleep +# endif +_GL_FUNCDECL_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# else +# if ! @HAVE_NANOSLEEP@ +_GL_FUNCDECL_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (nanosleep, int, + (struct timespec const *__rqtp, struct timespec *__rmtp)); +# endif +_GL_CXXALIASWARN (nanosleep); +# endif + +/* Initialize time conversion information. */ +# if @GNULIB_TZSET@ +# if @REPLACE_TZSET@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tzset +# define tzset rpl_tzset +# endif +_GL_FUNCDECL_RPL (tzset, void, (void)); +_GL_CXXALIAS_RPL (tzset, void, (void)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tzset +# define tzset _tzset +# endif +_GL_CXXALIAS_MDA (tzset, void, (void)); +# else +_GL_CXXALIAS_SYS (tzset, void, (void)); +# endif +_GL_CXXALIASWARN (tzset); +# elif @GNULIB_MDA_TZSET@ +/* On native Windows, map 'tzset' to '_tzset', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::tzset always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef tzset +# define tzset _tzset +# endif +_GL_CXXALIAS_MDA (tzset, void, (void)); +# else +_GL_CXXALIAS_SYS (tzset, void, (void)); +# endif +_GL_CXXALIASWARN (tzset); +# endif + +/* Return the 'time_t' representation of TP and normalize TP. */ +# if @GNULIB_MKTIME@ +# if @REPLACE_MKTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define mktime rpl_mktime +# endif +_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); +# else +_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (mktime); +# endif +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + and + . */ +# if @GNULIB_TIME_R@ +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime_r +# define localtime_r rpl_localtime_r +# endif +_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (localtime_r); +# endif +# if @REPLACE_LOCALTIME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime_r +# define gmtime_r rpl_gmtime_r +# endif +_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# else +# if ! @HAVE_DECL_LOCALTIME_R@ +_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, + struct tm *restrict __result)); +# endif +# if @HAVE_DECL_LOCALTIME_R@ +_GL_CXXALIASWARN (gmtime_r); +# endif +# endif + +/* Convert TIMER to RESULT, assuming local time and UTC respectively. See + and + . */ +# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@ +# if @REPLACE_LOCALTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef localtime +# define localtime rpl_localtime +# endif +_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (localtime); +# endif +# endif + +# if 0 || @REPLACE_GMTIME@ +# if @REPLACE_GMTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gmtime +# define gmtime rpl_gmtime +# endif +_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); +# else +_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); +# endif +_GL_CXXALIASWARN (gmtime); +# endif + +/* Parse BUF as a timestamp, assuming FORMAT specifies its layout, and store + the resulting broken-down time into TM. See + . */ +# if @GNULIB_STRPTIME@ +# if ! @HAVE_STRPTIME@ +_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm) + _GL_ARG_NONNULL ((1, 2, 3))); +# endif +_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, + char const *restrict __format, + struct tm *restrict __tm)); +_GL_CXXALIASWARN (strptime); +# endif + +/* Convert *TP to a date and time string. See + . */ +# if @GNULIB_CTIME@ +# if @REPLACE_CTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define ctime rpl_ctime +# endif +_GL_ATTRIBUTE_DEPRECATED +_GL_FUNCDECL_RPL (ctime, char *, (time_t const *__tp) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp)); +# else +_GL_CXXALIAS_SYS (ctime, char *, (time_t const *__tp)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (ctime); +# endif +# endif + +/* Convert *TP to a date and time string. See + . */ +# if @GNULIB_STRFTIME@ +# if @REPLACE_STRFTIME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strftime rpl_strftime +# endif +_GL_FUNCDECL_RPL (strftime, size_t, + (char *restrict __buf, size_t __bufsize, + const char *restrict __fmt, const struct tm *restrict __tp) + _GL_ARG_NONNULL ((1, 3, 4))); +_GL_CXXALIAS_RPL (strftime, size_t, + (char *restrict __buf, size_t __bufsize, + const char *restrict __fmt, const struct tm *restrict __tp)); +# else +_GL_CXXALIAS_SYS (strftime, size_t, + (char *restrict __buf, size_t __bufsize, + const char *restrict __fmt, const struct tm *restrict __tp)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strftime); +# endif +# endif + +# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@ +/* Functions that use a first-class time zone data type, instead of + relying on an implicit global time zone. + Inspired by NetBSD. */ + +/* Represents a time zone. + (timezone_t) NULL stands for UTC. */ +typedef struct tm_zone *timezone_t; + +/* tzalloc (name) + Returns a time zone object for the given time zone NAME. This object + represents the time zone that other functions would use it the TZ + environment variable was set to NAME. + If NAME is NULL, the result represents the time zone that other functions + would use it the TZ environment variable was unset. + May return NULL if NAME is invalid (this is platform dependent) or + upon memory allocation failure. */ +_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name)); +_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name)); + +/* tzfree (tz) + Frees a time zone object. + The argument must have been returned by tzalloc(). */ +_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz)); +_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz)); + +/* localtime_rz (tz, &t, &result) + Converts an absolute time T to a broken-down time RESULT, assuming the + time zone TZ. + This function is like 'localtime_r', but relies on the argument TZ instead + of an implicit global time zone. */ +_GL_FUNCDECL_SYS (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_SYS (localtime_rz, struct tm *, + (timezone_t __tz, time_t const *restrict __timer, + struct tm *restrict __result)); + +/* mktime_z (tz, &tm) + Normalizes the broken-down time TM and converts it to an absolute time, + assuming the time zone TZ. Returns the absolute time. + This function is like 'mktime', but relies on the argument TZ instead + of an implicit global time zone. */ +_GL_FUNCDECL_SYS (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __tm) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_SYS (mktime_z, time_t, + (timezone_t __tz, struct tm *restrict __tm)); + +/* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z' + in the 'tm_zone' member of 'struct tm') are valid as long as + - the 'struct tm' argument is not destroyed or overwritten, + and + - the 'timezone_t' argument is not freed through tzfree(). */ + +# endif + +/* Convert TM to a time_t value, assuming UTC. */ +# if @GNULIB_TIMEGM@ +# if @REPLACE_TIMEGM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef timegm +# define timegm rpl_timegm +# endif +_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); +# else +# if ! @HAVE_TIMEGM@ +_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); +# endif +_GL_CXXALIASWARN (timegm); +# endif + +/* Encourage applications to avoid unsafe functions that can overrun + buffers when given outlandish struct tm values. Portable + applications should use strftime (or even sprintf) instead. */ +# if defined GNULIB_POSIXCHECK +# undef asctime +_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef asctime_r +# if HAVE_RAW_DECL_ASCTIME_R +_GL_WARN_ON_USE (asctime_r, "asctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime +_GL_WARN_ON_USE (ctime, "ctime can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# if defined GNULIB_POSIXCHECK +# undef ctime_r +# if HAVE_RAW_DECL_CTIME_R +_GL_WARN_ON_USE (ctime_r, "ctime_r can overrun buffers in some cases - " + "better use strftime (or even sprintf) instead"); +# endif +# endif + +#endif diff --git a/cross/lib/time_r.c b/cross/lib/time_r.c new file mode 100644 index 00000000000..97be4fd0544 --- /dev/null +++ b/cross/lib/time_r.c @@ -0,0 +1,44 @@ +/* Reentrant time functions like localtime_r. + + Copyright (C) 2003, 2006-2007, 2010-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#include + +static struct tm * +copy_tm_result (struct tm *dest, struct tm const *src) +{ + if (! src) + return 0; + *dest = *src; + return dest; +} + + +struct tm * +gmtime_r (time_t const * restrict t, struct tm * restrict tp) +{ + return copy_tm_result (tp, gmtime (t)); +} + +struct tm * +localtime_r (time_t const * restrict t, struct tm * restrict tp) +{ + return copy_tm_result (tp, localtime (t)); +} diff --git a/cross/lib/time_rz.c b/cross/lib/time_rz.c new file mode 100644 index 00000000000..da0d57b8b1a --- /dev/null +++ b/cross/lib/time_rz.c @@ -0,0 +1,316 @@ +/* Time zone functions such as tzalloc and localtime_rz + + Copyright 2015-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +/* Although this module is not thread-safe, any races should be fairly + rare and reasonably benign. For complete thread-safety, use a C + library with a working timezone_t type, so that this module is not + needed. */ + +#include + +#include + +#include +#include +#include +#include + +#include "flexmember.h" +#include "idx.h" +#include "time-internal.h" + +/* The approximate size to use for small allocation requests. This is + the largest "small" request for the GNU C library malloc. */ +enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; + +/* Minimum size of the ABBRS member of struct tm_zone. ABBRS is larger + only in the unlikely case where an abbreviation longer than this is + used. */ +enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; + +/* Magic cookie timezone_t value, for local time. It differs from + NULL and from all other timezone_t values. Only the address + matters; the pointer is never dereferenced. */ +static timezone_t const local_tz = (timezone_t) 1; + +/* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this + includes its trailing null byte). Append an extra null byte to + mark the end of ABBRS. */ +static void +extend_abbrs (char *abbrs, char const *abbr, size_t abbr_size) +{ + memcpy (abbrs, abbr, abbr_size); + abbrs[abbr_size] = '\0'; +} + +/* Return a newly allocated time zone for NAME, or NULL on failure. + A null NAME stands for wall clock time (which is like unset TZ). */ +timezone_t +tzalloc (char const *name) +{ + size_t name_size = name ? strlen (name) + 1 : 0; + size_t abbr_size = name_size < ABBR_SIZE_MIN ? ABBR_SIZE_MIN : name_size + 1; + timezone_t tz = malloc (FLEXSIZEOF (struct tm_zone, abbrs, abbr_size)); + if (tz) + { + tz->next = NULL; +#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE + tz->tzname_copy[0] = tz->tzname_copy[1] = NULL; +#endif + tz->tz_is_set = !!name; + tz->abbrs[0] = '\0'; + if (name) + extend_abbrs (tz->abbrs, name, name_size); + } + return tz; +} + +/* Save into TZ any nontrivial time zone abbreviation used by TM, and + update *TM (if HAVE_STRUCT_TM_TM_ZONE) or *TZ (if + !HAVE_STRUCT_TM_TM_ZONE && HAVE_TZNAME) if they use the abbreviation. + Return true if successful, false (setting errno) otherwise. */ +static bool +save_abbr (timezone_t tz, struct tm *tm) +{ +#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME + char const *zone = NULL; + char *zone_copy = (char *) ""; + +# if HAVE_TZNAME + int tzname_index = -1; +# endif + +# if HAVE_STRUCT_TM_TM_ZONE + zone = tm->tm_zone; +# endif + +# if HAVE_TZNAME + if (! (zone && *zone) && 0 <= tm->tm_isdst) + { + tzname_index = tm->tm_isdst != 0; + zone = tzname[tzname_index]; + } +# endif + + /* No need to replace null zones, or zones within the struct tm. */ + if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1))) + return true; + + if (*zone) + { + zone_copy = tz->abbrs; + + while (strcmp (zone_copy, zone) != 0) + { + if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set))) + { + idx_t zone_size = strlen (zone) + 1; + if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy) + extend_abbrs (zone_copy, zone, zone_size); + else + { + tz = tz->next = tzalloc (zone); + if (!tz) + return false; + tz->tz_is_set = 0; + zone_copy = tz->abbrs; + } + break; + } + + zone_copy += strlen (zone_copy) + 1; + if (!*zone_copy && tz->next) + { + tz = tz->next; + zone_copy = tz->abbrs; + } + } + } + + /* Replace the zone name so that its lifetime matches that of TZ. */ +# if HAVE_STRUCT_TM_TM_ZONE + tm->tm_zone = zone_copy; +# else + if (0 <= tzname_index) + tz->tzname_copy[tzname_index] = zone_copy; +# endif +#endif + + return true; +} + +/* Free a time zone. */ +void +tzfree (timezone_t tz) +{ + if (tz != local_tz) + while (tz) + { + timezone_t next = tz->next; + free (tz); + tz = next; + } +} + +/* Get and set the TZ environment variable. These functions can be + overridden by programs like Emacs that manage their own environment. */ + +#ifndef getenv_TZ +static char * +getenv_TZ (void) +{ + return getenv ("TZ"); +} +#endif + +#ifndef setenv_TZ +static int +setenv_TZ (char const *tz) +{ + return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ"); +} +#endif + +/* Change the environment to match the specified timezone_t value. + Return true if successful, false (setting errno) otherwise. */ +static bool +change_env (timezone_t tz) +{ + if (setenv_TZ (tz->tz_is_set ? tz->abbrs : NULL) != 0) + return false; + tzset (); + return true; +} + +/* Temporarily set the time zone to TZ, which must not be null. + Return LOCAL_TZ if the time zone setting is already correct. + Otherwise return a newly allocated time zone representing the old + setting, or NULL (setting errno) on failure. */ +static timezone_t +set_tz (timezone_t tz) +{ + char *env_tz = getenv_TZ (); + if (env_tz + ? tz->tz_is_set && strcmp (tz->abbrs, env_tz) == 0 + : !tz->tz_is_set) + return local_tz; + else + { + timezone_t old_tz = tzalloc (env_tz); + if (!old_tz) + return old_tz; + if (! change_env (tz)) + { + int saved_errno = errno; + tzfree (old_tz); + errno = saved_errno; + return NULL; + } + return old_tz; + } +} + +/* Restore an old setting returned by set_tz. It must not be null. + Return true (preserving errno) if successful, false (setting errno) + otherwise. */ +static bool +revert_tz (timezone_t tz) +{ + if (tz == local_tz) + return true; + else + { + int saved_errno = errno; + bool ok = change_env (tz); + if (!ok) + saved_errno = errno; + tzfree (tz); + errno = saved_errno; + return ok; + } +} + +/* Use time zone TZ to compute localtime_r (T, TM). */ +struct tm * +localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) +{ +#ifdef HAVE_LOCALTIME_INFLOOP_BUG + /* The -67768038400665599 comes from: + https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html + On affected platforms the greatest POSIX-compatible time_t value + that could return nonnull is 67768036191766798 (when + TZ="XXX24:59:59" it resolves to the year 2**31 - 1 + 1900, on + 12-31 at 23:59:59), so test for that too while we're in the + neighborhood. */ + if (! (-67768038400665599 <= *t && *t <= 67768036191766798)) + { + errno = EOVERFLOW; + return NULL; + } +#endif + + if (!tz) + return gmtime_r (t, tm); + else + { + timezone_t old_tz = set_tz (tz); + if (old_tz) + { + bool abbr_saved = localtime_r (t, tm) && save_abbr (tz, tm); + if (revert_tz (old_tz) && abbr_saved) + return tm; + } + return NULL; + } +} + +/* Use time zone TZ to compute mktime (TM). */ +time_t +mktime_z (timezone_t tz, struct tm *tm) +{ + if (!tz) + return timegm (tm); + else + { + timezone_t old_tz = set_tz (tz); + if (old_tz) + { + struct tm tm_1; + tm_1.tm_sec = tm->tm_sec; + tm_1.tm_min = tm->tm_min; + tm_1.tm_hour = tm->tm_hour; + tm_1.tm_mday = tm->tm_mday; + tm_1.tm_mon = tm->tm_mon; + tm_1.tm_year = tm->tm_year; + tm_1.tm_yday = -1; + tm_1.tm_isdst = tm->tm_isdst; + time_t t = mktime (&tm_1); + bool ok = 0 <= tm_1.tm_yday; +#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME + ok = ok && save_abbr (tz, &tm_1); +#endif + if (revert_tz (old_tz) && ok) + { + *tm = tm_1; + return t; + } + } + return -1; + } +} diff --git a/cross/lib/timegm.c b/cross/lib/timegm.c new file mode 100644 index 00000000000..b47025a0545 --- /dev/null +++ b/cross/lib/timegm.c @@ -0,0 +1,58 @@ +/* Convert UTC calendar time to simple time. Like mktime but assumes UTC. + + Copyright (C) 1994-2023 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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. + + The GNU C 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 the GNU C Library; if not, see + . */ + +#ifndef _LIBC +# include +#endif + +#include +#include + +#include "mktime-internal.h" + +__time64_t +__timegm64 (struct tm *tmp) +{ + static mktime_offset_t gmtime_offset; + tmp->tm_isdst = 0; + return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset); +} + +#if defined _LIBC && __TIMESIZE != 64 + +libc_hidden_def (__timegm64) + +time_t +timegm (struct tm *tmp) +{ + struct tm tm = *tmp; + __time64_t t = __timegm64 (&tm); + if (in_time_t_range (t)) + { + *tmp = tm; + return t; + } + else + { + __set_errno (EOVERFLOW); + return -1; + } +} + +#endif diff --git a/cross/lib/timespec-add.c b/cross/lib/timespec-add.c new file mode 100644 index 00000000000..cb3017803b4 --- /dev/null +++ b/cross/lib/timespec-add.c @@ -0,0 +1,65 @@ +/* Add two struct timespec values. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +/* Return the sum of two timespec values A and B. On overflow, return + an extremal value. This assumes 0 <= tv_nsec < TIMESPEC_HZ. */ + +#include +#include "timespec.h" + +#include "intprops.h" + +struct timespec +timespec_add (struct timespec a, struct timespec b) +{ + time_t rs = a.tv_sec; + time_t bs = b.tv_sec; + int ns = a.tv_nsec + b.tv_nsec; + int nsd = ns - TIMESPEC_HZ; + int rns = ns; + + if (0 <= nsd) + { + rns = nsd; + time_t bs1; + if (!INT_ADD_WRAPV (bs, 1, &bs1)) + bs = bs1; + else if (rs < 0) + rs++; + else + goto high_overflow; + } + + if (INT_ADD_WRAPV (rs, bs, &rs)) + { + if (bs < 0) + { + rs = TYPE_MINIMUM (time_t); + rns = 0; + } + else + { + high_overflow: + rs = TYPE_MAXIMUM (time_t); + rns = TIMESPEC_HZ - 1; + } + } + + return make_timespec (rs, rns); +} diff --git a/cross/lib/timespec-sub.c b/cross/lib/timespec-sub.c new file mode 100644 index 00000000000..822c2831089 --- /dev/null +++ b/cross/lib/timespec-sub.c @@ -0,0 +1,65 @@ +/* Subtract two struct timespec values. + + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Paul Eggert. */ + +/* Return the difference between two timespec values A and B. On + overflow, return an extremal value. This assumes 0 <= tv_nsec < + TIMESPEC_HZ. */ + +#include +#include "timespec.h" + +#include "intprops.h" + +struct timespec +timespec_sub (struct timespec a, struct timespec b) +{ + time_t rs = a.tv_sec; + time_t bs = b.tv_sec; + int ns = a.tv_nsec - b.tv_nsec; + int rns = ns; + + if (ns < 0) + { + rns = ns + TIMESPEC_HZ; + time_t bs1; + if (!INT_ADD_WRAPV (bs, 1, &bs1)) + bs = bs1; + else if (- TYPE_SIGNED (time_t) < rs) + rs--; + else + goto low_overflow; + } + + if (INT_SUBTRACT_WRAPV (rs, bs, &rs)) + { + if (0 < bs) + { + low_overflow: + rs = TYPE_MINIMUM (time_t); + rns = 0; + } + else + { + rs = TYPE_MAXIMUM (time_t); + rns = TIMESPEC_HZ - 1; + } + } + + return make_timespec (rs, rns); +} diff --git a/cross/lib/timespec.c b/cross/lib/timespec.c new file mode 100644 index 00000000000..5f7ffbdd45f --- /dev/null +++ b/cross/lib/timespec.c @@ -0,0 +1,21 @@ +/* Inline functions for . + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define _GL_TIMESPEC_INLINE _GL_EXTERN_INLINE +#include "timespec.h" diff --git a/cross/lib/timespec.h b/cross/lib/timespec.h new file mode 100644 index 00000000000..ba78647f09a --- /dev/null +++ b/cross/lib/timespec.h @@ -0,0 +1,102 @@ +/* timespec -- System time interface + + Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2023 Free Software + Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +#if ! defined TIMESPEC_H +#define TIMESPEC_H + +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_TIMESPEC_INLINE +# define _GL_TIMESPEC_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "arg-nonnull.h" + +/* Inverse resolution of timespec timestamps (in units per second), + and log base 10 of the inverse resolution. */ + +enum { TIMESPEC_HZ = 1000000000 }; +enum { LOG10_TIMESPEC_HZ = 9 }; + +/* Obsolescent names for backward compatibility. + They are misnomers, because TIMESPEC_RESOLUTION is not a resolution. */ + +enum { TIMESPEC_RESOLUTION = TIMESPEC_HZ }; +enum { LOG10_TIMESPEC_RESOLUTION = LOG10_TIMESPEC_HZ }; + +/* Return a timespec with seconds S and nanoseconds NS. */ + +_GL_TIMESPEC_INLINE struct timespec +make_timespec (time_t s, long int ns) +{ + struct timespec r; + r.tv_sec = s; + r.tv_nsec = ns; + return r; +} + +/* Return negative, zero, positive if A < B, A == B, A > B, respectively. */ + +_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE +timespec_cmp (struct timespec a, struct timespec b) +{ + return 2 * _GL_CMP (a.tv_sec, b.tv_sec) + _GL_CMP (a.tv_nsec, b.tv_nsec); +} + +/* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be + nonnegative. */ +_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE +timespec_sign (struct timespec a) +{ + return _GL_CMP (a.tv_sec, 0) + (!a.tv_sec & !!a.tv_nsec); +} + +struct timespec timespec_add (struct timespec, struct timespec) + _GL_ATTRIBUTE_CONST; +struct timespec timespec_sub (struct timespec, struct timespec) + _GL_ATTRIBUTE_CONST; +struct timespec dtotimespec (double) + _GL_ATTRIBUTE_CONST; + +/* Return an approximation to A, of type 'double'. */ +_GL_TIMESPEC_INLINE double +timespectod (struct timespec a) +{ + return a.tv_sec + a.tv_nsec / 1e9; +} + +long int gettime_res (void); +struct timespec current_timespec (void); +void gettime (struct timespec *) _GL_ARG_NONNULL ((1)); +int settime (struct timespec const *) _GL_ARG_NONNULL ((1)); + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif diff --git a/cross/lib/u64.c b/cross/lib/u64.c new file mode 100644 index 00000000000..ca088b45463 --- /dev/null +++ b/cross/lib/u64.c @@ -0,0 +1,22 @@ +/* uint64_t-like operations that work even on hosts lacking uint64_t + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define _GL_U64_INLINE _GL_EXTERN_INLINE +#include "u64.h" +typedef int dummy; diff --git a/cross/lib/u64.h b/cross/lib/u64.h new file mode 100644 index 00000000000..0353ad4d9af --- /dev/null +++ b/cross/lib/u64.h @@ -0,0 +1,179 @@ +/* uint64_t-like operations that work even on hosts lacking uint64_t + + Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_U64_INLINE +# define _GL_U64_INLINE _GL_INLINE +#endif + +/* Return X rotated left by N bits, where 0 < N < 64. */ +#define u64rol(x, n) u64or (u64shl (x, n), u64shr (x, 64 - n)) + +#ifdef UINT64_MAX + +/* Native implementations are trivial. See below for comments on what + these operations do. */ +typedef uint64_t u64; +# define u64hilo(hi, lo) ((u64) (((u64) (hi) << 32) + (lo))) +# define u64init(hi, lo) u64hilo (hi, lo) +# define u64lo(x) ((u64) (x)) +# define u64size(x) u64lo (x) +# define u64lt(x, y) ((x) < (y)) +# define u64and(x, y) ((x) & (y)) +# define u64or(x, y) ((x) | (y)) +# define u64xor(x, y) ((x) ^ (y)) +# define u64plus(x, y) ((x) + (y)) +# define u64shl(x, n) ((x) << (n)) +# define u64shr(x, n) ((x) >> (n)) + +#else + +/* u64 is a 64-bit unsigned integer value. + u64init (HI, LO), is like u64hilo (HI, LO), but for use in + initializer contexts. */ +# ifdef WORDS_BIGENDIAN +typedef struct { uint32_t hi, lo; } u64; +# define u64init(hi, lo) { hi, lo } +# else +typedef struct { uint32_t lo, hi; } u64; +# define u64init(hi, lo) { lo, hi } +# endif + +/* Given the high and low-order 32-bit quantities HI and LO, return a u64 + value representing (HI << 32) + LO. */ +_GL_U64_INLINE u64 +u64hilo (uint32_t hi, uint32_t lo) +{ + u64 r; + r.hi = hi; + r.lo = lo; + return r; +} + +/* Return a u64 value representing LO. */ +_GL_U64_INLINE u64 +u64lo (uint32_t lo) +{ + u64 r; + r.hi = 0; + r.lo = lo; + return r; +} + +/* Return a u64 value representing SIZE. */ +_GL_U64_INLINE u64 +u64size (size_t size) +{ + u64 r; + r.hi = size >> 31 >> 1; + r.lo = size; + return r; +} + +/* Return X < Y. */ +_GL_U64_INLINE int +u64lt (u64 x, u64 y) +{ + return x.hi < y.hi || (x.hi == y.hi && x.lo < y.lo); +} + +/* Return X & Y. */ +_GL_U64_INLINE u64 +u64and (u64 x, u64 y) +{ + u64 r; + r.hi = x.hi & y.hi; + r.lo = x.lo & y.lo; + return r; +} + +/* Return X | Y. */ +_GL_U64_INLINE u64 +u64or (u64 x, u64 y) +{ + u64 r; + r.hi = x.hi | y.hi; + r.lo = x.lo | y.lo; + return r; +} + +/* Return X ^ Y. */ +_GL_U64_INLINE u64 +u64xor (u64 x, u64 y) +{ + u64 r; + r.hi = x.hi ^ y.hi; + r.lo = x.lo ^ y.lo; + return r; +} + +/* Return X + Y. */ +_GL_U64_INLINE u64 +u64plus (u64 x, u64 y) +{ + u64 r; + r.lo = x.lo + y.lo; + r.hi = x.hi + y.hi + (r.lo < x.lo); + return r; +} + +/* Return X << N. */ +_GL_U64_INLINE u64 +u64shl (u64 x, int n) +{ + u64 r; + if (n < 32) + { + r.hi = (x.hi << n) | (x.lo >> (32 - n)); + r.lo = x.lo << n; + } + else + { + r.hi = x.lo << (n - 32); + r.lo = 0; + } + return r; +} + +/* Return X >> N. */ +_GL_U64_INLINE u64 +u64shr (u64 x, int n) +{ + u64 r; + if (n < 32) + { + r.hi = x.hi >> n; + r.lo = (x.hi << (32 - n)) | (x.lo >> n); + } + else + { + r.hi = 0; + r.lo = x.hi >> (n - 32); + } + return r; +} + +#endif + +_GL_INLINE_HEADER_END diff --git a/cross/lib/unistd.c b/cross/lib/unistd.c new file mode 100644 index 00000000000..be7a8255033 --- /dev/null +++ b/cross/lib/unistd.c @@ -0,0 +1,22 @@ +/* Inline functions for . + + Copyright (C) 2012-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#include + +#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE +#include "unistd.h" +typedef int dummy; diff --git a/cross/lib/unistd.in.h b/cross/lib/unistd.in.h new file mode 100644 index 00000000000..4812fdb1120 --- /dev/null +++ b/cross/lib/unistd.in.h @@ -0,0 +1,2329 @@ +/* Substitute for and wrapper around . + Copyright (C) 2003-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef _@GUARD_PREFIX@_UNISTD_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if @HAVE_UNISTD_H@ && defined _GL_INCLUDING_UNISTD_H +/* Special invocation convention: + - On Mac OS X 10.3.9 we have a sequence of nested includes + -> -> -> + In this situation, the functions are not yet declared, therefore we cannot + provide the C++ aliases. */ + +#@INCLUDE_NEXT@ @NEXT_UNISTD_H@ + +#else +/* Normal invocation convention. */ + +/* The include_next requires a split double-inclusion guard. */ +#if @HAVE_UNISTD_H@ +# define _GL_INCLUDING_UNISTD_H +# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ +# undef _GL_INCLUDING_UNISTD_H +#endif + +/* Get all possible declarations of gethostname(). */ +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ + && !defined _GL_INCLUDING_WINSOCK2_H +# define _GL_INCLUDING_WINSOCK2_H +# include +# undef _GL_INCLUDING_WINSOCK2_H +#endif + +#if !defined _@GUARD_PREFIX@_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H +#define _@GUARD_PREFIX@_UNISTD_H + +/* NetBSD 5.0 mis-defines NULL. Also get size_t. */ +/* But avoid namespace pollution on glibc systems. */ +#ifndef __GLIBC__ +# include +#endif + +/* mingw doesn't define the SEEK_* or *_FILENO macros in . */ +/* MSVC declares 'unlink' in , not in . We must include + it before we #define unlink rpl_unlink. */ +/* Cygwin 1.7.1 declares symlinkat in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \ + || ((@GNULIB_UNLINK@ || defined GNULIB_POSIXCHECK) \ + && (defined _WIN32 && ! defined __CYGWIN__)) \ + || ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \ + && defined __CYGWIN__)) \ + && ! defined __GLIBC__ +# include +#endif + +/* Cygwin 1.7.1 and Android 4.3 declare unlinkat in , not in + . */ +/* But avoid namespace pollution on glibc systems. */ +#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \ + && (defined __CYGWIN__ || defined __ANDROID__) \ + && ! defined __GLIBC__ +# include +#endif + +/* mingw fails to declare _exit in . */ +/* mingw, MSVC, BeOS, Haiku declare environ in , not in + . */ +/* Solaris declares getcwd not only in but also in . */ +/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system is + included here. */ +/* But avoid namespace pollution on glibc systems. */ +#if !defined __GLIBC__ && !defined __osf__ +# define __need_system_stdlib_h +# include +# undef __need_system_stdlib_h +#endif + +/* Native Windows platforms declare _chdir, _getcwd, _rmdir in + and/or , not in . + They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(), + _lseek(), _read(), _unlink(), _write() in . */ +#if defined _WIN32 && !defined __CYGWIN__ +# include +# include +#endif + +/* Native Windows platforms declare _execl*, _execv* in . */ +#if defined _WIN32 && !defined __CYGWIN__ +# include +#endif + +/* AIX and OSF/1 5.1 declare getdomainname in , not in . + NonStop Kernel declares gethostname in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \ + || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \ + && !defined __GLIBC__ +# include +#endif + +/* Mac OS X 10.13, Solaris 11.4, and Android 9.0 declare getentropy in + , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (@GNULIB_GETENTROPY@ || defined GNULIB_POSIXCHECK) \ + && ((defined __APPLE__ && defined __MACH__) || defined __sun \ + || defined __ANDROID__) \ + && @UNISTD_H_HAVE_SYS_RANDOM_H@ \ + && !defined __GLIBC__ +# include +#endif + +/* Android 4.3 declares fchownat in , not in . */ +/* But avoid namespace pollution on glibc systems. */ +#if (@GNULIB_FCHOWNAT@ || defined GNULIB_POSIXCHECK) && defined __ANDROID__ \ + && !defined __GLIBC__ +# include +#endif + +/* MSVC defines off_t in . + May also define off_t to a 64-bit type on native Windows. */ +/* Get off_t, ssize_t, mode_t. */ +#include + +/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ + +/* The definition of _GL_ARG_NONNULL is copied here. */ + +/* The definition of _GL_WARN_ON_USE is copied here. */ + + +/* Get getopt(), optarg, optind, opterr, optopt. */ +#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT +# include +# include +#endif + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_UNISTD_INLINE +# define _GL_UNISTD_INLINE _GL_INLINE +#endif + +/* Hide some function declarations from . */ + +#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ +# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef socket +# define socket socket_used_without_including_sys_socket_h +# undef connect +# define connect connect_used_without_including_sys_socket_h +# undef accept +# define accept accept_used_without_including_sys_socket_h +# undef bind +# define bind bind_used_without_including_sys_socket_h +# undef getpeername +# define getpeername getpeername_used_without_including_sys_socket_h +# undef getsockname +# define getsockname getsockname_used_without_including_sys_socket_h +# undef getsockopt +# define getsockopt getsockopt_used_without_including_sys_socket_h +# undef listen +# define listen listen_used_without_including_sys_socket_h +# undef recv +# define recv recv_used_without_including_sys_socket_h +# undef send +# define send send_used_without_including_sys_socket_h +# undef recvfrom +# define recvfrom recvfrom_used_without_including_sys_socket_h +# undef sendto +# define sendto sendto_used_without_including_sys_socket_h +# undef setsockopt +# define setsockopt setsockopt_used_without_including_sys_socket_h +# undef shutdown +# define shutdown shutdown_used_without_including_sys_socket_h +# else + _GL_WARN_ON_USE (socket, + "socket() used without including "); + _GL_WARN_ON_USE (connect, + "connect() used without including "); + _GL_WARN_ON_USE (accept, + "accept() used without including "); + _GL_WARN_ON_USE (bind, + "bind() used without including "); + _GL_WARN_ON_USE (getpeername, + "getpeername() used without including "); + _GL_WARN_ON_USE (getsockname, + "getsockname() used without including "); + _GL_WARN_ON_USE (getsockopt, + "getsockopt() used without including "); + _GL_WARN_ON_USE (listen, + "listen() used without including "); + _GL_WARN_ON_USE (recv, + "recv() used without including "); + _GL_WARN_ON_USE (send, + "send() used without including "); + _GL_WARN_ON_USE (recvfrom, + "recvfrom() used without including "); + _GL_WARN_ON_USE (sendto, + "sendto() used without including "); + _GL_WARN_ON_USE (setsockopt, + "setsockopt() used without including "); + _GL_WARN_ON_USE (shutdown, + "shutdown() used without including "); +# endif +# endif +# if !defined _@GUARD_PREFIX@_SYS_SELECT_H +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef select +# define select select_used_without_including_sys_select_h +# else + _GL_WARN_ON_USE (select, + "select() used without including "); +# endif +# endif +#endif + + +/* OS/2 EMX lacks these macros. */ +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +/* Ensure *_OK macros exist. */ +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + + +/* Declare overridden functions. */ + + +#if @GNULIB_ACCESS@ +# if @REPLACE_ACCESS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef access +# define access rpl_access +# endif +_GL_FUNCDECL_RPL (access, int, (const char *file, int mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (access, int, (const char *file, int mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef access +# define access _access +# endif +_GL_CXXALIAS_MDA (access, int, (const char *file, int mode)); +# else +_GL_CXXALIAS_SYS (access, int, (const char *file, int mode)); +# endif +_GL_CXXALIASWARN (access); +#elif defined GNULIB_POSIXCHECK +# undef access +# if HAVE_RAW_DECL_ACCESS +/* The access() function is a security risk. */ +_GL_WARN_ON_USE (access, "access does not always support X_OK - " + "use gnulib module access for portability; " + "also, this function is a security risk - " + "use the gnulib module faccessat instead"); +# endif +#elif @GNULIB_MDA_ACCESS@ +/* On native Windows, map 'access' to '_access', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::access always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef access +# define access _access +# endif +_GL_CXXALIAS_MDA (access, int, (const char *file, int mode)); +# else +_GL_CXXALIAS_SYS (access, int, (const char *file, int mode)); +# endif +_GL_CXXALIASWARN (access); +#endif + + +#if @GNULIB_CHDIR@ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chdir +# define chdir _chdir +# endif +_GL_CXXALIAS_MDA (chdir, int, (const char *file)); +# else +_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIASWARN (chdir); +#elif defined GNULIB_POSIXCHECK +# undef chdir +# if HAVE_RAW_DECL_CHDIR +_GL_WARN_ON_USE (chown, "chdir is not always in - " + "use gnulib module chdir for portability"); +# endif +#elif @GNULIB_MDA_CHDIR@ +/* On native Windows, map 'chdir' to '_chdir', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::chdir always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chdir +# define chdir _chdir +# endif +_GL_CXXALIAS_MDA (chdir, int, (const char *file)); +# else +_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIASWARN (chdir); +#endif + + +#if @GNULIB_CHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_DUP2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup2 rpl_dup2 +# endif +_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd)); +_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef dup2 +# define dup2 _dup2 +# endif +_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd)); +# else +_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIASWARN (dup2); +#elif defined GNULIB_POSIXCHECK +# undef dup2 +# if HAVE_RAW_DECL_DUP2 +_GL_WARN_ON_USE (dup2, "dup2 is unportable - " + "use gnulib module dup2 for portability"); +# endif +#elif @GNULIB_MDA_DUP2@ +/* On native Windows, map 'dup2' to '_dup2', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::dup2 always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef dup2 +# define dup2 _dup2 +# endif +_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd)); +# else +_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); +# endif +_GL_CXXALIASWARN (dup2); +#endif + + +#if @GNULIB_DUP3@ +/* Copy the file descriptor OLDFD into file descriptor NEWFD, with the + specified flags. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Close NEWFD first if it is open. + Return newfd if successful, otherwise -1 and errno set. + See the Linux man page at + . */ +# if @HAVE_DUP3@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup3 rpl_dup3 +# endif +_GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags)); +# else +_GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags)); +_GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags)); +# endif +_GL_CXXALIASWARN (dup3); +#elif defined GNULIB_POSIXCHECK +# undef dup3 +# if HAVE_RAW_DECL_DUP3 +_GL_WARN_ON_USE (dup3, "dup3 is unportable - " + "use gnulib module dup3 for portability"); +# endif +#endif + + +#if @GNULIB_ENVIRON@ +# if defined __CYGWIN__ && !defined __i386__ +/* The 'environ' variable is defined in a DLL. Therefore its declaration needs + the '__declspec(dllimport)' attribute, but the system's lacks it. + This leads to a link error on 64-bit Cygwin when the option + -Wl,--disable-auto-import is in use. */ +_GL_EXTERN_C __declspec(dllimport) char **environ; +# endif +# if !@HAVE_DECL_ENVIRON@ +/* Set of environment variables and values. An array of strings of the form + "VARIABLE=VALUE", terminated with a NULL. */ +# if defined __APPLE__ && defined __MACH__ +# include +# if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +# define _GL_USE_CRT_EXTERNS +# endif +# endif +# ifdef _GL_USE_CRT_EXTERNS +# include +# define environ (*_NSGetEnviron ()) +# else +# ifdef __cplusplus +extern "C" { +# endif +extern char **environ; +# ifdef __cplusplus +} +# endif +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# if HAVE_RAW_DECL_ENVIRON +_GL_UNISTD_INLINE char *** +_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - " + "use gnulib module environ for portability") +rpl_environ (void) +{ + return &environ; +} +# undef environ +# define environ (*rpl_environ ()) +# endif +#endif + + +#if @GNULIB_EUIDACCESS@ +/* Like access(), except that it uses the effective user id and group id of + the current process. */ +# if !@HAVE_EUIDACCESS@ +_GL_FUNCDECL_SYS (euidaccess, int, (const char *filename, int mode) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (euidaccess, int, (const char *filename, int mode)); +_GL_CXXALIASWARN (euidaccess); +# if defined GNULIB_POSIXCHECK +/* Like access(), this function is a security risk. */ +_GL_WARN_ON_USE (euidaccess, "the euidaccess function is a security risk - " + "use the gnulib module faccessat instead"); +# endif +#elif defined GNULIB_POSIXCHECK +# undef euidaccess +# if HAVE_RAW_DECL_EUIDACCESS +_GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - " + "use gnulib module euidaccess for portability"); +# endif +#endif + + +#if @GNULIB_EXECL@ +# if @REPLACE_EXECL@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execl +# define execl rpl_execl +# endif +_GL_FUNCDECL_RPL (execl, int, (const char *program, const char *arg, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (execl, int, (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execl); +#elif defined GNULIB_POSIXCHECK +# undef execl +# if HAVE_RAW_DECL_EXECL +_GL_WARN_ON_USE (execl, "execl behaves very differently on mingw - " + "use gnulib module execl for portability"); +# endif +#elif @GNULIB_MDA_EXECL@ +/* On native Windows, map 'execl' to '_execl', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execl always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execl +# define execl _execl +# endif +_GL_CXXALIAS_MDA (execl, intptr_t, (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execl); +#endif + +#if @GNULIB_EXECLE@ +# if @REPLACE_EXECLE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execle +# define execle rpl_execle +# endif +_GL_FUNCDECL_RPL (execle, int, (const char *program, const char *arg, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (execle, int, (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execle); +#elif defined GNULIB_POSIXCHECK +# undef execle +# if HAVE_RAW_DECL_EXECLE +_GL_WARN_ON_USE (execle, "execle behaves very differently on mingw - " + "use gnulib module execle for portability"); +# endif +#elif @GNULIB_MDA_EXECLE@ +/* On native Windows, map 'execle' to '_execle', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execle always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execle +# define execle _execle +# endif +_GL_CXXALIAS_MDA (execle, intptr_t, + (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execle); +#endif + +#if @GNULIB_EXECLP@ +# if @REPLACE_EXECLP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execlp +# define execlp rpl_execlp +# endif +_GL_FUNCDECL_RPL (execlp, int, (const char *program, const char *arg, ...) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (execlp, int, (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execlp); +#elif defined GNULIB_POSIXCHECK +# undef execlp +# if HAVE_RAW_DECL_EXECLP +_GL_WARN_ON_USE (execlp, "execlp behaves very differently on mingw - " + "use gnulib module execlp for portability"); +# endif +#elif @GNULIB_MDA_EXECLP@ +/* On native Windows, map 'execlp' to '_execlp', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execlp always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execlp +# define execlp _execlp +# endif +_GL_CXXALIAS_MDA (execlp, intptr_t, + (const char *program, const char *arg, ...)); +# else +_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...)); +# endif +_GL_CXXALIASWARN (execlp); +#endif + + +#if @GNULIB_EXECV@ +# if @REPLACE_EXECV@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execv +# define execv rpl_execv +# endif +_GL_FUNCDECL_RPL (execv, int, (const char *program, char * const *argv) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (execv, int, (const char *program, char * const *argv)); +# else +_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv)); +# endif +_GL_CXXALIASWARN (execv); +#elif defined GNULIB_POSIXCHECK +# undef execv +# if HAVE_RAW_DECL_EXECV +_GL_WARN_ON_USE (execv, "execv behaves very differently on mingw - " + "use gnulib module execv for portability"); +# endif +#elif @GNULIB_MDA_EXECV@ +/* On native Windows, map 'execv' to '_execv', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execv always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execv +# define execv _execv +# endif +_GL_CXXALIAS_MDA_CAST (execv, intptr_t, + (const char *program, char * const *argv)); +# else +_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv)); +# endif +_GL_CXXALIASWARN (execv); +#endif + +#if @GNULIB_EXECVE@ +# if @REPLACE_EXECVE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execve +# define execve rpl_execve +# endif +_GL_FUNCDECL_RPL (execve, int, + (const char *program, char * const *argv, char * const *env) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (execve, int, + (const char *program, char * const *argv, char * const *env)); +# else +_GL_CXXALIAS_SYS (execve, int, + (const char *program, char * const *argv, char * const *env)); +# endif +_GL_CXXALIASWARN (execve); +#elif defined GNULIB_POSIXCHECK +# undef execve +# if HAVE_RAW_DECL_EXECVE +_GL_WARN_ON_USE (execve, "execve behaves very differently on mingw - " + "use gnulib module execve for portability"); +# endif +#elif @GNULIB_MDA_EXECVE@ +/* On native Windows, map 'execve' to '_execve', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execve always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execve +# define execve _execve +# endif +_GL_CXXALIAS_MDA_CAST (execve, intptr_t, + (const char *program, char * const *argv, + char * const *env)); +# else +_GL_CXXALIAS_SYS (execve, int, + (const char *program, char * const *argv, char * const *env)); +# endif +_GL_CXXALIASWARN (execve); +#endif + +#if @GNULIB_EXECVP@ +# if @REPLACE_EXECVP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execvp +# define execvp rpl_execvp +# endif +_GL_FUNCDECL_RPL (execvp, int, (const char *program, char * const *argv) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (execvp, int, (const char *program, char * const *argv)); +# else +_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv)); +# endif +_GL_CXXALIASWARN (execvp); +#elif defined GNULIB_POSIXCHECK +# undef execvp +# if HAVE_RAW_DECL_EXECVP +_GL_WARN_ON_USE (execvp, "execvp behaves very differently on mingw - " + "use gnulib module execvp for portability"); +# endif +#elif @GNULIB_MDA_EXECVP@ +/* On native Windows, map 'execvp' to '_execvp', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execvp always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execvp +# define execvp _execvp +# endif +_GL_CXXALIAS_MDA_CAST (execvp, intptr_t, + (const char *program, char * const *argv)); +# else +_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv)); +# endif +_GL_CXXALIASWARN (execvp); +#endif + +#if @GNULIB_EXECVPE@ +# if @REPLACE_EXECVPE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execvpe +# define execvpe rpl_execvpe +# endif +_GL_FUNCDECL_RPL (execvpe, int, + (const char *program, char * const *argv, char * const *env) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (execvpe, int, + (const char *program, char * const *argv, char * const *env)); +# else +# if !@HAVE_DECL_EXECVPE@ +_GL_FUNCDECL_SYS (execvpe, int, + (const char *program, char * const *argv, char * const *env) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (execvpe, int, + (const char *program, char * const *argv, char * const *env)); +# endif +_GL_CXXALIASWARN (execvpe); +#elif defined GNULIB_POSIXCHECK +# undef execvpe +# if HAVE_RAW_DECL_EXECVPE +_GL_WARN_ON_USE (execvpe, "execvpe behaves very differently on mingw - " + "use gnulib module execvpe for portability"); +# endif +#elif @GNULIB_MDA_EXECVPE@ +/* On native Windows, map 'execvpe' to '_execvpe', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::execvpe on all platforms that have + it. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef execvpe +# define execvpe _execvpe +# endif +_GL_CXXALIAS_MDA_CAST (execvpe, intptr_t, + (const char *program, char * const *argv, + char * const *env)); +# elif @HAVE_EXECVPE@ +# if !@HAVE_DECL_EXECVPE@ +_GL_FUNCDECL_SYS (execvpe, int, + (const char *program, char * const *argv, char * const *env) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (execvpe, int, + (const char *program, char * const *argv, char * const *env)); +# endif +# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_EXECVPE@ +_GL_CXXALIASWARN (execvpe); +# endif +#endif + + +#if @GNULIB_FACCESSAT@ +# if @REPLACE_FACCESSAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef faccessat +# define faccessat rpl_faccessat +# endif +_GL_FUNCDECL_RPL (faccessat, int, + (int fd, char const *name, int mode, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (faccessat, int, + (int fd, char const *name, int mode, int flag)); +# else +# if !@HAVE_FACCESSAT@ +_GL_FUNCDECL_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (faccessat, int, + (int fd, char const *file, int mode, int flag)); +# endif +_GL_CXXALIASWARN (faccessat); +#elif defined GNULIB_POSIXCHECK +# undef faccessat +# if HAVE_RAW_DECL_FACCESSAT +_GL_WARN_ON_USE (faccessat, "faccessat is not portable - " + "use gnulib module faccessat for portability"); +# endif +#endif + + +#if @GNULIB_FCHDIR@ +/* Change the process' current working directory to the directory on which + the given file descriptor is open. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if ! @HAVE_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); + +/* Gnulib internal hooks needed to maintain the fchdir metadata. */ +_GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) + _GL_ARG_NONNULL ((2)); +_GL_EXTERN_C void _gl_unregister_fd (int fd); +_GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); +_GL_EXTERN_C const char *_gl_directory_name (int fd); + +# else +# if !@HAVE_DECL_FCHDIR@ +_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); +# endif +# endif +_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); +_GL_CXXALIASWARN (fchdir); +#elif defined GNULIB_POSIXCHECK +# undef fchdir +# if HAVE_RAW_DECL_FCHDIR +_GL_WARN_ON_USE (fchdir, "fchdir is unportable - " + "use gnulib module fchdir for portability"); +# endif +#endif + + +#if @GNULIB_FCHOWNAT@ +# if @REPLACE_FCHOWNAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fchownat +# define fchownat rpl_fchownat +# endif +_GL_FUNCDECL_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# else +# if !@HAVE_FCHOWNAT@ +_GL_FUNCDECL_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (fchownat, int, (int fd, char const *file, + uid_t owner, gid_t group, int flag)); +# endif +_GL_CXXALIASWARN (fchownat); +#elif defined GNULIB_POSIXCHECK +# undef fchownat +# if HAVE_RAW_DECL_FCHOWNAT +_GL_WARN_ON_USE (fchownat, "fchownat is not portable - " + "use gnulib module fchownat for portability"); +# endif +#endif + + +#if @GNULIB_FDATASYNC@ +/* Synchronize changes to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@ +_GL_FUNCDECL_SYS (fdatasync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fdatasync, int, (int fd)); +_GL_CXXALIASWARN (fdatasync); +#elif defined GNULIB_POSIXCHECK +# undef fdatasync +# if HAVE_RAW_DECL_FDATASYNC +_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - " + "use gnulib module fdatasync for portability"); +# endif +#endif + + +#if @GNULIB_FSYNC@ +/* Synchronize changes, including metadata, to a file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if !@HAVE_FSYNC@ +_GL_FUNCDECL_SYS (fsync, int, (int fd)); +# endif +_GL_CXXALIAS_SYS (fsync, int, (int fd)); +_GL_CXXALIASWARN (fsync); +#elif defined GNULIB_POSIXCHECK +# undef fsync +# if HAVE_RAW_DECL_FSYNC +_GL_WARN_ON_USE (fsync, "fsync is unportable - " + "use gnulib module fsync for portability"); +# endif +#endif + + +#if @GNULIB_FTRUNCATE@ +/* Change the size of the file to which FD is opened to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_FTRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ftruncate +# define ftruncate rpl_ftruncate +# endif +_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length)); +_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length)); +# else +# if !@HAVE_FTRUNCATE@ +_GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); +# endif +_GL_CXXALIASWARN (ftruncate); +#elif defined GNULIB_POSIXCHECK +# undef ftruncate +# if HAVE_RAW_DECL_FTRUNCATE +_GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " + "use gnulib module ftruncate for portability"); +# endif +#endif + + +#if @GNULIB_GETCWD@ +/* Get the name of the current working directory, and put it in SIZE bytes + of BUF. + Return BUF if successful, or NULL if the directory couldn't be determined + or SIZE was too small. + See the POSIX:2008 specification + . + Additionally, the gnulib module 'getcwd' guarantees the following GNU + extension: If BUF is NULL, an array is allocated with 'malloc'; the array + is SIZE bytes long, unless SIZE == 0, in which case it is as big as + necessary. */ +# if @REPLACE_GETCWD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getcwd rpl_getcwd +# endif +_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size)); +_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getcwd +# define getcwd _getcwd +# endif +_GL_CXXALIAS_MDA (getcwd, char *, (char *buf, size_t size)); +# else +/* Need to cast, because on mingw, the second parameter is + int size. */ +_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); +# endif +_GL_CXXALIASWARN (getcwd); +#elif defined GNULIB_POSIXCHECK +# undef getcwd +# if HAVE_RAW_DECL_GETCWD +_GL_WARN_ON_USE (getcwd, "getcwd is unportable - " + "use gnulib module getcwd for portability"); +# endif +#elif @GNULIB_MDA_GETCWD@ +/* On native Windows, map 'getcwd' to '_getcwd', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::getcwd always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getcwd +# define getcwd _getcwd +# endif +/* Need to cast, because on mingw, the second parameter is either + 'int size' or 'size_t size'. */ +_GL_CXXALIAS_MDA_CAST (getcwd, char *, (char *buf, size_t size)); +# else +_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); +# endif +_GL_CXXALIASWARN (getcwd); +#endif + + +#if @GNULIB_GETDOMAINNAME@ +/* Return the NIS domain name of the machine. + WARNING! The NIS domain name is unrelated to the fully qualified host name + of the machine. It is also unrelated to email addresses. + WARNING! The NIS domain name is usually the empty string or "(none)" when + not using NIS. + + Put up to LEN bytes of the NIS domain name into NAME. + Null terminate it if the name is shorter than LEN. + If the NIS domain name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @REPLACE_GETDOMAINNAME@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdomainname +# define getdomainname rpl_getdomainname +# endif +_GL_FUNCDECL_RPL (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getdomainname, int, (char *name, size_t len)); +# else +# if !@HAVE_DECL_GETDOMAINNAME@ +_GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getdomainname, int, (char *name, size_t len)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (getdomainname); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getdomainname +# if HAVE_RAW_DECL_GETDOMAINNAME +_GL_WARN_ON_USE (getdomainname, "getdomainname is unportable - " + "use gnulib module getdomainname for portability"); +# endif +#endif + + +#if @GNULIB_GETDTABLESIZE@ +/* Return the maximum number of file descriptors in the current process. + In POSIX, this is same as sysconf (_SC_OPEN_MAX). */ +# if @REPLACE_GETDTABLESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getdtablesize +# define getdtablesize rpl_getdtablesize +# endif +_GL_FUNCDECL_RPL (getdtablesize, int, (void)); +_GL_CXXALIAS_RPL (getdtablesize, int, (void)); +# else +# if !@HAVE_GETDTABLESIZE@ +_GL_FUNCDECL_SYS (getdtablesize, int, (void)); +# endif +/* Need to cast, because on AIX, the parameter list is + (...). */ +_GL_CXXALIAS_SYS_CAST (getdtablesize, int, (void)); +# endif +_GL_CXXALIASWARN (getdtablesize); +#elif defined GNULIB_POSIXCHECK +# undef getdtablesize +# if HAVE_RAW_DECL_GETDTABLESIZE +_GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - " + "use gnulib module getdtablesize for portability"); +# endif +#endif + + +#if @GNULIB_GETENTROPY@ +/* Fill a buffer with random bytes. */ +# if !@HAVE_GETENTROPY@ +_GL_FUNCDECL_SYS (getentropy, int, (void *buffer, size_t length)); +# endif +_GL_CXXALIAS_SYS (getentropy, int, (void *buffer, size_t length)); +_GL_CXXALIASWARN (getentropy); +#elif defined GNULIB_POSIXCHECK +# undef getentropy +# if HAVE_RAW_DECL_GETENTROPY +_GL_WARN_ON_USE (getentropy, "getentropy is unportable - " + "use gnulib module getentropy for portability"); +# endif +#endif + + +#if @GNULIB_GETGROUPS@ +/* Return the supplemental groups that the current process belongs to. + It is unspecified whether the effective group id is in the list. + If N is 0, return the group count; otherwise, N describes how many + entries are available in GROUPS. Return -1 and set errno if N is + not 0 and not large enough. Fails with ENOSYS on some systems. */ +# if @REPLACE_GETGROUPS@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getgroups +# define getgroups rpl_getgroups +# endif +_GL_FUNCDECL_RPL (getgroups, int, (int n, gid_t *groups)); +_GL_CXXALIAS_RPL (getgroups, int, (int n, gid_t *groups)); +# else +# if !@HAVE_GETGROUPS@ +_GL_FUNCDECL_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIAS_SYS (getgroups, int, (int n, gid_t *groups)); +# endif +_GL_CXXALIASWARN (getgroups); +#elif defined GNULIB_POSIXCHECK +# undef getgroups +# if HAVE_RAW_DECL_GETGROUPS +_GL_WARN_ON_USE (getgroups, "getgroups is unportable - " + "use gnulib module getgroups for portability"); +# endif +#endif + + +#if @GNULIB_GETHOSTNAME@ +/* Return the standard host name of the machine. + WARNING! The host name may or may not be fully qualified. + + Put up to LEN bytes of the host name into NAME. + Null terminate it if the name is shorter than LEN. + If the host name is longer than LEN, set errno = EINVAL and return -1. + Return 0 if successful, otherwise set errno and return -1. */ +# if @UNISTD_H_HAVE_WINSOCK2_H@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gethostname +# define gethostname rpl_gethostname +# endif +_GL_FUNCDECL_RPL (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); +# else +# if !@HAVE_GETHOSTNAME@ +_GL_FUNCDECL_SYS (gethostname, int, (char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 and OSF/1 5.1 systems, the second + parameter is + int len. */ +_GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); +# endif +_GL_CXXALIASWARN (gethostname); +#elif @UNISTD_H_HAVE_WINSOCK2_H@ +# undef gethostname +# define gethostname gethostname_used_without_requesting_gnulib_module_gethostname +#elif defined GNULIB_POSIXCHECK +# undef gethostname +# if HAVE_RAW_DECL_GETHOSTNAME +_GL_WARN_ON_USE (gethostname, "gethostname is unportable - " + "use gnulib module gethostname for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN@ +/* Returns the user's login name, or NULL if it cannot be found. Upon error, + returns NULL with errno set. + + See . + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if !@HAVE_DECL_GETLOGIN@ +_GL_FUNCDECL_SYS (getlogin, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getlogin, char *, (void)); +_GL_CXXALIASWARN (getlogin); +#elif defined GNULIB_POSIXCHECK +# undef getlogin +# if HAVE_RAW_DECL_GETLOGIN +_GL_WARN_ON_USE (getlogin, "getlogin is unportable - " + "use gnulib module getlogin for portability"); +# endif +#endif + + +#if @GNULIB_GETLOGIN_R@ +/* Copies the user's login name to NAME. + The array pointed to by NAME has room for SIZE bytes. + + Returns 0 if successful. Upon error, an error number is returned, or -1 in + the case that the login name cannot be found but no specific error is + provided (this case is hopefully rare but is left open by the POSIX spec). + + See . + + Most programs don't need to use this function, because the information is + available through environment variables: + ${LOGNAME-$USER} on Unix platforms, + $USERNAME on native Windows platforms. + */ +# if @REPLACE_GETLOGIN_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getlogin_r rpl_getlogin_r +# endif +_GL_FUNCDECL_RPL (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getlogin_r, int, (char *name, size_t size)); +# else +# if !@HAVE_DECL_GETLOGIN_R@ +_GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 10 systems, the second argument is + int size. */ +_GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size)); +# endif +_GL_CXXALIASWARN (getlogin_r); +#elif defined GNULIB_POSIXCHECK +# undef getlogin_r +# if HAVE_RAW_DECL_GETLOGIN_R +_GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - " + "use gnulib module getlogin_r for portability"); +# endif +#endif + + +#if @GNULIB_GETPAGESIZE@ +# if @REPLACE_GETPAGESIZE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize rpl_getpagesize +# endif +_GL_FUNCDECL_RPL (getpagesize, int, (void)); +_GL_CXXALIAS_RPL (getpagesize, int, (void)); +# else +/* On HP-UX, getpagesize exists, but it is not declared in even if + the compiler options -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 are used. */ +# if defined __hpux +_GL_FUNCDECL_SYS (getpagesize, int, (void)); +# endif +# if !@HAVE_GETPAGESIZE@ +# if !defined getpagesize +/* This is for POSIX systems. */ +# if !defined _gl_getpagesize && defined _SC_PAGESIZE +# if ! (defined __VMS && __VMS_VER < 70000000) +# define _gl_getpagesize() sysconf (_SC_PAGESIZE) +# endif +# endif +/* This is for older VMS. */ +# if !defined _gl_getpagesize && defined __VMS +# ifdef __ALPHA +# define _gl_getpagesize() 8192 +# else +# define _gl_getpagesize() 512 +# endif +# endif +/* This is for BeOS. */ +# if !defined _gl_getpagesize && @HAVE_OS_H@ +# include +# if defined B_PAGE_SIZE +# define _gl_getpagesize() B_PAGE_SIZE +# endif +# endif +/* This is for AmigaOS4.0. */ +# if !defined _gl_getpagesize && defined __amigaos4__ +# define _gl_getpagesize() 2048 +# endif +/* This is for older Unix systems. */ +# if !defined _gl_getpagesize && @HAVE_SYS_PARAM_H@ +# include +# ifdef EXEC_PAGESIZE +# define _gl_getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# define _gl_getpagesize() (NBPG * CLSIZE) +# else +# ifdef NBPC +# define _gl_getpagesize() NBPC +# endif +# endif +# endif +# endif +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define getpagesize() _gl_getpagesize () +# else +# if !GNULIB_defined_getpagesize_function +_GL_UNISTD_INLINE int +getpagesize () +{ + return _gl_getpagesize (); +} +# define GNULIB_defined_getpagesize_function 1 +# endif +# endif +# endif +# endif +/* Need to cast, because on Cygwin 1.5.x systems, the return type is size_t. */ +_GL_CXXALIAS_SYS_CAST (getpagesize, int, (void)); +# endif +# if @HAVE_DECL_GETPAGESIZE@ +_GL_CXXALIASWARN (getpagesize); +# endif +#elif defined GNULIB_POSIXCHECK +# undef getpagesize +# if HAVE_RAW_DECL_GETPAGESIZE +_GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - " + "use gnulib module getpagesize for portability"); +# endif +#endif + + +#if @GNULIB_GETPASS@ +/* Function getpass() from module 'getpass': + Read a password from /dev/tty or stdin. + Function getpass() from module 'getpass-gnu': + Read a password of arbitrary length from /dev/tty or stdin. */ +# if (@GNULIB_GETPASS@ && @REPLACE_GETPASS@) \ + || (@GNULIB_GETPASS_GNU@ && @REPLACE_GETPASS_FOR_GETPASS_GNU@) +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getpass +# define getpass rpl_getpass +# endif +_GL_FUNCDECL_RPL (getpass, char *, (const char *prompt) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getpass, char *, (const char *prompt)); +# else +# if !@HAVE_GETPASS@ +_GL_FUNCDECL_SYS (getpass, char *, (const char *prompt) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (getpass, char *, (const char *prompt)); +# endif +_GL_CXXALIASWARN (getpass); +#elif defined GNULIB_POSIXCHECK +# undef getpass +# if HAVE_RAW_DECL_GETPASS +_GL_WARN_ON_USE (getpass, "getpass is unportable - " + "use gnulib module getpass or getpass-gnu for portability"); +# endif +#endif + + +#if @GNULIB_MDA_GETPID@ +/* On native Windows, map 'getpid' to '_getpid', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::getpid always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getpid +# define getpid _getpid +# endif +_GL_CXXALIAS_MDA (getpid, int, (void)); +# else +_GL_CXXALIAS_SYS (getpid, pid_t, (void)); +# endif +_GL_CXXALIASWARN (getpid); +#endif + + +#if @GNULIB_GETUSERSHELL@ +/* Return the next valid login shell on the system, or NULL when the end of + the list has been reached. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (getusershell, char *, (void)); +# endif +_GL_CXXALIAS_SYS (getusershell, char *, (void)); +_GL_CXXALIASWARN (getusershell); +#elif defined GNULIB_POSIXCHECK +# undef getusershell +# if HAVE_RAW_DECL_GETUSERSHELL +_GL_WARN_ON_USE (getusershell, "getusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Rewind to pointer that is advanced at each getusershell() call. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (setusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (setusershell, void, (void)); +_GL_CXXALIASWARN (setusershell); +#elif defined GNULIB_POSIXCHECK +# undef setusershell +# if HAVE_RAW_DECL_SETUSERSHELL +_GL_WARN_ON_USE (setusershell, "setusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + +#if @GNULIB_GETUSERSHELL@ +/* Free the pointer that is advanced at each getusershell() call and + associated resources. */ +# if !@HAVE_DECL_GETUSERSHELL@ +_GL_FUNCDECL_SYS (endusershell, void, (void)); +# endif +_GL_CXXALIAS_SYS (endusershell, void, (void)); +_GL_CXXALIASWARN (endusershell); +#elif defined GNULIB_POSIXCHECK +# undef endusershell +# if HAVE_RAW_DECL_ENDUSERSHELL +_GL_WARN_ON_USE (endusershell, "endusershell is unportable - " + "use gnulib module getusershell for portability"); +# endif +#endif + + +#if @GNULIB_GROUP_MEMBER@ +/* Determine whether group id is in calling user's group list. */ +# if !@HAVE_GROUP_MEMBER@ +_GL_FUNCDECL_SYS (group_member, int, (gid_t gid)); +# endif +_GL_CXXALIAS_SYS (group_member, int, (gid_t gid)); +_GL_CXXALIASWARN (group_member); +#elif defined GNULIB_POSIXCHECK +# undef group_member +# if HAVE_RAW_DECL_GROUP_MEMBER +_GL_WARN_ON_USE (group_member, "group_member is unportable - " + "use gnulib module group-member for portability"); +# endif +#endif + + +#if @GNULIB_ISATTY@ +# if @REPLACE_ISATTY@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty rpl_isatty +# endif +# define GNULIB_defined_isatty 1 +_GL_FUNCDECL_RPL (isatty, int, (int fd)); +_GL_CXXALIAS_RPL (isatty, int, (int fd)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty _isatty +# endif +_GL_CXXALIAS_MDA (isatty, int, (int fd)); +# else +_GL_CXXALIAS_SYS (isatty, int, (int fd)); +# endif +_GL_CXXALIASWARN (isatty); +#elif defined GNULIB_POSIXCHECK +# undef isatty +# if HAVE_RAW_DECL_ISATTY +_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - " + "use gnulib module isatty for portability"); +# endif +#elif @GNULIB_MDA_ISATTY@ +/* On native Windows, map 'isatty' to '_isatty', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::isatty always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef isatty +# define isatty _isatty +# endif +_GL_CXXALIAS_MDA (isatty, int, (int fd)); +# else +_GL_CXXALIAS_SYS (isatty, int, (int fd)); +# endif +_GL_CXXALIASWARN (isatty); +#endif + + +#if @GNULIB_LCHOWN@ +/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE + to GID (if GID is not -1). Do not follow symbolic links. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_LCHOWN@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lchown +# define lchown rpl_lchown +# endif +_GL_FUNCDECL_RPL (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (lchown, int, (char const *file, uid_t owner, gid_t group)); +# else +# if !@HAVE_LCHOWN@ +_GL_FUNCDECL_SYS (lchown, int, (char const *file, uid_t owner, gid_t group) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (lchown, int, (char const *file, uid_t owner, gid_t group)); +# endif +_GL_CXXALIASWARN (lchown); +#elif defined GNULIB_POSIXCHECK +# undef lchown +# if HAVE_RAW_DECL_LCHOWN +_GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " + "use gnulib module lchown for portability"); +# endif +#endif + + +#if @GNULIB_LINK@ +/* Create a new hard link for an existing file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2008 specification + . */ +# if @REPLACE_LINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define link rpl_link +# endif +_GL_FUNCDECL_RPL (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (link, int, (const char *path1, const char *path2)); +# else +# if !@HAVE_LINK@ +_GL_FUNCDECL_SYS (link, int, (const char *path1, const char *path2) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (link, int, (const char *path1, const char *path2)); +# endif +_GL_CXXALIASWARN (link); +#elif defined GNULIB_POSIXCHECK +# undef link +# if HAVE_RAW_DECL_LINK +_GL_WARN_ON_USE (link, "link is unportable - " + "use gnulib module link for portability"); +# endif +#endif + + +#if @GNULIB_LINKAT@ +/* Create a new hard link for an existing file, relative to two + directories. FLAG controls whether symlinks are followed. + Return 0 if successful, otherwise -1 and errno set. */ +# if @REPLACE_LINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef linkat +# define linkat rpl_linkat +# endif +_GL_FUNCDECL_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +_GL_CXXALIAS_RPL (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# else +# if !@HAVE_LINKAT@ +_GL_FUNCDECL_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag) + _GL_ARG_NONNULL ((2, 4))); +# endif +_GL_CXXALIAS_SYS (linkat, int, + (int fd1, const char *path1, int fd2, const char *path2, + int flag)); +# endif +_GL_CXXALIASWARN (linkat); +#elif defined GNULIB_POSIXCHECK +# undef linkat +# if HAVE_RAW_DECL_LINKAT +_GL_WARN_ON_USE (linkat, "linkat is unportable - " + "use gnulib module linkat for portability"); +# endif +#endif + + +#if @GNULIB_LSEEK@ +/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. + Return the new offset if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_LSEEK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define lseek rpl_lseek +# endif +_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lseek +# define lseek _lseek +# endif +_GL_CXXALIAS_MDA (lseek, off_t, (int fd, off_t offset, int whence)); +# else +_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (lseek); +#elif defined GNULIB_POSIXCHECK +# undef lseek +# if HAVE_RAW_DECL_LSEEK +_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " + "systems - use gnulib module lseek for portability"); +# endif +#elif @GNULIB_MDA_LSEEK@ +/* On native Windows, map 'lseek' to '_lseek', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::lseek always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef lseek +# define lseek _lseek +# endif +_GL_CXXALIAS_MDA (lseek, long, (int fd, long offset, int whence)); +# else +_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); +# endif +_GL_CXXALIASWARN (lseek); +#endif + + +#if @GNULIB_PIPE@ +/* Create a pipe, defaulting to O_BINARY mode. + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. */ +# if !@HAVE_PIPE@ +_GL_FUNCDECL_SYS (pipe, int, (int fd[2]) _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (pipe, int, (int fd[2])); +_GL_CXXALIASWARN (pipe); +#elif defined GNULIB_POSIXCHECK +# undef pipe +# if HAVE_RAW_DECL_PIPE +_GL_WARN_ON_USE (pipe, "pipe is unportable - " + "use gnulib module pipe-posix for portability"); +# endif +#endif + + +#if @GNULIB_PIPE2@ +/* Create a pipe, applying the given flags when opening the read-end of the + pipe and the write-end of the pipe. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ) + and O_TEXT, O_BINARY (defined in "binary-io.h"). + Store the read-end as fd[0] and the write-end as fd[1]. + Return 0 upon success, or -1 with errno set upon failure. + See also the Linux man page at + . */ +# if @HAVE_PIPE2@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define pipe2 rpl_pipe2 +# endif +_GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags)); +# else +_GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags)); +# endif +_GL_CXXALIASWARN (pipe2); +#elif defined GNULIB_POSIXCHECK +# undef pipe2 +# if HAVE_RAW_DECL_PIPE2 +_GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " + "use gnulib module pipe2 for portability"); +# endif +#endif + + +#if @GNULIB_PREAD@ +/* Read at most BUFSIZE bytes from FD into BUF, starting at OFFSET. + Return the number of bytes placed into BUF if successful, otherwise + set errno and return -1. 0 indicates EOF. + See the POSIX:2008 specification + . */ +# if @REPLACE_PREAD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pread +# define pread rpl_pread +# endif +_GL_FUNCDECL_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PREAD@ +_GL_FUNCDECL_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pread, ssize_t, + (int fd, void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pread); +#elif defined GNULIB_POSIXCHECK +# undef pread +# if HAVE_RAW_DECL_PREAD +_GL_WARN_ON_USE (pread, "pread is unportable - " + "use gnulib module pread for portability"); +# endif +#endif + + +#if @GNULIB_PWRITE@ +/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. + Return the number of bytes written if successful, otherwise + set errno and return -1. 0 indicates nothing written. See the + POSIX:2008 specification + . */ +# if @REPLACE_PWRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef pwrite +# define pwrite rpl_pwrite +# endif +_GL_FUNCDECL_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# else +# if !@HAVE_PWRITE@ +_GL_FUNCDECL_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (pwrite, ssize_t, + (int fd, const void *buf, size_t bufsize, off_t offset)); +# endif +_GL_CXXALIASWARN (pwrite); +#elif defined GNULIB_POSIXCHECK +# undef pwrite +# if HAVE_RAW_DECL_PWRITE +_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " + "use gnulib module pwrite for portability"); +# endif +#endif + + +#if @GNULIB_READ@ +/* Read up to COUNT bytes from file descriptor FD into the buffer starting + at BUF. See the POSIX:2008 specification + . */ +# if @REPLACE_READ@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read rpl_read +# endif +_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read _read +# endif +_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, size_t count)); +# else +_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (read); +#elif @GNULIB_MDA_READ@ +/* On native Windows, map 'read' to '_read', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::read always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef read +# define read _read +# endif +# ifdef __MINGW32__ +_GL_CXXALIAS_MDA (read, int, (int fd, void *buf, unsigned int count)); +# else +_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, unsigned int count)); +# endif +# else +_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (read); +#endif + + +#if @GNULIB_READLINK@ +/* Read the contents of the symbolic link FILE and place the first BUFSIZE + bytes of it into BUF. Return the number of bytes placed into BUF if + successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_READLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlink rpl_readlink +# endif +_GL_FUNCDECL_RPL (readlink, ssize_t, + (const char *restrict file, + char *restrict buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (readlink, ssize_t, + (const char *restrict file, + char *restrict buf, size_t bufsize)); +# else +# if !@HAVE_READLINK@ +_GL_FUNCDECL_SYS (readlink, ssize_t, + (const char *restrict file, + char *restrict buf, size_t bufsize) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (readlink, ssize_t, + (const char *restrict file, + char *restrict buf, size_t bufsize)); +# endif +_GL_CXXALIASWARN (readlink); +#elif defined GNULIB_POSIXCHECK +# undef readlink +# if HAVE_RAW_DECL_READLINK +_GL_WARN_ON_USE (readlink, "readlink is unportable - " + "use gnulib module readlink for portability"); +# endif +#endif + + +#if @GNULIB_READLINKAT@ +# if @REPLACE_READLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define readlinkat rpl_readlinkat +# endif +_GL_FUNCDECL_RPL (readlinkat, ssize_t, + (int fd, char const *restrict file, + char *restrict buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +_GL_CXXALIAS_RPL (readlinkat, ssize_t, + (int fd, char const *restrict file, + char *restrict buf, size_t len)); +# else +# if !@HAVE_READLINKAT@ +_GL_FUNCDECL_SYS (readlinkat, ssize_t, + (int fd, char const *restrict file, + char *restrict buf, size_t len) + _GL_ARG_NONNULL ((2, 3))); +# endif +_GL_CXXALIAS_SYS (readlinkat, ssize_t, + (int fd, char const *restrict file, + char *restrict buf, size_t len)); +# endif +_GL_CXXALIASWARN (readlinkat); +#elif defined GNULIB_POSIXCHECK +# undef readlinkat +# if HAVE_RAW_DECL_READLINKAT +_GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " + "use gnulib module readlinkat for portability"); +# endif +#endif + + +#if @GNULIB_RMDIR@ +/* Remove the directory DIR. */ +# if @REPLACE_RMDIR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define rmdir rpl_rmdir +# endif +_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (rmdir, int, (char const *name)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef rmdir +# define rmdir _rmdir +# endif +_GL_CXXALIAS_MDA (rmdir, int, (char const *name)); +# else +_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); +# endif +_GL_CXXALIASWARN (rmdir); +#elif defined GNULIB_POSIXCHECK +# undef rmdir +# if HAVE_RAW_DECL_RMDIR +_GL_WARN_ON_USE (rmdir, "rmdir is unportable - " + "use gnulib module rmdir for portability"); +# endif +#elif @GNULIB_MDA_RMDIR@ +/* On native Windows, map 'rmdir' to '_rmdir', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::rmdir always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef rmdir +# define rmdir _rmdir +# endif +_GL_CXXALIAS_MDA (rmdir, int, (char const *name)); +# else +_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); +# endif +_GL_CXXALIASWARN (rmdir); +#endif + + +#if @GNULIB_SETHOSTNAME@ +/* Set the host name of the machine. + The host name may or may not be fully qualified. + + Put LEN bytes of NAME into the host name. + Return 0 if successful, otherwise, set errno and return -1. + + Platforms with no ability to set the hostname return -1 and set + errno = ENOSYS. */ +# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@ +_GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len) + _GL_ARG_NONNULL ((1))); +# endif +/* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5 + and FreeBSD 6.4 the second parameter is int. On Solaris 11 + 2011-10, the first parameter is not const. */ +_GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len)); +_GL_CXXALIASWARN (sethostname); +#elif defined GNULIB_POSIXCHECK +# undef sethostname +# if HAVE_RAW_DECL_SETHOSTNAME +_GL_WARN_ON_USE (sethostname, "sethostname is unportable - " + "use gnulib module sethostname for portability"); +# endif +#endif + + +#if @GNULIB_SLEEP@ +/* Pause the execution of the current thread for N seconds. + Returns the number of seconds left to sleep. + See the POSIX:2008 specification + . */ +# if @REPLACE_SLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef sleep +# define sleep rpl_sleep +# endif +_GL_FUNCDECL_RPL (sleep, unsigned int, (unsigned int n)); +_GL_CXXALIAS_RPL (sleep, unsigned int, (unsigned int n)); +# else +# if !@HAVE_SLEEP@ +_GL_FUNCDECL_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIAS_SYS (sleep, unsigned int, (unsigned int n)); +# endif +_GL_CXXALIASWARN (sleep); +#elif defined GNULIB_POSIXCHECK +# undef sleep +# if HAVE_RAW_DECL_SLEEP +_GL_WARN_ON_USE (sleep, "sleep is unportable - " + "use gnulib module sleep for portability"); +# endif +#endif + + +#if @GNULIB_MDA_SWAB@ +/* On native Windows, map 'swab' to '_swab', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::swab always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef swab +# define swab _swab +# endif +/* Need to cast, because in old mingw the arguments are + (const char *from, char *to, size_t n). */ +_GL_CXXALIAS_MDA_CAST (swab, void, (char *from, char *to, int n)); +# else +# if defined __hpux /* HP-UX */ +_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, int n)); +# elif defined __sun && (defined __SunOS_5_10 || defined __XOPEN_OR_POSIX) && !defined _XPG4 /* Solaris */ +_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, ssize_t n)); +# else +_GL_CXXALIAS_SYS (swab, void, (const void *from, void *to, ssize_t n)); +# endif +# endif +_GL_CXXALIASWARN (swab); +#endif + + +#if @GNULIB_SYMLINK@ +# if @REPLACE_SYMLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlink +# define symlink rpl_symlink +# endif +_GL_FUNCDECL_RPL (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (symlink, int, (char const *contents, char const *file)); +# else +# if !@HAVE_SYMLINK@ +_GL_FUNCDECL_SYS (symlink, int, (char const *contents, char const *file) + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (symlink, int, (char const *contents, char const *file)); +# endif +_GL_CXXALIASWARN (symlink); +#elif defined GNULIB_POSIXCHECK +# undef symlink +# if HAVE_RAW_DECL_SYMLINK +_GL_WARN_ON_USE (symlink, "symlink is not portable - " + "use gnulib module symlink for portability"); +# endif +#endif + + +#if @GNULIB_SYMLINKAT@ +# if @REPLACE_SYMLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef symlinkat +# define symlinkat rpl_symlinkat +# endif +_GL_FUNCDECL_RPL (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +_GL_CXXALIAS_RPL (symlinkat, int, + (char const *contents, int fd, char const *file)); +# else +# if !@HAVE_SYMLINKAT@ +_GL_FUNCDECL_SYS (symlinkat, int, + (char const *contents, int fd, char const *file) + _GL_ARG_NONNULL ((1, 3))); +# endif +_GL_CXXALIAS_SYS (symlinkat, int, + (char const *contents, int fd, char const *file)); +# endif +_GL_CXXALIASWARN (symlinkat); +#elif defined GNULIB_POSIXCHECK +# undef symlinkat +# if HAVE_RAW_DECL_SYMLINKAT +_GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " + "use gnulib module symlinkat for portability"); +# endif +#endif + + +#if @GNULIB_TRUNCATE@ +/* Change the size of the file designated by FILENAME to become equal to LENGTH. + Return 0 if successful, otherwise -1 and errno set. + See the POSIX:2008 specification + . */ +# if @REPLACE_TRUNCATE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef truncate +# define truncate rpl_truncate +# endif +_GL_FUNCDECL_RPL (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (truncate, int, (const char *filename, off_t length)); +# else +# if !@HAVE_DECL_TRUNCATE@ +_GL_FUNCDECL_SYS (truncate, int, (const char *filename, off_t length) + _GL_ARG_NONNULL ((1))); +# endif +_GL_CXXALIAS_SYS (truncate, int, (const char *filename, off_t length)); +# endif +_GL_CXXALIASWARN (truncate); +#elif defined GNULIB_POSIXCHECK +# undef truncate +# if HAVE_RAW_DECL_TRUNCATE +_GL_WARN_ON_USE (truncate, "truncate is unportable - " + "use gnulib module truncate for portability"); +# endif +#endif + + +#if @GNULIB_TTYNAME_R@ +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +# if @REPLACE_TTYNAME_R@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef ttyname_r +# define ttyname_r rpl_ttyname_r +# endif +_GL_FUNCDECL_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# else +# if !@HAVE_DECL_TTYNAME_R@ +_GL_FUNCDECL_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (ttyname_r, int, + (int fd, char *buf, size_t buflen)); +# endif +_GL_CXXALIASWARN (ttyname_r); +#elif defined GNULIB_POSIXCHECK +# undef ttyname_r +# if HAVE_RAW_DECL_TTYNAME_R +_GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - " + "use gnulib module ttyname_r for portability"); +# endif +#endif + + +#if @GNULIB_UNLINK@ +# if @REPLACE_UNLINK@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlink +# define unlink rpl_unlink +# endif +_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (unlink, int, (char const *file)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlink +# define unlink _unlink +# endif +_GL_CXXALIAS_MDA (unlink, int, (char const *file)); +# else +_GL_CXXALIAS_SYS (unlink, int, (char const *file)); +# endif +_GL_CXXALIASWARN (unlink); +#elif defined GNULIB_POSIXCHECK +# undef unlink +# if HAVE_RAW_DECL_UNLINK +_GL_WARN_ON_USE (unlink, "unlink is not portable - " + "use gnulib module unlink for portability"); +# endif +#elif @GNULIB_MDA_UNLINK@ +/* On native Windows, map 'unlink' to '_unlink', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::unlink always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlink +# define unlink _unlink +# endif +_GL_CXXALIAS_MDA (unlink, int, (char const *file)); +# else +_GL_CXXALIAS_SYS (unlink, int, (char const *file)); +# endif +_GL_CXXALIASWARN (unlink); +#endif + + +#if @GNULIB_UNLINKAT@ +# if @REPLACE_UNLINKAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef unlinkat +# define unlinkat rpl_unlinkat +# endif +_GL_FUNCDECL_RPL (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (unlinkat, int, (int fd, char const *file, int flag)); +# else +# if !@HAVE_UNLINKAT@ +_GL_FUNCDECL_SYS (unlinkat, int, (int fd, char const *file, int flag) + _GL_ARG_NONNULL ((2))); +# endif +_GL_CXXALIAS_SYS (unlinkat, int, (int fd, char const *file, int flag)); +# endif +_GL_CXXALIASWARN (unlinkat); +#elif defined GNULIB_POSIXCHECK +# undef unlinkat +# if HAVE_RAW_DECL_UNLINKAT +_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " + "use gnulib module unlinkat for portability"); +# endif +#endif + + +#if @GNULIB_USLEEP@ +/* Pause the execution of the current thread for N microseconds. + Returns 0 on completion, or -1 on range error. + See the POSIX:2001 specification + . */ +# if @REPLACE_USLEEP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef usleep +# define usleep rpl_usleep +# endif +_GL_FUNCDECL_RPL (usleep, int, (useconds_t n)); +_GL_CXXALIAS_RPL (usleep, int, (useconds_t n)); +# else +# if !@HAVE_USLEEP@ +_GL_FUNCDECL_SYS (usleep, int, (useconds_t n)); +# endif +/* Need to cast, because on Haiku, the first parameter is + unsigned int n. */ +_GL_CXXALIAS_SYS_CAST (usleep, int, (useconds_t n)); +# endif +_GL_CXXALIASWARN (usleep); +#elif defined GNULIB_POSIXCHECK +# undef usleep +# if HAVE_RAW_DECL_USLEEP +_GL_WARN_ON_USE (usleep, "usleep is unportable - " + "use gnulib module usleep for portability"); +# endif +#endif + + +#if @GNULIB_WRITE@ +/* Write up to COUNT bytes starting at BUF to file descriptor FD. + See the POSIX:2008 specification + . */ +# if @REPLACE_WRITE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef write +# define write rpl_write +# endif +_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef write +# define write _write +# endif +_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, size_t count)); +# else +_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (write); +#elif @GNULIB_MDA_WRITE@ +/* On native Windows, map 'write' to '_write', so that -loldnames is not + required. In C++ with GNULIB_NAMESPACE, avoid differences between + platforms by defining GNULIB_NAMESPACE::write always. */ +# if defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef write +# define write _write +# endif +# ifdef __MINGW32__ +_GL_CXXALIAS_MDA (write, int, (int fd, const void *buf, unsigned int count)); +# else +_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, unsigned int count)); +# endif +# else +_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count)); +# endif +_GL_CXXALIASWARN (write); +#endif + +_GL_INLINE_HEADER_END + +#endif /* _@GUARD_PREFIX@_UNISTD_H */ +#endif /* _GL_INCLUDING_UNISTD_H */ +#endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/cross/lib/unlocked-io.h b/cross/lib/unlocked-io.h new file mode 100644 index 00000000000..fdef624ab9c --- /dev/null +++ b/cross/lib/unlocked-io.h @@ -0,0 +1,136 @@ +/* Prefer faster, non-thread-safe stdio functions if available. + + Copyright (C) 2001-2004, 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* Written by Jim Meyering. */ + +#ifndef UNLOCKED_IO_H +# define UNLOCKED_IO_H 1 + +/* These are wrappers for functions/macros from the GNU C library, and + from other C libraries supporting POSIX's optional thread-safe functions. + + The standard I/O functions are thread-safe. These *_unlocked ones are + more efficient but not thread-safe. That they're not thread-safe is + fine since all of the applications in this package are single threaded. + + Also, some code that is shared with the GNU C library may invoke + the *_unlocked functions directly. On hosts that lack those + functions, invoke the non-thread-safe versions instead. */ + +# include + +# if HAVE_DECL_CLEARERR_UNLOCKED || defined clearerr_unlocked +# undef clearerr +# define clearerr(x) clearerr_unlocked (x) +# else +# define clearerr_unlocked(x) clearerr (x) +# endif + +# if HAVE_DECL_FEOF_UNLOCKED || defined feof_unlocked +# undef feof +# define feof(x) feof_unlocked (x) +# else +# define feof_unlocked(x) feof (x) +# endif + +# if HAVE_DECL_FERROR_UNLOCKED || defined ferror_unlocked +# undef ferror +# define ferror(x) ferror_unlocked (x) +# else +# define ferror_unlocked(x) ferror (x) +# endif + +# if HAVE_DECL_FFLUSH_UNLOCKED || defined fflush_unlocked +# undef fflush +# define fflush(x) fflush_unlocked (x) +# else +# define fflush_unlocked(x) fflush (x) +# endif + +# if HAVE_DECL_FGETS_UNLOCKED || defined fgets_unlocked +# undef fgets +# define fgets(x,y,z) fgets_unlocked (x,y,z) +# else +# define fgets_unlocked(x,y,z) fgets (x,y,z) +# endif + +# if HAVE_DECL_FPUTC_UNLOCKED || defined fputc_unlocked +# undef fputc +# define fputc(x,y) fputc_unlocked (x,y) +# else +# define fputc_unlocked(x,y) fputc (x,y) +# endif + +# if HAVE_DECL_FPUTS_UNLOCKED || defined fputs_unlocked +# undef fputs +# define fputs(x,y) fputs_unlocked (x,y) +# else +# define fputs_unlocked(x,y) fputs (x,y) +# endif + +# if HAVE_DECL_FREAD_UNLOCKED || defined fread_unlocked +# undef fread +# define fread(w,x,y,z) fread_unlocked (w,x,y,z) +# else +# define fread_unlocked(w,x,y,z) fread (w,x,y,z) +# endif + +# if HAVE_DECL_FWRITE_UNLOCKED || defined fwrite_unlocked +# undef fwrite +# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) +# else +# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) +# endif + +# if HAVE_DECL_GETC_UNLOCKED || defined get_unlocked +# undef getc +# define getc(x) getc_unlocked (x) +# else +# define getc_unlocked(x) getc (x) +# endif + +# if HAVE_DECL_GETCHAR_UNLOCKED || defined getchar_unlocked +# undef getchar +# define getchar() getchar_unlocked () +# else +# define getchar_unlocked() getchar () +# endif + +# if HAVE_DECL_PUTC_UNLOCKED || defined putc_unlocked +# undef putc +# define putc(x,y) putc_unlocked (x,y) +# else +# define putc_unlocked(x,y) putc (x,y) +# endif + +# if HAVE_DECL_PUTCHAR_UNLOCKED || defined putchar_unlocked +# undef putchar +# define putchar(x) putchar_unlocked (x) +# else +# define putchar_unlocked(x) putchar (x) +# endif + +# undef flockfile +# define flockfile(x) ((void) 0) + +# undef ftrylockfile +# define ftrylockfile(x) 0 + +# undef funlockfile +# define funlockfile(x) ((void) 0) + +#endif /* UNLOCKED_IO_H */ diff --git a/cross/lib/utimens.c b/cross/lib/utimens.c new file mode 100644 index 00000000000..4c5377eca0f --- /dev/null +++ b/cross/lib/utimens.c @@ -0,0 +1,646 @@ +/* Set file access and modification times. + + Copyright (C) 2003-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +/* derived from a function in touch.c */ + +#include + +#define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE +#include "utimens.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "stat-time.h" +#include "timespec.h" + +/* On native Windows, use SetFileTime; but avoid this when compiling + GNU Emacs, which arranges for this in some other way and which + defines WIN32_LEAN_AND_MEAN itself. */ + +#if defined _WIN32 && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION +# define USE_SETFILETIME +# define WIN32_LEAN_AND_MEAN +# include +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include +# endif +#endif + +/* Avoid recursion with rpl_futimens or rpl_utimensat. */ +#undef futimens +#if !HAVE_NEARLY_WORKING_UTIMENSAT +# undef utimensat +#endif + +/* Solaris 9 mistakenly succeeds when given a non-directory with a + trailing slash. Force the use of rpl_stat for a fix. */ +#ifndef REPLACE_FUNC_STAT_FILE +# define REPLACE_FUNC_STAT_FILE 0 +#endif + +#if HAVE_UTIMENSAT || HAVE_FUTIMENS +/* Cache variables for whether the utimensat syscall works; used to + avoid calling the syscall if we know it will just fail with ENOSYS, + and to avoid unnecessary work in massaging timestamps if the + syscall will work. Multiple variables are needed, to distinguish + between the following scenarios on Linux: + utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS + kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW + kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec + kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT + utimensat completely works + For each cache variable: 0 = unknown, 1 = yes, -1 = no. */ +static int utimensat_works_really; +static int lutimensat_works_really; +#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ + +/* Validate the requested timestamps. Return 0 if the resulting + timespec can be used for utimensat (after possibly modifying it to + work around bugs in utimensat). Return a positive value if the + timespec needs further adjustment based on stat results: 1 if any + adjustment is needed for utimes, and 2 if any adjustment is needed + for Linux utimensat. Return -1, with errno set to EINVAL, if + timespec is out of range. */ +static int +validate_timespec (struct timespec timespec[2]) +{ + int result = 0; + int utime_omit_count = 0; + if ((timespec[0].tv_nsec != UTIME_NOW + && timespec[0].tv_nsec != UTIME_OMIT + && ! (0 <= timespec[0].tv_nsec + && timespec[0].tv_nsec < TIMESPEC_HZ)) + || (timespec[1].tv_nsec != UTIME_NOW + && timespec[1].tv_nsec != UTIME_OMIT + && ! (0 <= timespec[1].tv_nsec + && timespec[1].tv_nsec < TIMESPEC_HZ))) + { + errno = EINVAL; + return -1; + } + /* Work around Linux kernel 2.6.25 bug, where utimensat fails with + EINVAL if tv_sec is not 0 when using the flag values of tv_nsec. + Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT + fails to bump ctime. */ + if (timespec[0].tv_nsec == UTIME_NOW + || timespec[0].tv_nsec == UTIME_OMIT) + { + timespec[0].tv_sec = 0; + result = 1; + if (timespec[0].tv_nsec == UTIME_OMIT) + utime_omit_count++; + } + if (timespec[1].tv_nsec == UTIME_NOW + || timespec[1].tv_nsec == UTIME_OMIT) + { + timespec[1].tv_sec = 0; + result = 1; + if (timespec[1].tv_nsec == UTIME_OMIT) + utime_omit_count++; + } + return result + (utime_omit_count == 1); +} + +/* Normalize any UTIME_NOW or UTIME_OMIT values in (*TS)[0] and (*TS)[1], + using STATBUF to obtain the current timestamps of the file. If + both times are UTIME_NOW, set *TS to NULL (as this can avoid some + permissions issues). If both times are UTIME_OMIT, return true + (nothing further beyond the prior collection of STATBUF is + necessary); otherwise return false. */ +static bool +update_timespec (struct stat const *statbuf, struct timespec **ts) +{ + struct timespec *timespec = *ts; + if (timespec[0].tv_nsec == UTIME_OMIT + && timespec[1].tv_nsec == UTIME_OMIT) + return true; + if (timespec[0].tv_nsec == UTIME_NOW + && timespec[1].tv_nsec == UTIME_NOW) + { + *ts = NULL; + return false; + } + + if (timespec[0].tv_nsec == UTIME_OMIT) + timespec[0] = get_stat_atime (statbuf); + else if (timespec[0].tv_nsec == UTIME_NOW) + gettime (×pec[0]); + + if (timespec[1].tv_nsec == UTIME_OMIT) + timespec[1] = get_stat_mtime (statbuf); + else if (timespec[1].tv_nsec == UTIME_NOW) + gettime (×pec[1]); + + return false; +} + +/* Set the access and modification timestamps of FD (a.k.a. FILE) to be + TIMESPEC[0] and TIMESPEC[1], respectively. + FD must be either negative -- in which case it is ignored -- + or a file descriptor that is open on FILE. + If FD is nonnegative, then FILE can be NULL, which means + use just futimes (or equivalent) instead of utimes (or equivalent), + and fail if on an old system without futimes (or equivalent). + If TIMESPEC is null, set the timestamps to the current time. + Return 0 on success, -1 (setting errno) on failure. */ + +int +fdutimens (int fd, char const *file, struct timespec const timespec[2]) +{ + struct timespec adjusted_timespec[2]; + struct timespec *ts = timespec ? adjusted_timespec : NULL; + int adjustment_needed = 0; + struct stat st; + + if (ts) + { + adjusted_timespec[0] = timespec[0]; + adjusted_timespec[1] = timespec[1]; + adjustment_needed = validate_timespec (ts); + } + if (adjustment_needed < 0) + return -1; + + /* Require that at least one of FD or FILE are potentially valid, to avoid + a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather + than failing. */ + if (fd < 0 && !file) + { + errno = EBADF; + return -1; + } + + /* Some Linux-based NFS clients are buggy, and mishandle timestamps + of files in NFS file systems in some cases. We have no + configure-time test for this, but please see + for references to + some of the problems with Linux 2.6.16. If this affects you, + compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to + help in some cases, albeit at a cost in performance. But you + really should upgrade your kernel to a fixed version, since the + problem affects many applications. */ + +#if HAVE_BUGGY_NFS_TIME_STAMPS + if (fd < 0) + sync (); + else + fsync (fd); +#endif + + /* POSIX 2008 added two interfaces to set file timestamps with + nanosecond resolution; newer Linux implements both functions via + a single syscall. We provide a fallback for ENOSYS (for example, + compiling against Linux 2.6.25 kernel headers and glibc 2.7, but + running on Linux 2.6.18 kernel). */ +#if HAVE_UTIMENSAT || HAVE_FUTIMENS + if (0 <= utimensat_works_really) + { + int result; +# if __linux__ || __sun + /* As recently as Linux kernel 2.6.32 (Dec 2009), several file + systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, + but work if both times are either explicitly specified or + UTIME_NOW. Work around it with a preparatory [f]stat prior + to calling futimens/utimensat; fortunately, there is not much + timing impact due to the extra syscall even on file systems + where UTIME_OMIT would have worked. + + The same bug occurs in Solaris 11.1 (Apr 2013). + + FIXME: Simplify this for Linux in 2016 and for Solaris in + 2024, when file system bugs are no longer common. */ + if (adjustment_needed == 2) + { + if (fd < 0 ? stat (file, &st) : fstat (fd, &st)) + return -1; + if (ts[0].tv_nsec == UTIME_OMIT) + ts[0] = get_stat_atime (&st); + else if (ts[1].tv_nsec == UTIME_OMIT) + ts[1] = get_stat_mtime (&st); + /* Note that st is good, in case utimensat gives ENOSYS. */ + adjustment_needed++; + } +# endif +# if HAVE_UTIMENSAT + if (fd < 0) + { +# if defined __APPLE__ && defined __MACH__ + size_t len = strlen (file); + if (len > 0 && file[len - 1] == '/') + { + struct stat statbuf; + if (stat (file, &statbuf) < 0) + return -1; + if (!S_ISDIR (statbuf.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } +# endif + result = utimensat (AT_FDCWD, file, ts, 0); +# ifdef __linux__ + /* Work around a kernel bug: + https://bugzilla.redhat.com/show_bug.cgi?id=442352 + https://bugzilla.redhat.com/show_bug.cgi?id=449910 + It appears that utimensat can mistakenly return 280 rather + than -1 upon ENOSYS failure. + FIXME: remove in 2010 or whenever the offending kernels + are no longer in common use. */ + if (0 < result) + errno = ENOSYS; +# endif /* __linux__ */ + if (result == 0 || errno != ENOSYS) + { + utimensat_works_really = 1; + return result; + } + } +# endif /* HAVE_UTIMENSAT */ +# if HAVE_FUTIMENS + if (0 <= fd) + { + result = futimens (fd, ts); +# ifdef __linux__ + /* Work around the same bug as above. */ + if (0 < result) + errno = ENOSYS; +# endif /* __linux__ */ + if (result == 0 || errno != ENOSYS) + { + utimensat_works_really = 1; + return result; + } + } +# endif /* HAVE_FUTIMENS */ + } + utimensat_works_really = -1; + lutimensat_works_really = -1; +#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ + +#ifdef USE_SETFILETIME + /* On native Windows, use SetFileTime(). See + + */ + if (0 <= fd) + { + HANDLE handle; + FILETIME current_time; + FILETIME last_access_time; + FILETIME last_write_time; + + handle = (HANDLE) _get_osfhandle (fd); + if (handle == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + + if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) + { + /* GetSystemTimeAsFileTime + . + It would be overkill to use + GetSystemTimePreciseAsFileTime + . */ + GetSystemTimeAsFileTime (¤t_time); + } + + if (ts == NULL || ts[0].tv_nsec == UTIME_NOW) + { + last_access_time = current_time; + } + else if (ts[0].tv_nsec == UTIME_OMIT) + { + last_access_time.dwLowDateTime = 0; + last_access_time.dwHighDateTime = 0; + } + else + { + ULONGLONG time_since_16010101 = + (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL; + last_access_time.dwLowDateTime = (DWORD) time_since_16010101; + last_access_time.dwHighDateTime = time_since_16010101 >> 32; + } + + if (ts == NULL || ts[1].tv_nsec == UTIME_NOW) + { + last_write_time = current_time; + } + else if (ts[1].tv_nsec == UTIME_OMIT) + { + last_write_time.dwLowDateTime = 0; + last_write_time.dwHighDateTime = 0; + } + else + { + ULONGLONG time_since_16010101 = + (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL; + last_write_time.dwLowDateTime = (DWORD) time_since_16010101; + last_write_time.dwHighDateTime = time_since_16010101 >> 32; + } + + if (SetFileTime (handle, NULL, &last_access_time, &last_write_time)) + return 0; + else + { + DWORD sft_error = GetLastError (); + #if 0 + fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error); + #endif + switch (sft_error) + { + case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */ + errno = EACCES; /* not specified by POSIX */ + break; + default: + errno = EINVAL; + break; + } + return -1; + } + } +#endif + + /* The platform lacks an interface to set file timestamps with + nanosecond resolution, so do the best we can, discarding any + fractional part of the timestamp. */ + + if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0)) + { + if (adjustment_needed != 3 + && (fd < 0 ? stat (file, &st) : fstat (fd, &st))) + return -1; + if (ts && update_timespec (&st, &ts)) + return 0; + } + + { +#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES + struct timeval timeval[2]; + struct timeval *t; + if (ts) + { + timeval[0].tv_sec = ts[0].tv_sec; + timeval[0].tv_usec = ts[0].tv_nsec / 1000; + timeval[1].tv_sec = ts[1].tv_sec; + timeval[1].tv_usec = ts[1].tv_nsec / 1000; + t = timeval; + } + else + t = NULL; + + if (fd < 0) + { +# if HAVE_FUTIMESAT + return futimesat (AT_FDCWD, file, t); +# endif + } + else + { + /* If futimesat or futimes fails here, don't try to speed things + up by returning right away. glibc can incorrectly fail with + errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0 + in high security mode doesn't allow ordinary users to read + /proc/self, so glibc incorrectly fails with errno == EACCES. + If errno == EIO, EPERM, or EROFS, it's probably safe to fail + right away, but these cases are rare enough that they're not + worth optimizing, and who knows what other messed-up systems + are out there? So play it safe and fall back on the code + below. */ + +# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES +# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG +# undef futimes +# define futimes(fd, t) futimesat (fd, NULL, t) +# endif + if (futimes (fd, t) == 0) + { +# if __linux__ && __GLIBC__ + /* Work around a longstanding glibc bug, still present as + of 2010-12-27. On older Linux kernels that lack both + utimensat and utimes, glibc's futimes rounds instead of + truncating when falling back on utime. The same bug + occurs in futimesat with a null 2nd arg. */ + if (t) + { + bool abig = 500000 <= t[0].tv_usec; + bool mbig = 500000 <= t[1].tv_usec; + if ((abig | mbig) && fstat (fd, &st) == 0) + { + /* If these two subtractions overflow, they'll + track the overflows inside the buggy glibc. */ + time_t adiff = st.st_atime - t[0].tv_sec; + time_t mdiff = st.st_mtime - t[1].tv_sec; + + struct timeval *tt = NULL; + struct timeval truncated_timeval[2]; + truncated_timeval[0] = t[0]; + truncated_timeval[1] = t[1]; + if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0) + { + tt = truncated_timeval; + tt[0].tv_usec = 0; + } + if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0) + { + tt = truncated_timeval; + tt[1].tv_usec = 0; + } + if (tt) + futimes (fd, tt); + } + } +# endif + + return 0; + } +# endif + } +#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */ + + if (!file) + { +#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \ + || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) + errno = ENOSYS; +#endif + return -1; + } + +#ifdef USE_SETFILETIME + return _gl_utimens_windows (file, ts); +#elif HAVE_WORKING_UTIMES + return utimes (file, t); +#else + { + struct utimbuf utimbuf; + struct utimbuf *ut; + if (ts) + { + utimbuf.actime = ts[0].tv_sec; + utimbuf.modtime = ts[1].tv_sec; + ut = &utimbuf; + } + else + ut = NULL; + + return utime (file, ut); + } +#endif /* !HAVE_WORKING_UTIMES */ + } +} + +/* Set the access and modification timestamps of FILE to be + TIMESPEC[0] and TIMESPEC[1], respectively. */ +int +utimens (char const *file, struct timespec const timespec[2]) +{ + return fdutimens (-1, file, timespec); +} + +/* Set the access and modification timestamps of FILE to be + TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing + symlinks. Fail with ENOSYS if the platform does not support + changing symlink timestamps, but FILE was a symlink. */ +int +lutimens (char const *file, struct timespec const timespec[2]) +{ + struct timespec adjusted_timespec[2]; + struct timespec *ts = timespec ? adjusted_timespec : NULL; + int adjustment_needed = 0; + struct stat st; + + if (ts) + { + adjusted_timespec[0] = timespec[0]; + adjusted_timespec[1] = timespec[1]; + adjustment_needed = validate_timespec (ts); + } + if (adjustment_needed < 0) + return -1; + + /* The Linux kernel did not support symlink timestamps until + utimensat, in version 2.6.22, so we don't need to mimic + fdutimens' worry about buggy NFS clients. But we do have to + worry about bogus return values. */ + +#if HAVE_UTIMENSAT + if (0 <= lutimensat_works_really) + { + int result; +# if __linux__ || __sun + /* As recently as Linux kernel 2.6.32 (Dec 2009), several file + systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, + but work if both times are either explicitly specified or + UTIME_NOW. Work around it with a preparatory lstat prior to + calling utimensat; fortunately, there is not much timing + impact due to the extra syscall even on file systems where + UTIME_OMIT would have worked. + + The same bug occurs in Solaris 11.1 (Apr 2013). + + FIXME: Simplify this for Linux in 2016 and for Solaris in + 2024, when file system bugs are no longer common. */ + if (adjustment_needed == 2) + { + if (lstat (file, &st)) + return -1; + if (ts[0].tv_nsec == UTIME_OMIT) + ts[0] = get_stat_atime (&st); + else if (ts[1].tv_nsec == UTIME_OMIT) + ts[1] = get_stat_mtime (&st); + /* Note that st is good, in case utimensat gives ENOSYS. */ + adjustment_needed++; + } +# endif + result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW); +# ifdef __linux__ + /* Work around a kernel bug: + https://bugzilla.redhat.com/show_bug.cgi?id=442352 + https://bugzilla.redhat.com/show_bug.cgi?id=449910 + It appears that utimensat can mistakenly return 280 rather + than -1 upon ENOSYS failure. + FIXME: remove in 2010 or whenever the offending kernels + are no longer in common use. */ + if (0 < result) + errno = ENOSYS; +# endif + if (result == 0 || errno != ENOSYS) + { + utimensat_works_really = 1; + lutimensat_works_really = 1; + return result; + } + } + lutimensat_works_really = -1; +#endif /* HAVE_UTIMENSAT */ + + /* The platform lacks an interface to set file timestamps with + nanosecond resolution, so do the best we can, discarding any + fractional part of the timestamp. */ + + if (adjustment_needed || REPLACE_FUNC_STAT_FILE) + { + if (adjustment_needed != 3 && lstat (file, &st)) + return -1; + if (ts && update_timespec (&st, &ts)) + return 0; + } + + /* On Linux, lutimes is a thin wrapper around utimensat, so there is + no point trying lutimes if utimensat failed with ENOSYS. */ +#if HAVE_LUTIMES && !HAVE_UTIMENSAT + { + struct timeval timeval[2]; + struct timeval *t; + int result; + if (ts) + { + timeval[0].tv_sec = ts[0].tv_sec; + timeval[0].tv_usec = ts[0].tv_nsec / 1000; + timeval[1].tv_sec = ts[1].tv_sec; + timeval[1].tv_usec = ts[1].tv_nsec / 1000; + t = timeval; + } + else + t = NULL; + + result = lutimes (file, t); + if (result == 0 || errno != ENOSYS) + return result; + } +#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */ + + /* Out of luck for symlinks, but we still handle regular files. */ + if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st)) + return -1; + if (!S_ISLNK (st.st_mode)) + return fdutimens (-1, file, ts); + errno = ENOSYS; + return -1; +} diff --git a/cross/lib/utimens.h b/cross/lib/utimens.h new file mode 100644 index 00000000000..a7056981f32 --- /dev/null +++ b/cross/lib/utimens.h @@ -0,0 +1,49 @@ +/* Set file access and modification times. + + Copyright 2012-2023 Free Software Foundation, Inc. + + This file 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 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert. */ + +#include +int fdutimens (int, char const *, struct timespec const [2]); +int utimens (char const *, struct timespec const [2]); +int lutimens (char const *, struct timespec const [2]); + +#if GNULIB_FDUTIMENSAT +# include +# include + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef _GL_UTIMENS_INLINE +# define _GL_UTIMENS_INLINE _GL_INLINE +#endif + +int fdutimensat (int fd, int dir, char const *name, struct timespec const [2], + int atflag); + +/* Using this function makes application code slightly more readable. */ +_GL_UTIMENS_INLINE int +lutimensat (int dir, char const *file, struct timespec const times[2]) +{ + return utimensat (dir, file, times, AT_SYMLINK_NOFOLLOW); +} + +_GL_INLINE_HEADER_END + +#endif diff --git a/cross/lib/utimensat.c b/cross/lib/utimensat.c new file mode 100644 index 00000000000..5cff11cd0a9 --- /dev/null +++ b/cross/lib/utimensat.c @@ -0,0 +1,217 @@ +/* Set the access and modification time of a file relative to directory fd. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . */ + +/* written by Eric Blake */ + +#include + +/* Specification. */ +#include + +#include +#include +#include +#include +#include + +#include "stat-time.h" +#include "timespec.h" +#include "utimens.h" + +#if HAVE_NEARLY_WORKING_UTIMENSAT + +/* Use the original utimensat(), but correct the trailing slash handling. */ +int +rpl_utimensat (int fd, char const *file, struct timespec const times[2], + int flag) +# undef utimensat +{ + size_t len = strlen (file); + if (len && file[len - 1] == '/') + { + struct stat st; + if (fstatat (fd, file, &st, flag & AT_SYMLINK_NOFOLLOW) < 0) + return -1; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } + + return utimensat (fd, file, times, flag); +} + +#else + +# if HAVE_UTIMENSAT + +/* If we have a native utimensat, but are compiling this file, then + utimensat was defined to rpl_utimensat by our replacement + sys/stat.h. We assume the native version might fail with ENOSYS, + or succeed without properly affecting ctime (as is the case when + using newer glibc but older Linux kernel). In this scenario, + rpl_utimensat checks whether the native version is usable, and + local_utimensat provides the fallback manipulation. */ + +static int local_utimensat (int, char const *, struct timespec const[2], int); +# define AT_FUNC_NAME local_utimensat + +/* Like utimensat, but work around native bugs. */ + +int +rpl_utimensat (int fd, char const *file, struct timespec const times[2], + int flag) +# undef utimensat +{ +# if defined __linux__ || defined __sun + struct timespec ts[2]; +# endif + + /* See comments in utimens.c for details. */ + static int utimensat_works_really; /* 0 = unknown, 1 = yes, -1 = no. */ + if (0 <= utimensat_works_really) + { + int result; +# if defined __linux__ || defined __sun + struct stat st; + /* As recently as Linux kernel 2.6.32 (Dec 2009), several file + systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, + but work if both times are either explicitly specified or + UTIME_NOW. Work around it with a preparatory [l]stat prior + to calling utimensat; fortunately, there is not much timing + impact due to the extra syscall even on file systems where + UTIME_OMIT would have worked. + + The same bug occurs in Solaris 11.1 (Apr 2013). + + FIXME: Simplify this in 2024, when these file system bugs are + no longer common on Gnulib target platforms. */ + if (times && (times[0].tv_nsec == UTIME_OMIT + || times[1].tv_nsec == UTIME_OMIT)) + { + if (fstatat (fd, file, &st, flag)) + return -1; + if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) + return 0; + if (times[0].tv_nsec == UTIME_OMIT) + ts[0] = get_stat_atime (&st); + else + ts[0] = times[0]; + if (times[1].tv_nsec == UTIME_OMIT) + ts[1] = get_stat_mtime (&st); + else + ts[1] = times[1]; + times = ts; + } +# ifdef __hppa__ + /* Linux kernel 2.6.22.19 on hppa does not reject invalid tv_nsec + values. */ + else if (times + && ((times[0].tv_nsec != UTIME_NOW + && ! (0 <= times[0].tv_nsec + && times[0].tv_nsec < TIMESPEC_HZ)) + || (times[1].tv_nsec != UTIME_NOW + && ! (0 <= times[1].tv_nsec + && times[1].tv_nsec < TIMESPEC_HZ)))) + { + errno = EINVAL; + return -1; + } +# endif +# endif +# if defined __APPLE__ && defined __MACH__ + /* macOS 10.13 does not reject invalid tv_nsec values either. */ + if (times + && ((times[0].tv_nsec != UTIME_OMIT + && times[0].tv_nsec != UTIME_NOW + && ! (0 <= times[0].tv_nsec + && times[0].tv_nsec < TIMESPEC_HZ)) + || (times[1].tv_nsec != UTIME_OMIT + && times[1].tv_nsec != UTIME_NOW + && ! (0 <= times[1].tv_nsec + && times[1].tv_nsec < TIMESPEC_HZ)))) + { + errno = EINVAL; + return -1; + } + size_t len = strlen (file); + if (len > 0 && file[len - 1] == '/') + { + struct stat statbuf; + if (fstatat (fd, file, &statbuf, 0) < 0) + return -1; + if (!S_ISDIR (statbuf.st_mode)) + { + errno = ENOTDIR; + return -1; + } + } +# endif + result = utimensat (fd, file, times, flag); + /* Linux kernel 2.6.25 has a bug where it returns EINVAL for + UTIME_NOW or UTIME_OMIT with non-zero tv_sec, which + local_utimensat works around. Meanwhile, EINVAL for a bad + flag is indeterminate whether the native utimensat works, but + local_utimensat will also reject it. */ + if (result == -1 && errno == EINVAL && (flag & ~AT_SYMLINK_NOFOLLOW)) + return result; + if (result == 0 || (errno != ENOSYS && errno != EINVAL)) + { + utimensat_works_really = 1; + return result; + } + } + /* No point in trying openat/futimens, since on Linux, futimens is + implemented with the same syscall as utimensat. Only avoid the + native utimensat due to an ENOSYS failure; an EINVAL error was + data-dependent, and the next caller may pass valid data. */ + if (0 <= utimensat_works_really && errno == ENOSYS) + utimensat_works_really = -1; + return local_utimensat (fd, file, times, flag); +} + +# else /* !HAVE_UTIMENSAT */ + +# define AT_FUNC_NAME utimensat + +# endif /* !HAVE_UTIMENSAT */ + +/* Set the access and modification timestamps of FILE to be + TIMESPEC[0] and TIMESPEC[1], respectively; relative to directory + FD. If flag is AT_SYMLINK_NOFOLLOW, change the times of a symlink, + or fail with ENOSYS if not possible. If TIMESPEC is null, set the + timestamps to the current time. If possible, do it without + changing the working directory. Otherwise, resort to using + save_cwd/fchdir, then utimens/restore_cwd. If either the save_cwd + or the restore_cwd fails, then give a diagnostic and exit nonzero. + Return 0 on success, -1 (setting errno) on failure. */ + +/* AT_FUNC_NAME is now utimensat or local_utimensat. */ +# define AT_FUNC_F1 lutimens +# define AT_FUNC_F2 utimens +# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW +# define AT_FUNC_POST_FILE_PARAM_DECLS , struct timespec const ts[2], int flag +# define AT_FUNC_POST_FILE_ARGS , ts +# include "at-func.c" +# undef AT_FUNC_NAME +# undef AT_FUNC_F1 +# undef AT_FUNC_F2 +# undef AT_FUNC_USE_F1_COND +# undef AT_FUNC_POST_FILE_PARAM_DECLS +# undef AT_FUNC_POST_FILE_ARGS + +#endif /* !HAVE_NEARLY_WORKING_UTIMENSAT */ diff --git a/cross/lib/verify.h b/cross/lib/verify.h new file mode 100644 index 00000000000..b63cb264321 --- /dev/null +++ b/cross/lib/verify.h @@ -0,0 +1,350 @@ +/* Compile-time assert-like macros. + + Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ + +#ifndef _GL_VERIFY_H +#define _GL_VERIFY_H + + +/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC) + works as per C11. This is supported by GCC 4.6.0+ and by clang 4+. + + Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as + per C23. This is supported by GCC 9.1+. + + Support compilers claiming conformance to the relevant standard, + and also support GCC when not pedantic. If we were willing to slow + 'configure' down we could also use it with other compilers, but + since this affects only the quality of diagnostics, why bother? */ +#ifndef __cplusplus +# if (201112 <= __STDC_VERSION__ \ + || (!defined __STRICT_ANSI__ \ + && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__))) +# define _GL_HAVE__STATIC_ASSERT 1 +# endif +# if (202311 <= __STDC_VERSION__ \ + || (!defined __STRICT_ANSI__ && 9 <= __GNUC__)) +# define _GL_HAVE__STATIC_ASSERT1 1 +# endif +#endif + +/* FreeBSD 9.1 , included by and lots of other + system headers, defines a conflicting _Static_assert that is no + better than ours; override it. */ +#ifndef _GL_HAVE__STATIC_ASSERT +# include +# undef _Static_assert +#endif + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + If _Static_assert works, verify (R) uses it directly. Similarly, + _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct + that is an operand of sizeof. + + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: + + * The first step is ((R) ? 1 : -1). Given an expression R, of + integral or boolean or floating-point type, this yields an + expression of integral type, whose value is later verified to be + constant and nonnegative. + + * Next this expression W is wrapped in a type + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: W; + }. + If W is negative, this yields a compile-time error. No compiler can + deal with a bit-field of negative size. + + One might think that an array size check would have the same + effect, that is, that the type struct { unsigned int dummy[W]; } + would work as well. However, inside a function, some compilers + (such as C++ compilers and GNU C) allow local parameters and + variables inside array size expressions. With these compilers, + an array size check would not properly diagnose this misuse of + the verify macro: + + void function (int n) { verify (n < 0); } + + * For the verify macro, the struct _gl_verify_type will need to + somehow be embedded into a declaration. To be portable, this + declaration must declare an object, a constant, a function, or a + typedef name. If the declared entity uses the type directly, + such as in + + struct dummy {...}; + typedef struct {...} dummy; + extern struct {...} *dummy; + extern void dummy (struct {...} *); + extern struct {...} *dummy (void); + + two uses of the verify macro would yield colliding declarations + if the entity names are not disambiguated. A workaround is to + attach the current line number to the entity name: + + #define _GL_CONCAT0(x, y) x##y + #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) + extern struct {...} * _GL_CONCAT (dummy, __LINE__); + + But this has the problem that two invocations of verify from + within the same macro would collide, since the __LINE__ value + would be the same for both invocations. (The GCC __COUNTER__ + macro solves this problem, but is not portable.) + + A solution is to use the sizeof operator. It yields a number, + getting rid of the identity of the type. Declarations like + + extern int dummy [sizeof (struct {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + + can be repeated. + + * Should the implementation use a named struct or an unnamed struct? + Which of the following alternatives can be used? + + extern int dummy [sizeof (struct {...})]; + extern int dummy [sizeof (struct _gl_verify_type {...})]; + extern void dummy (int [sizeof (struct {...})]); + extern void dummy (int [sizeof (struct _gl_verify_type {...})]); + extern int (*dummy (void)) [sizeof (struct {...})]; + extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; + + In the second and sixth case, the struct type is exported to the + outer scope; two such declarations therefore collide. GCC warns + about the first, third, and fourth cases. So the only remaining + possibility is the fifth case: + + extern int (*dummy (void)) [sizeof (struct {...})]; + + * GCC warns about duplicate declarations of the dummy function if + -Wredundant-decls is used. GCC 4.3 and later have a builtin + __COUNTER__ macro that can let us generate unique identifiers for + each dummy function, to suppress this warning. + + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. + + * GCC warns if -Wnested-externs is enabled and 'verify' is used + within a function body; but inside a function, you can always + arrange to use verify_expr instead. + + * In C++, any struct definition inside sizeof is invalid. + Use a template type to work around the problem. */ + +/* Concatenate two preprocessor tokens. */ +#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) +#define _GL_CONCAT0(x, y) x##y + +/* _GL_COUNTER is an integer, preferably one that changes each time we + use it. Use __COUNTER__ if it works, falling back on __LINE__ + otherwise. __LINE__ isn't perfect, but it's better than a + constant. */ +#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ +# define _GL_COUNTER __COUNTER__ +#else +# define _GL_COUNTER __LINE__ +#endif + +/* Generate a symbol with the given prefix, making it unique if + possible. */ +#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) + +/* Verify requirement R at compile-time, as an integer constant expression + that returns 1. If R is false, fail at compile-time, preferably + with a diagnostic that includes the string-literal DIAGNOSTIC. */ + +#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ + (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) + +#ifdef __cplusplus +# if !GNULIB_defined_struct__gl_verify_type +template + struct _gl_verify_type { + unsigned int _gl_verify_error_if_negative: w; + }; +# define GNULIB_defined_struct__gl_verify_type 1 +# endif +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + _gl_verify_type<(R) ? 1 : -1> +#elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { \ + _Static_assert (R, DIAGNOSTIC); \ + int _gl_dummy; \ + } +#else +# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ + struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } +#endif + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. If R is false, fail at compile-time. + + This macro requires three or more arguments but uses at most the first + two, so that the _Static_assert macro optionally defined below supports + both the C11 two-argument syntax and the C23 one-argument syntax. + + Unfortunately, unlike C11, this implementation must appear as an + ordinary declaration, and cannot appear inside struct { ... }. */ + +#if 202311 <= __STDC_VERSION__ || 200410 <= __cpp_static_assert +# define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC) +#elif defined _GL_HAVE__STATIC_ASSERT +# define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC) +#else +# define _GL_VERIFY(R, DIAGNOSTIC, ...) \ + extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ + [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] +# if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# pragma GCC diagnostic ignored "-Wnested-externs" +# endif +#endif + +/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ +#ifdef _GL_STATIC_ASSERT_H +# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert +# if !defined _MSC_VER || defined __clang__ +# define _Static_assert(...) \ + _GL_VERIFY (__VA_ARGS__, "static assertion failed", -) +# else + /* Work around MSVC preprocessor incompatibility with ISO C; see + . */ +# define _Static_assert(R, ...) \ + _GL_VERIFY ((R), "static assertion failed", -) +# endif +# endif +# if (!defined static_assert \ + && __STDC_VERSION__ < 202311 \ + && (!defined __cplusplus \ + || (__cpp_static_assert < 201411 \ + && __GNUG__ < 6 && __clang_major__ < 6))) +# if defined __cplusplus && _MSC_VER >= 1900 && !defined __clang__ +/* MSVC 14 in C++ mode supports the two-arguments static_assert but not + the one-argument static_assert, and it does not support _Static_assert. + We have to play preprocessor tricks to distinguish the two cases. + Since the MSVC preprocessor is not ISO C compliant (see above),. + the solution is specific to MSVC. */ +# define _GL_EXPAND(x) x +# define _GL_SA1(a1) static_assert ((a1), "static assertion failed") +# define _GL_SA2 static_assert +# define _GL_SA3 static_assert +# define _GL_SA_PICK(x1,x2,x3,x4,...) x4 +# define static_assert(...) _GL_EXPAND(_GL_SA_PICK(__VA_ARGS__,_GL_SA3,_GL_SA2,_GL_SA1)) (__VA_ARGS__) +# else +# define static_assert _Static_assert /* C11 requires this #define. */ +# endif +# endif +#endif + +/* @assert.h omit start@ */ + +#if defined __clang_major__ && __clang_major__ < 5 +# define _GL_HAS_BUILTIN_TRAP 0 +#elif 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)) +# define _GL_HAS_BUILTIN_TRAP 1 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_TRAP __has_builtin (__builtin_trap) +#else +# define _GL_HAS_BUILTIN_TRAP 0 +#endif + +#if defined __clang_major__ && __clang_major__ < 5 +# define _GL_HAS_BUILTIN_UNREACHABLE 0 +#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) +# define _GL_HAS_BUILTIN_UNREACHABLE 1 +#elif defined __has_builtin +# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) +#else +# define _GL_HAS_BUILTIN_UNREACHABLE 0 +#endif + +/* Each of these macros verifies that its argument R is nonzero. To + be portable, R should be an integer constant expression. Unlike + assert (R), there is no run-time overhead. + + There are two macros, since no single macro can be used in all + contexts in C. verify_expr (R, E) is for scalar contexts, including + integer constant expression contexts. verify (R) is for declaration + contexts, e.g., the top level. */ + +/* Verify requirement R at compile-time. Return the value of the + expression E. */ + +#define verify_expr(R, E) \ + (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) + +/* Verify requirement R at compile-time, as a declaration without a + trailing ';'. verify (R) acts like static_assert (R) except that + it is portable to C11/C++14 and earlier, it can issue better + diagnostics, and its name is shorter and may be more convenient. */ + +#ifdef __PGI +/* PGI barfs if R is long. */ +# define verify(R) _GL_VERIFY (R, "verify (...)", -) +#else +# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -) +#endif + +/* Assume that R always holds. Behavior is undefined if R is false, + fails to evaluate, or has side effects. + + 'assume (R)' is a directive from the programmer telling the + compiler that R is true so the compiler needn't generate code to + test R. This is why 'assume' is in verify.h: it's related to + static checking (in this case, static checking done by the + programmer), not dynamic checking. + + 'assume (R)' can affect compilation of all the code, not just code + that happens to be executed after the assume (R) is "executed". + For example, if the code mistakenly does 'assert (R); assume (R);' + the compiler is entitled to optimize away the 'assert (R)'. + + Although assuming R can help a compiler generate better code or + diagnostics, performance can suffer if R uses hard-to-optimize + features such as function calls not inlined by the compiler. + + Avoid Clang's __builtin_assume, as it breaks GNU Emacs master + as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see + . It's not known whether this breakage + is a Clang bug or an Emacs bug; play it safe for now. */ + +#if _GL_HAS_BUILTIN_UNREACHABLE +# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#elif 1200 <= _MSC_VER +# define assume(R) __assume (R) +#elif 202311 <= __STDC_VERSION__ +# include +# define assume(R) ((R) ? (void) 0 : unreachable ()) +#elif (defined GCC_LINT || defined lint) && _GL_HAS_BUILTIN_TRAP + /* Doing it this way helps various packages when configured with + --enable-gcc-warnings, which compiles with -Dlint. It's nicer + if 'assume' silences warnings with GCC 3.4 through GCC 4.4.7 (2012). */ +# define assume(R) ((R) ? (void) 0 : __builtin_trap ()) +#else + /* Some older tools grok NOTREACHED, e.g., Oracle Studio 12.6 (2017). */ +# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0) +#endif + +/* @assert.h omit end@ */ + +#endif diff --git a/cross/lib/vla.h b/cross/lib/vla.h new file mode 100644 index 00000000000..55f112a060a --- /dev/null +++ b/cross/lib/vla.h @@ -0,0 +1,53 @@ +/* vla.h - variable length arrays + + Copyright 2014-2023 Free Software Foundation, Inc. + + This program is free software: you can 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 . + + Written by Paul Eggert. */ + +/* The VLA_ELEMS macro does not allocate variable-length arrays (VLAs), + so it does not have the security or performance issues commonly + associated with VLAs. VLA_ELEMS is for exploiting a C11 feature + where a function can start like this: + + double scan_array (int n, double v[static n]) + + to require a caller to pass a vector V with at least N elements; + this allows better static checking and performance in some cases. + In C11 this feature means that V is a VLA, so the feature is + supported only if __STDC_NO_VLA__ is defined, and for compatibility + to platforms that do not support VLAs, VLA_ELEMS (n) expands to + nothing when __STDC_NO_VLA__ is not defined. */ + +/* A function's argument must point to an array with at least N elements. + Example: 'int main (int argc, char *argv[VLA_ELEMS (argc)]);'. */ + +#ifdef __STDC_NO_VLA__ +# define VLA_ELEMS(n) +#else +# define VLA_ELEMS(n) static n +#endif + +/* Although C99 requires support for variable-length arrays (VLAs), + some C compilers never supported VLAs and VLAs are optional in C11. + VLAs are controversial because their allocation may be unintended + or awkward to support, and large VLAs might cause security or + performance problems. GCC can diagnose the use of VLAs via the + -Wvla and -Wvla-larger-than warnings options, and defining the + macro GNULIB_NO_VLA disables the allocation of VLAs in Gnulib code. + + The VLA_ELEMS macro is unaffected by GNULIB_NO_VLA, since it does + not allocate VLAs. Programs that use VLA_ELEMS should be compiled + with 'gcc -Wvla-larger-than' instead of with 'gcc -Wvla'. */ diff --git a/cross/lib/warn-on-use.h b/cross/lib/warn-on-use.h new file mode 100644 index 00000000000..30756034aff --- /dev/null +++ b/cross/lib/warn-on-use.h @@ -0,0 +1,149 @@ +/* A C macro for emitting warnings if a function is used. + Copyright (C) 2010-2023 Free Software Foundation, Inc. + + This program 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that 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 program. If not, see . */ + +/* _GL_WARN_ON_USE (function, "literal string") issues a declaration + for FUNCTION which will then trigger a compiler warning containing + the text of "literal string" anywhere that function is called, if + supported by the compiler. If the compiler does not support this + feature, the macro expands to an unused extern declaration. + + _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the + attribute used in _GL_WARN_ON_USE. If the compiler does not support + this feature, it expands to empty. + + These macros are useful for marking a function as a potential + portability trap, with the intent that "literal string" include + instructions on the replacement function that should be used + instead. + _GL_WARN_ON_USE is for functions with 'extern' linkage. + _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline' + linkage. + + However, one of the reasons that a function is a portability trap is + if it has the wrong signature. Declaring FUNCTION with a different + signature in C is a compilation error, so this macro must use the + same type as any existing declaration so that programs that avoid + the problematic FUNCTION do not fail to compile merely because they + included a header that poisoned the function. But this implies that + _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already + have a declaration. Use of this macro implies that there must not + be any other macro hiding the declaration of FUNCTION; but + undefining FUNCTION first is part of the poisoning process anyway + (although for symbols that are provided only via a macro, the result + is a compilation error rather than a warning containing + "literal string"). Also note that in C++, it is only safe to use if + FUNCTION has no overloads. + + For an example, it is possible to poison 'getline' by: + - adding a call to gl_WARN_ON_USE_PREPARE([[#include ]], + [getline]) in configure.ac, which potentially defines + HAVE_RAW_DECL_GETLINE + - adding this code to a header that wraps the system : + #undef getline + #if HAVE_RAW_DECL_GETLINE + _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but" + "not universally present; use the gnulib module getline"); + #endif + + It is not possible to directly poison global variables. But it is + possible to write a wrapper accessor function, and poison that + (less common usage, like &environ, will cause a compilation error + rather than issue the nice warning, but the end result of informing + the developer about their portability problem is still achieved): + #if HAVE_RAW_DECL_ENVIRON + static char *** + rpl_environ (void) { return &environ; } + _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); + # undef environ + # define environ (*rpl_environ ()) + #endif + or better (avoiding contradictory use of 'static' and 'extern'): + #if HAVE_RAW_DECL_ENVIRON + static char *** + _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared") + rpl_environ (void) { return &environ; } + # undef environ + # define environ (*rpl_environ ()) + #endif + */ +#ifndef _GL_WARN_ON_USE + +# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) +/* A compiler attribute is available in gcc versions 4.3.0 and later. */ +# define _GL_WARN_ON_USE(function, message) \ +_GL_WARN_EXTERN_C __typeof__ (function) function __attribute__ ((__warning__ (message))) +# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ + __attribute__ ((__warning__ (message))) +# elif __clang_major__ >= 4 +/* Another compiler attribute is available in clang. */ +# define _GL_WARN_ON_USE(function, message) \ +_GL_WARN_EXTERN_C __typeof__ (function) function \ + __attribute__ ((__diagnose_if__ (1, message, "warning"))) +# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ + __attribute__ ((__diagnose_if__ (1, message, "warning"))) +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE(function, message) \ +_GL_WARN_EXTERN_C __typeof__ (function) function +# define _GL_WARN_ON_USE_ATTRIBUTE(message) +# else /* Unsupported. */ +# define _GL_WARN_ON_USE(function, message) \ +_GL_WARN_EXTERN_C int _gl_warn_on_use +# define _GL_WARN_ON_USE_ATTRIBUTE(message) +# endif +#endif + +/* _GL_WARN_ON_USE_CXX (function, rettype_gcc, rettype_clang, parameters_and_attributes, "message") + is like _GL_WARN_ON_USE (function, "message"), except that in C++ mode the + function is declared with the given prototype, consisting of return type, + parameters, and attributes. + This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does + not work in this case. */ +#ifndef _GL_WARN_ON_USE_CXX +# if !defined __cplusplus +# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ + _GL_WARN_ON_USE (function, msg) +# else +# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) +/* A compiler attribute is available in gcc versions 4.3.0 and later. */ +# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ +extern rettype_gcc function parameters_and_attributes \ + __attribute__ ((__warning__ (msg))) +# elif __clang_major__ >= 4 +/* Another compiler attribute is available in clang. */ +# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ +extern rettype_clang function parameters_and_attributes \ + __attribute__ ((__diagnose_if__ (1, msg, "warning"))) +# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING +/* Verify the existence of the function. */ +# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ +extern rettype_gcc function parameters_and_attributes +# else /* Unsupported. */ +# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ +_GL_WARN_EXTERN_C int _gl_warn_on_use +# endif +# endif +#endif + +/* _GL_WARN_EXTERN_C declaration; + performs the declaration with C linkage. */ +#ifndef _GL_WARN_EXTERN_C +# if defined __cplusplus +# define _GL_WARN_EXTERN_C extern "C" +# else +# define _GL_WARN_EXTERN_C extern +# endif +#endif diff --git a/cross/lib/xalloc-oversized.h b/cross/lib/xalloc-oversized.h new file mode 100644 index 00000000000..5dbdfb5506a --- /dev/null +++ b/cross/lib/xalloc-oversized.h @@ -0,0 +1,65 @@ +/* xalloc-oversized.h -- memory allocation size checking + + Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc. + + This file 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 file is distributed in the hope that 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 program. If not, see . */ + +#ifndef XALLOC_OVERSIZED_H_ +#define XALLOC_OVERSIZED_H_ + +#include +#include + +/* True if N * S does not fit into both ptrdiff_t and size_t. + N and S should be nonnegative and free of side effects. + This expands to a constant expression if N and S are both constants. + By gnulib convention, SIZE_MAX represents overflow in size_t + calculations, so the conservative size_t-based dividend to use here + is SIZE_MAX - 1. */ +#define __xalloc_oversized(n, s) \ + ((s) != 0 \ + && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \ + < (n))) + +/* Return 1 if and only if an array of N objects, each of size S, + cannot exist reliably because its total size in bytes would exceed + MIN (PTRDIFF_MAX, SIZE_MAX - 1). + + N and S should be nonnegative and free of side effects. + + Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can + misbehave if N and S are both narrower than ptrdiff_t and size_t, + and can be rewritten as (xalloc_oversized (N, S) ? NULL + : malloc (N * (size_t) S)). + + This is a macro, not a function, so that it works even if an + argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */ +#if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX +# define xalloc_oversized(n, s) \ + __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1) +#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \ + && PTRDIFF_MAX < SIZE_MAX) +# define xalloc_oversized(n, s) \ + (__builtin_constant_p (n) && __builtin_constant_p (s) \ + ? __xalloc_oversized (n, s) \ + : ({ ptrdiff_t __xalloc_count; \ + __builtin_mul_overflow (n, s, &__xalloc_count); })) + +/* Other compilers use integer division; this may be slower but is + more portable. */ +#else +# define xalloc_oversized(n, s) __xalloc_oversized (n, s) +#endif + +#endif /* !XALLOC_OVERSIZED_H_ */ diff --git a/xcompile/Makefile.in b/xcompile/Makefile.in deleted file mode 100644 index ca3af4a9586..00000000000 --- a/xcompile/Makefile.in +++ /dev/null @@ -1,176 +0,0 @@ -### @configure_input@ - -# Copyright (C) 2023 Free Software Foundation, Inc. - -# This file is part of GNU Emacs. - -# GNU Emacs is free software: you can 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. - -# GNU Emacs is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with GNU Emacs. If not, see . - -top_srcdir = @top_srcdir@ -top_builddir = @top_builddir@ - -# Cross-compiling Emacs for Android. - -# The cross compiled binaries are built by having ``variant'' -# Makefiles generated at configure-time. First, -# $(top_builddir)/src/Makefile.android, -# $(top_builddir)/lib/Makefile.android, -# $(top_builddir)/lib/gnulib.mk.android and -# $(top_builddir)/lib-src/Makefile.android are copied to their usual -# locations in this directory. - -# Finally, the following commands are executed in order, to produce -# libgnu.a, various binaries in lib-src, and src/aemacs: -# make -C lib libgnu.a -# make -C lib-src src/aemacs -# make -C src aemacs - -# This is possibly the ugliest Makefile ever written! - -LIB_SRCDIR = $(realpath ./lib) -LIB_TOP_SRCDIR = $(realpath $(top_srcdir)) - -SRC_SRCDIR = $(realpath $(top_srcdir)/src) -SRC_TOP_SRCDIR = $(realpath $(top_srcdir)) - -LIB_SRC_SRCDIR = $(realpath $(top_srcdir)/lib-src) -LIB_SRC_TOP_SRCDIR = $(realpath $(top_src)) - -# This is a list of binaries to build and install in lib-src. - -LIBSRC_BINARIES = lib-src/etags lib-src/ctags lib-src/emacsclient \ - lib-src/ebrowse lib-src/hexl lib-src/movemail - -CLEAN_SUBDIRS=src lib-src - -.PHONY: all -all: lib/libgnu.a src/libemacs.so src/android-emacs $(LIBSRC_BINARIES) - -# This Makefile relies on builddir and top_builddir being relative -# paths in *.android. - -# This file is used to trick lib/gnulib.mk, it is not actually useful. -config.status: - touch config.status - -src/verbose.mk: verbose.mk.android - mkdir -p src - cp -f verbose.mk.android src/verbose.mk - -# Gnulib, make-fingerprint and make-docfile must be built before -# entering any of the rules below, or they will get the Android -# versions of many headers. - -.PHONY: $(top_builddir)/lib/libgnu.a -$(top_builddir)/lib/libgnu.a: - + make -C $(top_builddir)/lib libgnu.a - -.PHONY: $(top_builddir)/lib-src/make-fingerprint -$(top_builddir)/lib-src/make-fingerprint: - make -C $(top_builddir)/lib-src make-fingerprint - -.PHONY: $(top_builddir)/lib-src/make-docfile -$(top_builddir)/lib-src/make-docfile: - make -C $(top_builddir)/lib-src make-docfile - -PRE_BUILD_DEPS=$(top_builddir)/lib/libgnu.a \ - $(top_builddir)/lib-src/make-fingerprint \ - $(top_builddir)/lib-src/make-docfile - -lib/config.h: $(top_builddir)/src/config.h.android - cp -f -p $(top_builddir)/src/config.h.android lib/config.h - -lib/gnulib.mk: $(top_builddir)/lib/gnulib.mk.android - cp -f -p $(top_builddir)/lib/gnulib.mk.android lib/gnulib.mk - sed -i 's/srcdir =.*$$/srcdir = $(subst /,\/,$(LIB_SRCDIR))/g' \ - lib/gnulib.mk - -lib/Makefile: $(top_builddir)/lib/Makefile.android - cp -f -p $(top_builddir)/lib/Makefile.android lib/Makefile - sed -i 's/top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \ - lib/Makefile - -# What is needed to build gnulib. -LIB_DEPS = lib/config.h lib/gnulib.mk lib/Makefile - -.PHONY: lib/libgnu.a -lib/libgnu.a: src/verbose.mk config.status $(LIB_DEPS) $(PRE_BUILD_DEPS) - mkdir -p lib/deps lib/deps/malloc - +make -C lib libgnu.a - -src/Makefile src/config.h &: $(top_builddir)/src/config.h.android \ - $(top_builddir)/src/Makefile.android - mkdir -p src src/deps -# Copy config.h to src/ - cp -f -p $(top_builddir)/src/config.h.android src/config.h -# And the Makefile. - cp -f -p $(top_builddir)/src/Makefile.android src/Makefile -# Next, edit srcdir and top_srcdir to the right location. - sed -i 's/srcdir =.*$$/srcdir = $(subst /,\/,$(SRC_SRCDIR))/g' src/Makefile - sed -i 's/top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \ - src/Makefile -# Edit references to ../admin/unidata to read ../../admin/unidata. - sed -i 's/\.\.\/admin\/unidata/..\/..\/admin\/unidata/g' src/Makefile - sed -i 's/\.\.\/admin\/charsets/..\/..\/admin\/charsets/g' src/Makefile -# Next, edit libsrc to the location at top_srcdir! It is important -# that src/Makefile uses the binaries there, instead of any -# cross-compiled binaries at ./lib-src. - sed -i 's/libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' src/Makefile -# Edit out anything saying -I($(top_srcdir)/lib); that should be -# covered by -I$(lib) - sed -i 's/-I\$$(top_srcdir)\/lib//g' src/Makefile - -.PHONY: src/android-emacs src/libemacs.so -src/android-emacs src/libemacs.so &: src/Makefile src/config.h \ - src/verbose.mk lib/libgnu.a $(PRE_BUILD_DEPS) - +make -C src android-emacs libemacs.so - -lib-src/Makefile: $(top_builddir)/lib-src/Makefile.android - mkdir -p lib-src - cp -f -p $< $@ - sed -i 's/-I\$${srcdir}\/\.\.\/lib//g' lib-src/Makefile - -.PHONY: $(LIBSRC_BINARIES) -$(LIBSRC_BINARIES) &: src/verbose.mk $(top_builddir)/$@ lib/libgnu.a \ - src/config.h lib-src/Makefile $(PRE_BUILD_DEPS) - mkdir -p src lib-src -# Next, edit srcdir and top_srcdir to the right location. - sed -i 's/srcdir=.*$$/srcdir = $(subst /,\/,$(LIB_SRC_SRCDIR))/g' \ - lib-src/Makefile - sed -i 's/top_srcdir=.*$$/top_srcdir = $(subst /,\/,$(LIB_SRC_TOP_SRCDIR))/g' \ - lib-src/Makefile -# Edit out SCRIPTS, it interferes with the build. - sed -i 's/^SCRIPTS=.*$$/SCRIPTS=/g' lib-src/Makefile -# Finally, go into lib-src and make everything being built - +make -C lib-src $(foreach bin,$(LIBSRC_BINARIES),$(notdir $(bin))) - -.PHONY: clean maintainer-clean distclean -clean: - rm -rf $(CLEAN_SUBDIRS) *.bak sys - if [ -e lib/Makefile ]; then \ - make -C lib clean; \ - fi - rm -rf lib/config.h - -distclean bootstrap-clean: clean - if [ -e lib/Makefile ]; then \ - make -C lib distclean; \ - fi -# Just in case. - rm -rf lib/Makefile lib/gnulib.mk - -maintainer-clean: distclean bootstrap-clean - if [ -e lib/Makefile ]; then \ - make -C lib maintainer-clean; \ - fi diff --git a/xcompile/README b/xcompile/README deleted file mode 100644 index d5282212b71..00000000000 --- a/xcompile/README +++ /dev/null @@ -1,3 +0,0 @@ -This directory holds Makefiles and other required assets to build an -Emacs binary independently for another toolchain. It also holds -another copy of gnulib that may be modified to work on Android. diff --git a/xcompile/langinfo.h b/xcompile/langinfo.h deleted file mode 100644 index b296ba8db80..00000000000 --- a/xcompile/langinfo.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Replacement langinfo.h file for building GNU Emacs on Android. - -Copyright (C) 2023 Free Software Foundation, Inc. - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can 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. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see . */ - -#define nl_langinfo(ignore) "ASCII" diff --git a/xcompile/lib/COPYING b/xcompile/lib/COPYING deleted file mode 100644 index f288702d2fa..00000000000 --- a/xcompile/lib/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/xcompile/lib/acl-errno-valid.c b/xcompile/lib/acl-errno-valid.c deleted file mode 100644 index a4fd575e3f3..00000000000 --- a/xcompile/lib/acl-errno-valid.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Test whether ACLs are well supported on this system. - - Copyright 2013-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert. */ - -#include - -#include - -#include - -/* Return true if errno value ERRNUM indicates that ACLs are well - supported on this system. ERRNUM should be an errno value obtained - after an ACL-related system call fails. */ -bool -acl_errno_valid (int errnum) -{ - /* Recognize some common errors such as from an NFS mount that does - not support ACLs, even when local drives do. */ - switch (errnum) - { - case EBUSY: return false; - case EINVAL: return false; -#if defined __APPLE__ && defined __MACH__ - case ENOENT: return false; -#endif - case ENOSYS: return false; - -#if defined ENOTSUP && ENOTSUP != EOPNOTSUPP -# if ENOTSUP != ENOSYS /* Needed for the MS-Windows port of GNU Emacs. */ - case ENOTSUP: return false; -# endif -#endif - - case EOPNOTSUPP: return false; - default: return true; - } -} diff --git a/xcompile/lib/acl-internal.c b/xcompile/lib/acl-internal.c deleted file mode 100644 index fbe9b2c9a06..00000000000 --- a/xcompile/lib/acl-internal.c +++ /dev/null @@ -1,507 +0,0 @@ -/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -#include - -#include "acl.h" - -#include "acl-internal.h" - -#if USE_ACL && HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - -# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - -/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. - Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial. */ -int -acl_extended_nontrivial (acl_t acl) -{ - /* acl is non-trivial if it is non-empty. */ - return (acl_entries (acl) > 0); -} - -# else /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ - -/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. - Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. - Return -1 and set errno upon failure to determine it. */ -int -acl_access_nontrivial (acl_t acl) -{ - /* acl is non-trivial if it has some entries other than for "user::", - "group::", and "other::". Normally these three should be present - at least, allowing us to write - return (3 < acl_entries (acl)); - but the following code is more robust. */ -# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Cygwin >= 2.5 */ - - acl_entry_t ace; - int got_one; - - for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); - got_one > 0; - got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) - { - acl_tag_t tag; - if (acl_get_tag_type (ace, &tag) < 0) - return -1; - if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) - return 1; - } - return got_one; - -# elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */ - /* Don't use acl_get_entry: it is undocumented. */ - - int count = acl->acl_cnt; - int i; - - for (i = 0; i < count; i++) - { - acl_entry_t ace = &acl->acl_entry[i]; - acl_tag_t tag = ace->ae_tag; - - if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ - || tag == ACL_OTHER_OBJ)) - return 1; - } - return 0; - -# elif HAVE_ACL_FREE_TEXT /* Tru64 */ - /* Don't use acl_get_entry: it takes only one argument and does not work. */ - - int count = acl->acl_num; - acl_entry_t ace; - - for (ace = acl->acl_first; count > 0; ace = ace->next, count--) - { - acl_tag_t tag; - acl_perm_t perm; - - tag = ace->entry->acl_type; - if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER)) - return 1; - - perm = ace->entry->acl_perm; - /* On Tru64, perm can also contain non-standard bits such as - PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */ - if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0) - return 1; - } - return 0; - -# else - - errno = ENOSYS; - return -1; -# endif -} - -int -acl_default_nontrivial (acl_t acl) -{ - /* acl is non-trivial if it is non-empty. */ - return (acl_entries (acl) > 0); -} - -# endif - -#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ - -/* Test an ACL retrieved with GETACL. - Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_nontrivial (int count, aclent_t *entries) -{ - int i; - - for (i = 0; i < count; i++) - { - aclent_t *ace = &entries[i]; - - /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). - If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). - We don't need to check ace->a_id in these cases. */ - if (!(ace->a_type == USER_OBJ - || ace->a_type == GROUP_OBJ - || ace->a_type == OTHER_OBJ - /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry - sometimes. */ - || ace->a_type == CLASS_OBJ)) - return 1; - } - return 0; -} - -# ifdef ACE_GETACL - -/* A shortcut for a bitmask. */ -# define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA) - -/* Test an ACL retrieved with ACE_GETACL. - Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_ace_nontrivial (int count, ace_t *entries) -{ - int i; - - /* The flags in the ace_t structure changed in a binary incompatible way - when ACL_NO_TRIVIAL etc. were introduced in version 1.15. - How to distinguish the two conventions at runtime? - In the old convention, usually three ACEs have a_flags = ACE_OWNER / - ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new - convention, these values are not used. */ - int old_convention = 0; - - for (i = 0; i < count; i++) - if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) - { - old_convention = 1; - break; - } - - if (old_convention) - /* Running on Solaris 10. */ - for (i = 0; i < count; i++) - { - ace_t *ace = &entries[i]; - - /* Note: - If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat(). - If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat(). - We don't need to check ace->a_who in these cases. */ - if (!(ace->a_type == OLD_ALLOW - && (ace->a_flags == OLD_ACE_OWNER - || ace->a_flags == OLD_ACE_GROUP - || ace->a_flags == OLD_ACE_OTHER))) - return 1; - } - else - { - /* Running on Solaris 10 (newer version) or Solaris 11. */ - unsigned int access_masks[6] = - { - 0, /* owner@ deny */ - 0, /* owner@ allow */ - 0, /* group@ deny */ - 0, /* group@ allow */ - 0, /* everyone@ deny */ - 0 /* everyone@ allow */ - }; - - for (i = 0; i < count; i++) - { - ace_t *ace = &entries[i]; - unsigned int index1; - unsigned int index2; - - if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE) - index1 = 1; - else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE) - index1 = 0; - else - return 1; - - if (ace->a_flags == NEW_ACE_OWNER) - index2 = 0; - else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP)) - index2 = 2; - else if (ace->a_flags == NEW_ACE_EVERYONE) - index2 = 4; - else - return 1; - - access_masks[index1 + index2] |= ace->a_access_mask; - } - - /* The same bit shouldn't be both allowed and denied. */ - if (access_masks[0] & access_masks[1]) - return 1; - if (access_masks[2] & access_masks[3]) - return 1; - if (access_masks[4] & access_masks[5]) - return 1; - - /* Check minimum masks. */ - if ((NEW_ACE_WRITE_NAMED_ATTRS - | NEW_ACE_WRITE_ATTRIBUTES - | NEW_ACE_WRITE_ACL - | NEW_ACE_WRITE_OWNER) - & ~ access_masks[1]) - return 1; - access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS - | NEW_ACE_WRITE_ATTRIBUTES - | NEW_ACE_WRITE_ACL - | NEW_ACE_WRITE_OWNER); - if ((NEW_ACE_READ_NAMED_ATTRS - | NEW_ACE_READ_ATTRIBUTES - | NEW_ACE_READ_ACL - | NEW_ACE_SYNCHRONIZE) - & ~ access_masks[5]) - return 1; - access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS - | NEW_ACE_READ_ATTRIBUTES - | NEW_ACE_READ_ACL - | NEW_ACE_SYNCHRONIZE); - - /* Check the allowed or denied bits. */ - switch ((access_masks[0] | access_masks[1]) - & ~(NEW_ACE_READ_NAMED_ATTRS - | NEW_ACE_READ_ATTRIBUTES - | NEW_ACE_READ_ACL - | NEW_ACE_SYNCHRONIZE)) - { - case 0: - case NEW_ACE_READ_DATA: - case NEW_ACE_WRITEA_DATA: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: - case NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - break; - default: - return 1; - } - switch ((access_masks[2] | access_masks[3]) - & ~(NEW_ACE_READ_NAMED_ATTRS - | NEW_ACE_READ_ATTRIBUTES - | NEW_ACE_READ_ACL - | NEW_ACE_SYNCHRONIZE)) - { - case 0: - case NEW_ACE_READ_DATA: - case NEW_ACE_WRITEA_DATA: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: - case NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - break; - default: - return 1; - } - switch ((access_masks[4] | access_masks[5]) - & ~(NEW_ACE_WRITE_NAMED_ATTRS - | NEW_ACE_WRITE_ATTRIBUTES - | NEW_ACE_WRITE_ACL - | NEW_ACE_WRITE_OWNER)) - { - case 0: - case NEW_ACE_READ_DATA: - case NEW_ACE_WRITEA_DATA: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA: - case NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE: - break; - default: - return 1; - } - - /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are - either both allowed or both denied. */ - if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0) - != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0)) - return 1; - if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0) - != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0)) - return 1; - if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0) - != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0)) - return 1; - } - - return 0; -} - -# endif - -#elif USE_ACL && HAVE_GETACL /* HP-UX */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_nontrivial (int count, struct acl_entry *entries) -{ - int i; - - if (count > 3) - return 1; - - for (i = 0; i < count; i++) - { - struct acl_entry *ace = &entries[i]; - - if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP) - return 1; - } - return 0; -} - -# if HAVE_ACLV_H /* HP-UX >= 11.11 */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -aclv_nontrivial (int count, struct acl *entries) -{ - int i; - - for (i = 0; i < count; i++) - { - struct acl *ace = &entries[i]; - - /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). - If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). - We don't need to check ace->a_id in these cases. */ - if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ - || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ - || ace->a_type == CLASS_OBJ - || ace->a_type == OTHER_OBJ)) - return 1; - } - return 0; -} - -# endif - -#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_nontrivial (struct acl *a) -{ - /* The normal way to iterate through an ACL is like this: - struct acl_entry *ace; - for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace)) - { - struct ace_id *aei; - switch (ace->ace_type) - { - case ACC_PERMIT: - case ACC_DENY: - case ACC_SPECIFY: - ...; - } - for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei)) - ... - } - */ - return (acl_last (a) != a->acl_ext ? 1 : 0); -} - -# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_nfs4_nontrivial (nfs4_acl_int_t *a) -{ -# if 1 /* let's try this first */ - return (a->aclEntryN > 0 ? 1 : 0); -# else - int count = a->aclEntryN; - int i; - - for (i = 0; i < count; i++) - { - nfs4_ace_int_t *ace = &a->aclEntry[i]; - - if (!((ace->flags & ACE4_ID_SPECIAL) != 0 - && (ace->aceWho.special_whoid == ACE4_WHO_OWNER - || ace->aceWho.special_whoid == ACE4_WHO_GROUP - || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE) - && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE - && ace->aceFlags == 0 - && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY - | ACE4_WRITE_DATA | ACE4_ADD_FILE - | ACE4_EXECUTE)) == 0)) - return 1; - } - return 0; -# endif -} - -# endif - -#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ - -/* Test an ACL retrieved with ACL_GET. - Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -int -acl_nontrivial (int count, struct acl *entries) -{ - int i; - - for (i = 0; i < count; i++) - { - struct acl *ace = &entries[i]; - - /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). - If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). - We don't need to check ace->a_id in these cases. */ - if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ - || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ - || ace->a_type == CLASS_OBJ - || ace->a_type == OTHER_OBJ)) - return 1; - } - return 0; -} - -#endif - -void -free_permission_context (struct permission_context *ctx) -{ -#if USE_ACL -# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - if (ctx->acl) - acl_free (ctx->acl); -# if !HAVE_ACL_TYPE_EXTENDED - if (ctx->default_acl) - acl_free (ctx->default_acl); -# endif - -# elif defined GETACL /* Solaris, Cygwin < 2.5 */ - free (ctx->entries); -# ifdef ACE_GETACL - free (ctx->ace_entries); -# endif - -# elif HAVE_GETACL /* HP-UX */ - -# if HAVE_ACLV_H -# endif - -# elif HAVE_STATACL /* older AIX */ - -# elif HAVE_ACLSORT /* NonStop Kernel */ - -# endif -#endif -} diff --git a/xcompile/lib/acl-internal.h b/xcompile/lib/acl-internal.h deleted file mode 100644 index c97e847cdc5..00000000000 --- a/xcompile/lib/acl-internal.h +++ /dev/null @@ -1,301 +0,0 @@ -/* Internal implementation of access control lists. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -#include "acl.h" - -#include - -/* All systems define the ACL related API in . */ -#if HAVE_SYS_ACL_H -# include -#endif -#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT -# define GETACLCNT ACL_CNT -#endif - -/* On Linux and Cygwin >= 2.5, additional ACL related API is available in - . */ -#ifdef HAVE_ACL_LIBACL_H -# include -#endif - -/* On HP-UX >= 11.11, additional ACL API is available in . */ -#if HAVE_ACLV_H -# include -# include -/* HP-UX 11.11 lacks these declarations. */ -extern int acl (char *, int, int, struct acl *); -extern int aclsort (int, int, struct acl *); -#endif - -#include - -#include -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#ifndef HAVE_FCHMOD -# define HAVE_FCHMOD false -# define fchmod(fd, mode) (-1) -#endif - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef ACL_INTERNAL_INLINE -# define ACL_INTERNAL_INLINE _GL_INLINE -#endif - -#if USE_ACL - -# if HAVE_ACL_GET_FILE -/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ -/* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - -# ifndef MIN_ACL_ENTRIES -# define MIN_ACL_ENTRIES 4 -# endif - -/* POSIX 1003.1e (draft 17) */ -# ifdef HAVE_ACL_GET_FD -/* Most platforms have a 1-argument acl_get_fd, only OSF/1 has a 2-argument - macro(!). */ -# if HAVE_ACL_FREE_TEXT /* OSF/1 */ -ACL_INTERNAL_INLINE acl_t -rpl_acl_get_fd (int fd) -{ - return acl_get_fd (fd, ACL_TYPE_ACCESS); -} -# undef acl_get_fd -# define acl_get_fd rpl_acl_get_fd -# endif -# else -# define HAVE_ACL_GET_FD false -# undef acl_get_fd -# define acl_get_fd(fd) (NULL) -# endif - -/* POSIX 1003.1e (draft 17) */ -# ifdef HAVE_ACL_SET_FD -/* Most platforms have a 2-argument acl_set_fd, only OSF/1 has a 3-argument - macro(!). */ -# if HAVE_ACL_FREE_TEXT /* OSF/1 */ -ACL_INTERNAL_INLINE int -rpl_acl_set_fd (int fd, acl_t acl) -{ - return acl_set_fd (fd, ACL_TYPE_ACCESS, acl); -} -# undef acl_set_fd -# define acl_set_fd rpl_acl_set_fd -# endif -# else -# define HAVE_ACL_SET_FD false -# undef acl_set_fd -# define acl_set_fd(fd, acl) (-1) -# endif - -/* POSIX 1003.1e (draft 13) */ -# if ! HAVE_ACL_FREE_TEXT -# define acl_free_text(buf) acl_free (buf) -# endif - -/* Linux-specific */ -/* Cygwin >= 2.5 implements this function, but it returns 1 for all - directories, thus is unusable. */ -# if !defined HAVE_ACL_EXTENDED_FILE || defined __CYGWIN__ -# undef HAVE_ACL_EXTENDED_FILE -# define HAVE_ACL_EXTENDED_FILE false -# define acl_extended_file(name) (-1) -# endif - -# if ! defined HAVE_ACL_FROM_MODE && ! defined HAVE_ACL_FROM_TEXT -# define acl_from_mode (NULL) -# endif - -/* Set to 0 if a file's mode is stored independently from the ACL. */ -# if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */ -# define MODE_INSIDE_ACL 0 -# endif - -/* Return the number of entries in ACL. - Return -1 and set errno upon failure to determine it. */ -/* Define a replacement for acl_entries if needed. (Only Linux has it.) */ -# if !HAVE_ACL_ENTRIES -# define acl_entries rpl_acl_entries -extern int acl_entries (acl_t); -# endif - -# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ -/* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. - Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial. */ -extern int acl_extended_nontrivial (acl_t); -# else -/* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS. - Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. - Return -1 and set errno upon failure to determine it. */ -extern int acl_access_nontrivial (acl_t); - -/* ACL is an ACL, from a file, stored as type ACL_TYPE_DEFAULT. - Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. - Return -1 and set errno upon failure to determine it. */ -extern int acl_default_nontrivial (acl_t); -# endif - -# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ - -/* Set to 0 if a file's mode is stored independently from the ACL. */ -# if defined __CYGWIN__ /* Cygwin */ -# define MODE_INSIDE_ACL 0 -# endif - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, aclent_t *entries) _GL_ATTRIBUTE_PURE; - -# ifdef ACE_GETACL /* Solaris 10 */ - -/* Test an ACL retrieved with ACE_GETACL. - Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_ace_nontrivial (int count, ace_t *entries) _GL_ATTRIBUTE_PURE; - -/* Definitions for when the built executable is executed on Solaris 10 - (newer version) or Solaris 11. */ -/* For a_type. */ -# define OLD_ALLOW 0 -# define OLD_DENY 1 -# define NEW_ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */ -# define NEW_ACE_ACCESS_DENIED_ACE_TYPE 1 /* replaces DENY */ -/* For a_flags. */ -# define OLD_ACE_OWNER 0x0100 -# define OLD_ACE_GROUP 0x0200 -# define OLD_ACE_OTHER 0x0400 -# define NEW_ACE_OWNER 0x1000 -# define NEW_ACE_GROUP 0x2000 -# define NEW_ACE_IDENTIFIER_GROUP 0x0040 -# define NEW_ACE_EVERYONE 0x4000 -/* For a_access_mask. */ -# define NEW_ACE_READ_DATA 0x001 /* corresponds to 'r' */ -# define NEW_ACE_WRITE_DATA 0x002 /* corresponds to 'w' */ -# define NEW_ACE_APPEND_DATA 0x004 -# define NEW_ACE_READ_NAMED_ATTRS 0x008 -# define NEW_ACE_WRITE_NAMED_ATTRS 0x010 -# define NEW_ACE_EXECUTE 0x020 -# define NEW_ACE_DELETE_CHILD 0x040 -# define NEW_ACE_READ_ATTRIBUTES 0x080 -# define NEW_ACE_WRITE_ATTRIBUTES 0x100 -# define NEW_ACE_DELETE 0x10000 -# define NEW_ACE_READ_ACL 0x20000 -# define NEW_ACE_WRITE_ACL 0x40000 -# define NEW_ACE_WRITE_OWNER 0x80000 -# define NEW_ACE_SYNCHRONIZE 0x100000 - -# endif - -# elif HAVE_GETACL /* HP-UX */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, struct acl_entry *entries); - -# if HAVE_ACLV_H /* HP-UX >= 11.11 */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int aclv_nontrivial (int count, struct acl *entries); - -# endif - -# elif HAVE_ACLX_GET && 0 /* AIX */ - -/* TODO */ - -# elif HAVE_STATACL /* older AIX */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (struct acl *a); - -# elif HAVE_ACLSORT /* NonStop Kernel */ - -/* Return 1 if the given ACL is non-trivial. - Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ -extern int acl_nontrivial (int count, struct acl *entries); - -# endif - -/* Set to 1 if a file's mode is implicit by the ACL. */ -# ifndef MODE_INSIDE_ACL -# define MODE_INSIDE_ACL 1 -# endif - -#endif - -struct permission_context { - mode_t mode; -#if USE_ACL -# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - acl_t acl; -# if !HAVE_ACL_TYPE_EXTENDED - acl_t default_acl; -# endif - bool acls_not_supported; - -# elif defined GETACL /* Solaris, Cygwin < 2.5 */ - int count; - aclent_t *entries; -# ifdef ACE_GETACL - int ace_count; - ace_t *ace_entries; -# endif - -# elif HAVE_GETACL /* HP-UX */ - struct acl_entry entries[NACLENTRIES]; - int count; -# if HAVE_ACLV_H - struct acl aclv_entries[NACLVENTRIES]; - int aclv_count; -# endif - -# elif HAVE_STATACL /* older AIX */ - union { struct acl a; char room[4096]; } u; - bool have_u; - -# elif HAVE_ACLSORT /* NonStop Kernel */ - struct acl entries[NACLENTRIES]; - int count; - -# endif -#endif -}; - -int get_permissions (const char *, int, mode_t, struct permission_context *); -int set_permissions (struct permission_context *, const char *, int); -void free_permission_context (struct permission_context *); - -_GL_INLINE_HEADER_END diff --git a/xcompile/lib/acl.h b/xcompile/lib/acl.h deleted file mode 100644 index 58e5797179e..00000000000 --- a/xcompile/lib/acl.h +++ /dev/null @@ -1,34 +0,0 @@ -/* acl.c - access control lists - - Copyright (C) 2002, 2008-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert. */ - -#ifndef _GL_ACL_H -#define _GL_ACL_H 1 - -#include -#include - -bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; -int file_has_acl (char const *, struct stat const *); -int qset_acl (char const *, int, mode_t); -int set_acl (char const *, int, mode_t); -int qcopy_acl (char const *, int, char const *, int, mode_t); -int copy_acl (char const *, int, char const *, int, mode_t); -int chmod_or_fchmod (char const *, int, mode_t); - -#endif diff --git a/xcompile/lib/acl_entries.c b/xcompile/lib/acl_entries.c deleted file mode 100644 index a59ace3f404..00000000000 --- a/xcompile/lib/acl_entries.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Return the number of entries in an ACL. - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert and Andreas Gruenbacher. */ - -#include - -#include "acl-internal.h" - -/* This file assumes POSIX-draft like ACLs - (Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5). */ - -/* Return the number of entries in ACL. - Return -1 and set errno upon failure to determine it. */ - -int -acl_entries (acl_t acl) -{ - int count = 0; - - if (acl != NULL) - { -#if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD, Mac OS X, Cygwin >= 2.5 */ -# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - /* acl_get_entry returns 0 when it successfully fetches an entry, - and -1/EINVAL at the end. */ - acl_entry_t ace; - int got_one; - - for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); - got_one >= 0; - got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) - count++; -# else /* Linux, FreeBSD, Cygwin >= 2.5 */ - /* acl_get_entry returns 1 when it successfully fetches an entry, - and 0 at the end. */ - acl_entry_t ace; - int got_one; - - for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace); - got_one > 0; - got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace)) - count++; - if (got_one < 0) - return -1; -# endif -#else /* IRIX, Tru64 */ -# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */ - /* Don't use acl_get_entry: it is undocumented. */ - count = acl->acl_cnt; -# endif -# if HAVE_ACL_FREE_TEXT /* Tru64 */ - /* Don't use acl_get_entry: it takes only one argument and does not - work. */ - count = acl->acl_num; -# endif -#endif - } - - return count; -} diff --git a/xcompile/lib/af_alg.h b/xcompile/lib/af_alg.h deleted file mode 100644 index e8ffb3f7a09..00000000000 --- a/xcompile/lib/af_alg.h +++ /dev/null @@ -1,115 +0,0 @@ -/* af_alg.h - Compute message digests from file streams and buffers. - Copyright (C) 2018-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Matteo Croce , 2018. - Documentation by Bruno Haible , 2018. */ - -/* Declare specific functions for computing message digests - using the Linux kernel crypto API, if available. This kernel API gives - access to specialized crypto instructions (that would also be available - in user space) or to crypto devices (not directly available in user space). - - For a more complete set of facilities that use the Linux kernel crypto API, - look at libkcapi. */ - -#ifndef AF_ALG_H -# define AF_ALG_H 1 - -# include -# include - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_LINUX_CRYPTO_API - -/* Compute a message digest of a memory region. - - The memory region starts at BUFFER and is LEN bytes long. - - ALG is the message digest algorithm; see the file /proc/crypto. - - RESBLOCK points to a block of HASHLEN bytes, for the result. - HASHLEN must be the length of the message digest, in bytes, in particular: - - alg | hashlen - -------+-------- - md5 | 16 - sha1 | 20 - sha224 | 28 - sha256 | 32 - sha384 | 48 - sha512 | 64 - - If successful, fill RESBLOCK and return 0. - Upon failure, return a negated error number. */ -int -afalg_buffer (const char *buffer, size_t len, const char *alg, - void *resblock, ssize_t hashlen); - -/* Compute a message digest of data read from STREAM. - - STREAM is an open file stream. The last operation on STREAM should - not be 'ungetc', and if STREAM is also open for writing it should - have been fflushed since its last write. Read from the current - position to the end of STREAM. Handle regular files efficiently. - - ALG is the message digest algorithm; see the file /proc/crypto. - - RESBLOCK points to a block of HASHLEN bytes, for the result. - HASHLEN must be the length of the message digest, in bytes, in particular: - - alg | hashlen - -------+-------- - md5 | 16 - sha1 | 20 - sha224 | 28 - sha256 | 32 - sha384 | 48 - sha512 | 64 - - If successful, fill RESBLOCK and return 0. - Upon failure, return a negated error number. - Unless returning 0 or -EIO, restore STREAM's file position so that - the caller can fall back on some other method. */ -int -afalg_stream (FILE *stream, const char *alg, - void *resblock, ssize_t hashlen); - -# else - -static inline int -afalg_buffer (const char *buffer, size_t len, const char *alg, - void *resblock, ssize_t hashlen) -{ - return -EAFNOSUPPORT; -} - -static inline int -afalg_stream (FILE *stream, const char *alg, - void *resblock, ssize_t hashlen) -{ - return -EAFNOSUPPORT; -} - -# endif - -# ifdef __cplusplus -} -# endif - -#endif /* AF_ALG_H */ diff --git a/xcompile/lib/alloca.in.h b/xcompile/lib/alloca.in.h deleted file mode 100644 index a1bb3d758dc..00000000000 --- a/xcompile/lib/alloca.in.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Memory allocation on the stack. - - Copyright (C) 1995, 1999, 2001-2004, 2006-2023 Free Software Foundation, - Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H - means there is a real alloca function. */ -#ifndef _GL_ALLOCA_H -#define _GL_ALLOCA_H - -/* alloca (N) returns a pointer to N bytes of memory - allocated on the stack, which will last until the function returns. - Use of alloca should be avoided: - - inside arguments of function calls - undefined behaviour, - - in inline functions - the allocation may actually last until the - calling function returns, - - for huge N (say, N >= 65536) - you never know how large (or small) - the stack is, and when the stack cannot fulfill the memory allocation - request, the program just crashes. - */ - -#ifndef alloca - /* Some version of mingw have an that causes trouble when - included after 'alloca' gets defined as a macro. As a workaround, - include this first and define 'alloca' as a macro afterwards - if needed. */ -# if defined __GNUC__ && (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@ -# include_next -# endif -#endif -#ifndef alloca -# if defined __GNUC__ || (__clang_major__ >= 4) -# define alloca __builtin_alloca -# elif defined _AIX -# define alloca __alloca -# elif defined _MSC_VER -# include -# define alloca _alloca -# elif defined __DECC && defined __VMS -# define alloca __ALLOCA -# elif defined __TANDEM && defined _TNS_E_TARGET -# ifdef __cplusplus -extern "C" -# endif -void *_alloca (unsigned short); -# pragma intrinsic (_alloca) -# define alloca _alloca -# elif defined __MVS__ -# include -# else -# include -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -# endif -#endif - -#endif /* _GL_ALLOCA_H */ diff --git a/xcompile/lib/allocator.c b/xcompile/lib/allocator.c deleted file mode 100644 index 922be1fce8d..00000000000 --- a/xcompile/lib/allocator.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Memory allocators such as malloc+free. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#define _GL_USE_STDLIB_ALLOC 1 -#include -#include "allocator.h" -#include -struct allocator const stdlib_allocator = { malloc, realloc, free, NULL }; diff --git a/xcompile/lib/allocator.h b/xcompile/lib/allocator.h deleted file mode 100644 index 0c830d01cda..00000000000 --- a/xcompile/lib/allocator.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Memory allocators such as malloc+free. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef _GL_ALLOCATOR_H -#define _GL_ALLOCATOR_H - -#include - -/* An object describing a memory allocator family. */ - -struct allocator -{ - /* Do not use GCC attributes such as __attribute__ ((malloc)) with - the function types pointed at by these members, because these - attributes do not work with pointers to functions. See - . */ - - /* Call ALLOCATE to allocate memory, like 'malloc'. On failure ALLOCATE - should return NULL, though not necessarily set errno. When given - a zero size it may return NULL even if successful. */ - void *(*allocate) (size_t); - - /* If nonnull, call REALLOCATE to reallocate memory, like 'realloc'. - On failure REALLOCATE should return NULL, though not necessarily set - errno. When given a zero size it may return NULL even if - successful. */ - void *(*reallocate) (void *, size_t); - - /* Call FREE to free memory, like 'free'. */ - void (*free) (void *); - - /* If nonnull, call DIE (SIZE) if MALLOC (SIZE) or REALLOC (..., - SIZE) fails. DIE should not return. SIZE should equal SIZE_MAX - if size_t overflow was detected while calculating sizes to be - passed to MALLOC or REALLOC. */ - void (*die) (size_t); -}; - -/* An allocator using the stdlib functions and a null DIE function. */ -extern struct allocator const stdlib_allocator; - -#endif /* _GL_ALLOCATOR_H */ diff --git a/xcompile/lib/arg-nonnull.h b/xcompile/lib/arg-nonnull.h deleted file mode 100644 index 9498ae1f7da..00000000000 --- a/xcompile/lib/arg-nonnull.h +++ /dev/null @@ -1,26 +0,0 @@ -/* A C macro for declaring that specific arguments must not be NULL. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This program 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that 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 program. If not, see . */ - -/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools - that the values passed as arguments n, ..., m must be non-NULL pointers. - n = 1 stands for the first argument, n = 2 for the second argument etc. */ -#ifndef _GL_ARG_NONNULL -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__ -# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) -# else -# define _GL_ARG_NONNULL(params) -# endif -#endif diff --git a/xcompile/lib/assert.in.h b/xcompile/lib/assert.in.h deleted file mode 100644 index b0ab99c776e..00000000000 --- a/xcompile/lib/assert.in.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Substitute for and wrapper around - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Do not guard the include, since is supposed to define - the assert macro each time it is included. */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#@INCLUDE_NEXT@ @NEXT_ASSERT_H@ - -/* The definition of static_assert is copied here. */ diff --git a/xcompile/lib/at-func.c b/xcompile/lib/at-func.c deleted file mode 100644 index 13e3fb32056..00000000000 --- a/xcompile/lib/at-func.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Define at-style functions like fstatat, unlinkat, fchownat, etc. - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Jim Meyering */ - -#include "filename.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ - -#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD -# include -# ifndef ENOTSUP -# define ENOTSUP EINVAL -# endif -#else -# include "openat.h" -# include "openat-priv.h" -# include "save-cwd.h" -#endif - -#ifdef AT_FUNC_USE_F1_COND -# define CALL_FUNC(F) \ - (flag == AT_FUNC_USE_F1_COND \ - ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ - : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) -# define VALIDATE_FLAG(F) \ - if (flag & ~AT_FUNC_USE_F1_COND) \ - { \ - errno = EINVAL; \ - return FUNC_FAIL; \ - } -#else -# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) -# define VALIDATE_FLAG(F) /* empty */ -#endif - -#ifdef AT_FUNC_RESULT -# define FUNC_RESULT AT_FUNC_RESULT -#else -# define FUNC_RESULT int -#endif - -#ifdef AT_FUNC_FAIL -# define FUNC_FAIL AT_FUNC_FAIL -#else -# define FUNC_FAIL -1 -#endif - -/* Call AT_FUNC_F1 to operate on FILE, which is in the directory - open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, - AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag; - call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than - AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT - or AT_FUNC_FAIL are defined. If possible, do it without changing the - working directory. Otherwise, resort to using save_cwd/fchdir, - then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd - fails, then give a diagnostic and exit nonzero. */ -FUNC_RESULT -AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) -{ - VALIDATE_FLAG (flag); - - if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) - return CALL_FUNC (file); - -#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD - errno = ENOTSUP; - return FUNC_FAIL; -#else - { - /* Be careful to choose names unlikely to conflict with - AT_FUNC_POST_FILE_PARAM_DECLS. */ - struct saved_cwd saved_cwd; - int saved_errno; - FUNC_RESULT err; - - { - char proc_buf[OPENAT_BUFFER_SIZE]; - char *proc_file = openat_proc_name (proc_buf, fd, file); - if (proc_file) - { - FUNC_RESULT proc_result = CALL_FUNC (proc_file); - int proc_errno = errno; - if (proc_file != proc_buf) - free (proc_file); - /* If the syscall succeeds, or if it fails with an unexpected - errno value, then return right away. Otherwise, fall through - and resort to using save_cwd/restore_cwd. */ - if (FUNC_FAIL != proc_result) - return proc_result; - if (! EXPECTED_ERRNO (proc_errno)) - { - errno = proc_errno; - return proc_result; - } - } - } - - if (save_cwd (&saved_cwd) != 0) - openat_save_fail (errno); - if (0 <= fd && fd == saved_cwd.desc) - { - /* If saving the working directory collides with the user's - requested fd, then the user's fd must have been closed to - begin with. */ - free_cwd (&saved_cwd); - errno = EBADF; - return FUNC_FAIL; - } - - if (fchdir (fd) != 0) - { - saved_errno = errno; - free_cwd (&saved_cwd); - errno = saved_errno; - return FUNC_FAIL; - } - - err = CALL_FUNC (file); - saved_errno = (err == FUNC_FAIL ? errno : 0); - - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); - - free_cwd (&saved_cwd); - - if (saved_errno) - errno = saved_errno; - return err; - } -#endif -} -#undef CALL_FUNC -#undef FUNC_RESULT -#undef FUNC_FAIL diff --git a/xcompile/lib/attribute.h b/xcompile/lib/attribute.h deleted file mode 100644 index 130644d8798..00000000000 --- a/xcompile/lib/attribute.h +++ /dev/null @@ -1,226 +0,0 @@ -/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers - - Copyright 2020-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_* - macros used within Gnulib. */ - -/* These attributes can be placed in two ways: - - At the start of a declaration (i.e. even before storage-class - specifiers!); then they apply to all entities that are declared - by the declaration. - - Immediately after the name of an entity being declared by the - declaration; then they apply to that entity only. */ - -#ifndef _GL_ATTRIBUTE_H -#define _GL_ATTRIBUTE_H - - -/* This file defines two types of attributes: - * C23 standard attributes. These have macro names that do not begin with - 'ATTRIBUTE_'. - * Selected GCC attributes; see: - https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html - https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html - https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html - These names begin with 'ATTRIBUTE_' to avoid name clashes. */ - - -/* =============== Attributes for specific kinds of functions =============== */ - -/* Attributes for functions that should not be used. */ - -/* Warn if the entity is used. */ -/* Applies to: - - function, variable, - - struct, union, struct/union member, - - enumeration, enumeration item, - - typedef, - in C++ also: namespace, class, template specialization. */ -#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED - -/* If a function call is not optimized way, warn with MSG. */ -/* Applies to: functions. */ -#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg) - -/* If a function call is not optimized way, report an error with MSG. */ -/* Applies to: functions. */ -#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg) - - -/* Attributes for memory-allocating functions. */ - -/* The function returns a pointer to freshly allocated memory. */ -/* Applies to: functions. */ -#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC - -/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function - is the size of the returned memory block. - ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments - to determine the size of the returned memory block. */ -/* Applies to: function, pointer to function, function types. */ -#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args) - -/* ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers - that can be freed by passing them as the Ith argument to the - function F. - ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that - can be freed via 'free'; it can be used only after declaring 'free'. */ -/* Applies to: functions. Cannot be used on inline functions. */ -#define ATTRIBUTE_DEALLOC(f, i) _GL_ATTRIBUTE_DEALLOC(f, i) -#define ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC_FREE - -/* Attributes for variadic functions. */ - -/* The variadic function expects a trailing NULL argument. - ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99). - ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */ -/* Applies to: functions. */ -#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos) - - -/* ================== Attributes for compiler diagnostics ================== */ - -/* Attributes that help the compiler diagnose programmer mistakes. - Some of them may also help for some compiler optimizations. */ - -/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) - - The STRING-INDEXth function argument is a format string of style - ARCHETYPE, which is one of: - printf, gnu_printf - scanf, gnu_scanf, - strftime, gnu_strftime, - strfmon, - or the same thing prefixed and suffixed with '__'. - If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK - are suitable for the format string. */ -/* Applies to: functions. */ -#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec) - -/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL. - ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */ -/* Applies to: functions. */ -#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args) - -/* The function's return value is a non-NULL pointer. */ -/* Applies to: functions. */ -#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL - -/* Warn if the caller does not use the return value, - unless the caller uses something like ignore_value. */ -/* Applies to: function, enumeration, class. */ -#define NODISCARD _GL_ATTRIBUTE_NODISCARD - - -/* Attributes that disable false alarms when the compiler diagnoses - programmer "mistakes". */ - -/* Do not warn if the entity is not used. */ -/* Applies to: - - function, variable, - - struct, union, struct/union member, - - enumeration, enumeration item, - - typedef, - in C++ also: class. */ -#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED - -/* The contents of a character array is not meant to be NUL-terminated. */ -/* Applies to: struct/union members and variables that are arrays of element - type '[[un]signed] char'. */ -#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING - -/* Do not warn if control flow falls through to the immediately - following 'case' or 'default' label. */ -/* Applies to: Empty statement (;), inside a 'switch' statement. */ -#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH - - -/* ================== Attributes for debugging information ================== */ - -/* Attributes regarding debugging information emitted by the compiler. */ - -/* Omit the function from stack traces when debugging. */ -/* Applies to: function. */ -#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL - -/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */ -/* Applies to: functions, variables. */ -#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE - - -/* ========== Attributes that mainly direct compiler optimizations ========== */ - -/* The function does not throw exceptions. */ -/* Applies to: functions. */ -#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW - -/* Do not inline the function. */ -/* Applies to: functions. */ -#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE - -/* Always inline the function, and report an error if the compiler - cannot inline. */ -/* Applies to: function. */ -#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE - -/* It is OK for a compiler to omit duplicate calls with the same arguments. - This attribute is safe for a function that neither depends on - nor affects observable state, and always returns exactly once - - e.g., does not loop forever, and does not call longjmp. - (This attribute is stricter than ATTRIBUTE_PURE.) */ -/* Applies to: functions. */ -#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST - -/* It is OK for a compiler to omit duplicate calls with the same - arguments if observable state is not changed between calls. - This attribute is safe for a function that does not affect - observable state, and always returns exactly once. - (This attribute is looser than ATTRIBUTE_CONST.) */ -/* Applies to: functions. */ -#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE - -/* The function is rarely executed. */ -/* Applies to: functions. */ -#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD - -/* If called from some other compilation unit, the function executes - code from that unit only by return or by exception handling, - letting the compiler optimize that unit more aggressively. */ -/* Applies to: functions. */ -#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF - -/* For struct members: The member has the smallest possible alignment. - For struct, union, class: All members have the smallest possible alignment, - minimizing the memory required. */ -/* Applies to: struct members, struct, union, - in C++ also: class. */ -#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED - - -/* ================ Attributes that make invalid code valid ================ */ - -/* Attributes that prevent fatal compiler optimizations for code that is not - fully ISO C compliant. */ - -/* Pointers to the type may point to the same storage as pointers to - other types, thus disabling strict aliasing optimization. */ -/* Applies to: types. */ -#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS - - -#endif /* _GL_ATTRIBUTE_H */ diff --git a/xcompile/lib/binary-io.c b/xcompile/lib/binary-io.c deleted file mode 100644 index 28a9e6ed69c..00000000000 --- a/xcompile/lib/binary-io.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Binary mode I/O. - Copyright 2017-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define BINARY_IO_INLINE _GL_EXTERN_INLINE -#include "binary-io.h" - -#if defined __DJGPP__ || defined __EMX__ -# include - -int -set_binary_mode (int fd, int mode) -{ - if (isatty (fd)) - /* If FD refers to a console (not a pipe, not a regular file), - O_TEXT is the only reasonable mode, both on input and on output. - Silently ignore the request. If we were to return -1 here, - all programs that use xset_binary_mode would fail when run - with console input or console output. */ - return O_TEXT; - else - return __gl_setmode (fd, mode); -} - -#endif diff --git a/xcompile/lib/binary-io.h b/xcompile/lib/binary-io.h deleted file mode 100644 index 6f4db253354..00000000000 --- a/xcompile/lib/binary-io.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Binary mode I/O. - Copyright (C) 2001, 2003, 2005, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _BINARY_H -#define _BINARY_H - -/* For systems that distinguish between text and binary I/O. - O_BINARY is guaranteed by the gnulib . */ -#include - -/* The MSVC7 doesn't like to be included after '#define fileno ...', - so we include it here first. */ -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef BINARY_IO_INLINE -# define BINARY_IO_INLINE _GL_INLINE -#endif - -#if O_BINARY -# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__ -# include /* declares setmode() */ -# define __gl_setmode setmode -# else -# define __gl_setmode _setmode -# undef fileno -# define fileno _fileno -# endif -#else - /* On reasonable systems, binary I/O is the only choice. */ - /* Use a function rather than a macro, to avoid gcc warnings - "warning: statement with no effect". */ -BINARY_IO_INLINE int -__gl_setmode (_GL_UNUSED int fd, _GL_UNUSED int mode) -{ - return O_BINARY; -} -#endif - -/* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY. - Return the old mode if successful, -1 (setting errno) on failure. - Ordinarily this function would be called 'setmode', since that is - its old name on MS-Windows, but it is called 'set_binary_mode' here - to avoid colliding with a BSD function of another name. */ - -#if defined __DJGPP__ || defined __EMX__ -extern int set_binary_mode (int fd, int mode); -#else -BINARY_IO_INLINE int -set_binary_mode (int fd, int mode) -{ - return __gl_setmode (fd, mode); -} -#endif - -/* This macro is obsolescent. */ -#define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY)) - -_GL_INLINE_HEADER_END - -#endif /* _BINARY_H */ diff --git a/xcompile/lib/byteswap.in.h b/xcompile/lib/byteswap.in.h deleted file mode 100644 index e61be27e917..00000000000 --- a/xcompile/lib/byteswap.in.h +++ /dev/null @@ -1,44 +0,0 @@ -/* byteswap.h - Byte swapping - Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc. - Written by Oskar Liljeblad , 2005. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GL_BYTESWAP_H -#define _GL_BYTESWAP_H - -/* Given an unsigned 16-bit argument X, return the value corresponding to - X with reversed byte order. */ -#define bswap_16(x) ((((x) & 0x00FF) << 8) | \ - (((x) & 0xFF00) >> 8)) - -/* Given an unsigned 32-bit argument X, return the value corresponding to - X with reversed byte order. */ -#define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ - (((x) & 0x0000FF00) << 8) | \ - (((x) & 0x00FF0000) >> 8) | \ - (((x) & 0xFF000000) >> 24)) - -/* Given an unsigned 64-bit argument X, return the value corresponding to - X with reversed byte order. */ -#define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \ - (((x) & 0x000000000000FF00ULL) << 40) | \ - (((x) & 0x0000000000FF0000ULL) << 24) | \ - (((x) & 0x00000000FF000000ULL) << 8) | \ - (((x) & 0x000000FF00000000ULL) >> 8) | \ - (((x) & 0x0000FF0000000000ULL) >> 24) | \ - (((x) & 0x00FF000000000000ULL) >> 40) | \ - (((x) & 0xFF00000000000000ULL) >> 56)) - -#endif /* _GL_BYTESWAP_H */ diff --git a/xcompile/lib/c++defs.h b/xcompile/lib/c++defs.h deleted file mode 100644 index 8ad46951ad4..00000000000 --- a/xcompile/lib/c++defs.h +++ /dev/null @@ -1,331 +0,0 @@ -/* C++ compatible function declaration macros. - Copyright (C) 2010-2023 Free Software Foundation, Inc. - - This program 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GL_CXXDEFS_H -#define _GL_CXXDEFS_H - -/* Begin/end the GNULIB_NAMESPACE namespace. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_BEGIN_NAMESPACE namespace GNULIB_NAMESPACE { -# define _GL_END_NAMESPACE } -#else -# define _GL_BEGIN_NAMESPACE -# define _GL_END_NAMESPACE -#endif - -/* The three most frequent use cases of these macros are: - - * For providing a substitute for a function that is missing on some - platforms, but is declared and works fine on the platforms on which - it exists: - - #if @GNULIB_FOO@ - # if !@HAVE_FOO@ - _GL_FUNCDECL_SYS (foo, ...); - # endif - _GL_CXXALIAS_SYS (foo, ...); - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif - - * For providing a replacement for a function that exists on all platforms, - but is broken/insufficient and needs to be replaced on some platforms: - - #if @GNULIB_FOO@ - # if @REPLACE_FOO@ - # if !(defined __cplusplus && defined GNULIB_NAMESPACE) - # undef foo - # define foo rpl_foo - # endif - _GL_FUNCDECL_RPL (foo, ...); - _GL_CXXALIAS_RPL (foo, ...); - # else - _GL_CXXALIAS_SYS (foo, ...); - # endif - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif - - * For providing a replacement for a function that exists on some platforms - but is broken/insufficient and needs to be replaced on some of them and - is additionally either missing or undeclared on some other platforms: - - #if @GNULIB_FOO@ - # if @REPLACE_FOO@ - # if !(defined __cplusplus && defined GNULIB_NAMESPACE) - # undef foo - # define foo rpl_foo - # endif - _GL_FUNCDECL_RPL (foo, ...); - _GL_CXXALIAS_RPL (foo, ...); - # else - # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ - _GL_FUNCDECL_SYS (foo, ...); - # endif - _GL_CXXALIAS_SYS (foo, ...); - # endif - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif -*/ - -/* _GL_EXTERN_C declaration; - performs the declaration with C linkage. */ -#if defined __cplusplus -# define _GL_EXTERN_C extern "C" -#else -# define _GL_EXTERN_C extern -#endif - -/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); - declares a replacement function, named rpl_func, with the given prototype, - consisting of return type, parameters, and attributes. - Example: - _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) - _GL_ARG_NONNULL ((1))); - */ -#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ - _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) -#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C rettype rpl_func parameters_and_attributes - -/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); - declares the system function, named func, with the given prototype, - consisting of return type, parameters, and attributes. - Example: - _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) - _GL_ARG_NONNULL ((1))); - */ -#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C rettype func parameters_and_attributes - -/* _GL_CXXALIAS_RPL (func, rettype, parameters); - declares a C++ alias called GNULIB_NAMESPACE::func - that redirects to rpl_func, if GNULIB_NAMESPACE is defined. - Example: - _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); - - Wrapping rpl_func in an object with an inline conversion operator - avoids a reference to rpl_func unless GNULIB_NAMESPACE::func is - actually used in the program. */ -#define _GL_CXXALIAS_RPL(func,rettype,parameters) \ - _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static const struct _gl_ ## func ## _wrapper \ - { \ - typedef rettype (*type) parameters; \ - \ - inline operator type () const \ - { \ - return ::rpl_func; \ - } \ - } func = {}; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_MDA (func, rettype, parameters); - is to be used when func is a Microsoft deprecated alias, on native Windows. - It declares a C++ alias called GNULIB_NAMESPACE::func - that redirects to _func, if GNULIB_NAMESPACE is defined. - Example: - _GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); - */ -#define _GL_CXXALIAS_MDA(func,rettype,parameters) \ - _GL_CXXALIAS_RPL_1 (func, _##func, rettype, parameters) - -/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); - is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); - except that the C function rpl_func may have a slightly different - declaration. A cast is used to silence the "invalid conversion" error - that would otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static const struct _gl_ ## func ## _wrapper \ - { \ - typedef rettype (*type) parameters; \ - \ - inline operator type () const \ - { \ - return reinterpret_cast(::rpl_func); \ - } \ - } func = {}; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_MDA_CAST (func, rettype, parameters); - is like _GL_CXXALIAS_MDA (func, rettype, parameters); - except that the C function func may have a slightly different declaration. - A cast is used to silence the "invalid conversion" error that would - otherwise occur. */ -#define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \ - _GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters) - -/* _GL_CXXALIAS_SYS (func, rettype, parameters); - declares a C++ alias called GNULIB_NAMESPACE::func - that redirects to the system provided function func, if GNULIB_NAMESPACE - is defined. - Example: - _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); - - Wrapping func in an object with an inline conversion operator - avoids a reference to func unless GNULIB_NAMESPACE::func is - actually used in the program. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static const struct _gl_ ## func ## _wrapper \ - { \ - typedef rettype (*type) parameters; \ - \ - inline operator type () const \ - { \ - return ::func; \ - } \ - } func = {}; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); - is like _GL_CXXALIAS_SYS (func, rettype, parameters); - except that the C function func may have a slightly different declaration. - A cast is used to silence the "invalid conversion" error that would - otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static const struct _gl_ ## func ## _wrapper \ - { \ - typedef rettype (*type) parameters; \ - \ - inline operator type () const \ - { \ - return reinterpret_cast(::func); \ - } \ - } func = {}; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); - is like _GL_CXXALIAS_SYS (func, rettype, parameters); - except that the C function is picked among a set of overloaded functions, - namely the one with rettype2 and parameters2. Two consecutive casts - are used to silence the "cannot find a match" and "invalid conversion" - errors that would otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE - /* The outer cast must be a reinterpret_cast. - The inner cast: When the function is defined as a set of overloaded - functions, it works as a static_cast<>, choosing the designated variant. - When the function is defined as a single variant, it works as a - reinterpret_cast<>. The parenthesized cast syntax works both ways. */ -# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ - namespace GNULIB_NAMESPACE \ - { \ - static const struct _gl_ ## func ## _wrapper \ - { \ - typedef rettype (*type) parameters; \ - \ - inline operator type () const \ - { \ - return reinterpret_cast((rettype2 (*) parameters2)(::func)); \ - } \ - } func = {}; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIASWARN (func); - causes a warning to be emitted when ::func is used but not when - GNULIB_NAMESPACE::func is used. func must be defined without overloaded - variants. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIASWARN(func) \ - _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) -# define _GL_CXXALIASWARN_1(func,namespace) \ - _GL_CXXALIASWARN_2 (func, namespace) -/* To work around GCC bug , - we enable the warning only when not optimizing. */ -# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) -# define _GL_CXXALIASWARN_2(func,namespace) \ - _GL_WARN_ON_USE (func, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -# define _GL_CXXALIASWARN_2(func,namespace) \ - extern __typeof__ (func) func -# else -# define _GL_CXXALIASWARN_2(func,namespace) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -# endif -#else -# define _GL_CXXALIASWARN(func) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); - causes a warning to be emitted when the given overloaded variant of ::func - is used but not when GNULIB_NAMESPACE::func is used. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ - _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ - GNULIB_NAMESPACE) -# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ - _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) -/* To work around GCC bug , - we enable the warning only when not optimizing. */ -# if !(defined __GNUC__ && !defined __clang__ && __OPTIMIZE__) -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - _GL_WARN_ON_USE_CXX (func, rettype, rettype, parameters_and_attributes, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") -# else -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -# endif -#else -# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -#endif /* _GL_CXXDEFS_H */ diff --git a/xcompile/lib/c-ctype.c b/xcompile/lib/c-ctype.c deleted file mode 100644 index a4343f445f0..00000000000 --- a/xcompile/lib/c-ctype.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Character handling in C locale. - - Copyright (C) 2003-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define C_CTYPE_INLINE _GL_EXTERN_INLINE -#include "c-ctype.h" diff --git a/xcompile/lib/c-ctype.h b/xcompile/lib/c-ctype.h deleted file mode 100644 index 35ca83d7d43..00000000000 --- a/xcompile/lib/c-ctype.h +++ /dev/null @@ -1,364 +0,0 @@ -/* Character handling in C locale. - - These functions work like the corresponding functions in , - except that they have the C (POSIX) locale hardwired, whereas the - functions' behaviour depends on the current locale set via - setlocale. - - Copyright (C) 2000-2003, 2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef C_CTYPE_H -#define C_CTYPE_H - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef C_CTYPE_INLINE -# define C_CTYPE_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -/* The functions defined in this file assume the "C" locale and a character - set without diacritics (ASCII-US or EBCDIC-US or something like that). - Even if the "C" locale on a particular system is an extension of the ASCII - character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it - is ISO-8859-1), the functions in this file recognize only the ASCII - characters. */ - - -#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ - && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ - && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ - && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ - && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ - && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ - && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ - && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ - && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ - && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ - && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ - && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ - && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ - && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ - && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ - && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ - && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ - && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ - && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ - && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ - && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ - && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ - && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) -/* The character set is ASCII or one of its variants or extensions, not EBCDIC. - Testing the value of '\n' and '\r' is not relevant. */ -# define C_CTYPE_ASCII 1 -#elif ! (' ' == '\x40' && '0' == '\xf0' \ - && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \ - && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2') -# error "Only ASCII and EBCDIC are supported" -#endif - -#if 'A' < 0 -# error "EBCDIC and char is signed -- not supported" -#endif - -/* Cases for control characters. */ - -#define _C_CTYPE_CNTRL \ - case '\a': case '\b': case '\f': case '\n': \ - case '\r': case '\t': case '\v': \ - _C_CTYPE_OTHER_CNTRL - -/* ASCII control characters other than those with \-letter escapes. */ - -#if C_CTYPE_ASCII -# define _C_CTYPE_OTHER_CNTRL \ - case '\x00': case '\x01': case '\x02': case '\x03': \ - case '\x04': case '\x05': case '\x06': case '\x0e': \ - case '\x0f': case '\x10': case '\x11': case '\x12': \ - case '\x13': case '\x14': case '\x15': case '\x16': \ - case '\x17': case '\x18': case '\x19': case '\x1a': \ - case '\x1b': case '\x1c': case '\x1d': case '\x1e': \ - case '\x1f': case '\x7f' -#else - /* Use EBCDIC code page 1047's assignments for ASCII control chars; - assume all EBCDIC code pages agree about these assignments. */ -# define _C_CTYPE_OTHER_CNTRL \ - case '\x00': case '\x01': case '\x02': case '\x03': \ - case '\x07': case '\x0e': case '\x0f': case '\x10': \ - case '\x11': case '\x12': case '\x13': case '\x18': \ - case '\x19': case '\x1c': case '\x1d': case '\x1e': \ - case '\x1f': case '\x26': case '\x27': case '\x2d': \ - case '\x2e': case '\x32': case '\x37': case '\x3c': \ - case '\x3d': case '\x3f' -#endif - -/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */ - -#define _C_CTYPE_LOWER_A_THRU_F_N(N) \ - case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \ - case 'e' + (N): case 'f' + (N) -#define _C_CTYPE_LOWER_N(N) \ - _C_CTYPE_LOWER_A_THRU_F_N(N): \ - case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \ - case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \ - case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \ - case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \ - case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N) - -/* Cases for hex letters, digits, lower, punct, and upper. */ - -#define _C_CTYPE_A_THRU_F \ - _C_CTYPE_LOWER_A_THRU_F_N (0): \ - _C_CTYPE_LOWER_A_THRU_F_N ('A' - 'a') -#define _C_CTYPE_DIGIT \ - case '0': case '1': case '2': case '3': \ - case '4': case '5': case '6': case '7': \ - case '8': case '9' -#define _C_CTYPE_LOWER _C_CTYPE_LOWER_N (0) -#define _C_CTYPE_PUNCT \ - case '!': case '"': case '#': case '$': \ - case '%': case '&': case '\'': case '(': \ - case ')': case '*': case '+': case ',': \ - case '-': case '.': case '/': case ':': \ - case ';': case '<': case '=': case '>': \ - case '?': case '@': case '[': case '\\': \ - case ']': case '^': case '_': case '`': \ - case '{': case '|': case '}': case '~' -#define _C_CTYPE_UPPER _C_CTYPE_LOWER_N ('A' - 'a') - - -/* Function definitions. */ - -/* Unlike the functions in , which require an argument in the range - of the 'unsigned char' type, the functions here operate on values that are - in the 'unsigned char' range or in the 'char' range. In other words, - when you have a 'char' value, you need to cast it before using it as - argument to a function: - - const char *s = ...; - if (isalpha ((unsigned char) *s)) ... - - but you don't need to cast it for the functions defined in this file: - - const char *s = ...; - if (c_isalpha (*s)) ... - */ - -C_CTYPE_INLINE bool -c_isalnum (int c) -{ - switch (c) - { - _C_CTYPE_DIGIT: - _C_CTYPE_LOWER: - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isalpha (int c) -{ - switch (c) - { - _C_CTYPE_LOWER: - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -/* The function isascii is not locale dependent. - Its use in EBCDIC is questionable. */ -C_CTYPE_INLINE bool -c_isascii (int c) -{ - switch (c) - { - case ' ': - _C_CTYPE_CNTRL: - _C_CTYPE_DIGIT: - _C_CTYPE_LOWER: - _C_CTYPE_PUNCT: - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isblank (int c) -{ - return c == ' ' || c == '\t'; -} - -C_CTYPE_INLINE bool -c_iscntrl (int c) -{ - switch (c) - { - _C_CTYPE_CNTRL: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isdigit (int c) -{ - switch (c) - { - _C_CTYPE_DIGIT: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isgraph (int c) -{ - switch (c) - { - _C_CTYPE_DIGIT: - _C_CTYPE_LOWER: - _C_CTYPE_PUNCT: - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_islower (int c) -{ - switch (c) - { - _C_CTYPE_LOWER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isprint (int c) -{ - switch (c) - { - case ' ': - _C_CTYPE_DIGIT: - _C_CTYPE_LOWER: - _C_CTYPE_PUNCT: - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_ispunct (int c) -{ - switch (c) - { - _C_CTYPE_PUNCT: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isspace (int c) -{ - switch (c) - { - case ' ': case '\t': case '\n': case '\v': case '\f': case '\r': - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isupper (int c) -{ - switch (c) - { - _C_CTYPE_UPPER: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE bool -c_isxdigit (int c) -{ - switch (c) - { - _C_CTYPE_DIGIT: - _C_CTYPE_A_THRU_F: - return true; - default: - return false; - } -} - -C_CTYPE_INLINE int -c_tolower (int c) -{ - switch (c) - { - _C_CTYPE_UPPER: - return c - 'A' + 'a'; - default: - return c; - } -} - -C_CTYPE_INLINE int -c_toupper (int c) -{ - switch (c) - { - _C_CTYPE_LOWER: - return c - 'a' + 'A'; - default: - return c; - } -} - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif /* C_CTYPE_H */ diff --git a/xcompile/lib/c-strcase.h b/xcompile/lib/c-strcase.h deleted file mode 100644 index 9bcca01b27c..00000000000 --- a/xcompile/lib/c-strcase.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Case-insensitive string comparison functions in C locale. - Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef C_STRCASE_H -#define C_STRCASE_H - -#include - - -/* The functions defined in this file assume the "C" locale and a character - set without diacritics (ASCII-US or EBCDIC-US or something like that). - Even if the "C" locale on a particular system is an extension of the ASCII - character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it - is ISO-8859-1), the functions in this file recognize only the ASCII - characters. More precisely, one of the string arguments must be an ASCII - string; the other one can also contain non-ASCII characters (but then - the comparison result will be nonzero). */ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. */ -extern int c_strcasecmp (const char *s1, const char *s2) _GL_ATTRIBUTE_PURE; - -/* Compare no more than N characters of strings S1 and S2, ignoring case, - returning less than, equal to or greater than zero if S1 is - lexicographically less than, equal to or greater than S2. */ -extern int c_strncasecmp (const char *s1, const char *s2, size_t n) - _GL_ATTRIBUTE_PURE; - - -#ifdef __cplusplus -} -#endif - - -#endif /* C_STRCASE_H */ diff --git a/xcompile/lib/c-strcasecmp.c b/xcompile/lib/c-strcasecmp.c deleted file mode 100644 index 8a958dc4fd9..00000000000 --- a/xcompile/lib/c-strcasecmp.c +++ /dev/null @@ -1,56 +0,0 @@ -/* c-strcasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include "c-strcase.h" - -#include - -#include "c-ctype.h" - -int -c_strcasecmp (const char *s1, const char *s2) -{ - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - c1 = c_tolower (*p1); - c2 = c_tolower (*p2); - - if (c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return _GL_CMP (c1, c2); -} diff --git a/xcompile/lib/c-strncasecmp.c b/xcompile/lib/c-strncasecmp.c deleted file mode 100644 index 4ca8c5f4001..00000000000 --- a/xcompile/lib/c-strncasecmp.c +++ /dev/null @@ -1,56 +0,0 @@ -/* c-strncasecmp.c -- case insensitive string comparator in C locale - Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include "c-strcase.h" - -#include - -#include "c-ctype.h" - -int -c_strncasecmp (const char *s1, const char *s2, size_t n) -{ - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2 || n == 0) - return 0; - - do - { - c1 = c_tolower (*p1); - c2 = c_tolower (*p2); - - if (--n == 0 || c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return _GL_CMP (c1, c2); -} diff --git a/xcompile/lib/canonicalize-lgpl.c b/xcompile/lib/canonicalize-lgpl.c deleted file mode 100644 index e701297d84b..00000000000 --- a/xcompile/lib/canonicalize-lgpl.c +++ /dev/null @@ -1,469 +0,0 @@ -/* Return the canonical absolute name of a given file. - Copyright (C) 1996-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc - optimizes away the name == NULL test below. */ -# define _GL_ARG_NONNULL(params) - -# include -#endif - -/* Specification. */ -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef _LIBC -# include -# define GCC_LINT 1 -# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -#else -# define __canonicalize_file_name canonicalize_file_name -# define __realpath realpath -# define __strdup strdup -# include "pathmax.h" -# define __faccessat faccessat -# if defined _WIN32 && !defined __CYGWIN__ -# define __getcwd _getcwd -# elif HAVE_GETCWD -# if IN_RELOCWRAPPER - /* When building the relocatable program wrapper, use the system's getcwd - function, not the gnulib override, otherwise we would get a link error. - */ -# undef getcwd -# endif -# if defined VMS && !defined getcwd - /* We want the directory in Unix syntax, not in VMS syntax. - The gnulib override of 'getcwd' takes 2 arguments; the original VMS - 'getcwd' takes 3 arguments. */ -# define __getcwd(buf, max) getcwd (buf, max, 0) -# else -# define __getcwd getcwd -# endif -# else -# define __getcwd(buf, max) getwd (buf) -# endif -# define __mempcpy mempcpy -# define __pathconf pathconf -# define __rawmemchr rawmemchr -# define __readlink readlink -# if IN_RELOCWRAPPER - /* When building the relocatable program wrapper, use the system's memmove - function, not the gnulib override, otherwise we would get a link error. - */ -# undef memmove -# endif -#endif - -/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */ -#if defined GCC_LINT || defined lint -# define IF_LINT(Code) Code -#else -# define IF_LINT(Code) /* empty */ -#endif - -#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT -# define DOUBLE_SLASH_IS_DISTINCT_ROOT false -#endif - -#if defined _LIBC || !FUNC_REALPATH_WORKS - -/* Return true if FILE's existence can be shown, false (setting errno) - otherwise. Follow symbolic links. */ -static bool -file_accessible (char const *file) -{ -# if defined _LIBC || HAVE_FACCESSAT - return __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS) == 0; -# else - struct stat st; - return stat (file, &st) == 0 || errno == EOVERFLOW; -# endif -} - -/* True if concatenating END as a suffix to a file name means that the - code needs to check that the file name is that of a searchable - directory, since the canonicalize_filename_mode_stk code won't - check this later anyway when it checks an ordinary file name - component within END. END must either be empty, or start with a - slash. */ - -static bool _GL_ATTRIBUTE_PURE -suffix_requires_dir_check (char const *end) -{ - /* If END does not start with a slash, the suffix is OK. */ - while (ISSLASH (*end)) - { - /* Two or more slashes act like a single slash. */ - do - end++; - while (ISSLASH (*end)); - - switch (*end++) - { - default: return false; /* An ordinary file name component is OK. */ - case '\0': return true; /* Trailing "/" is trouble. */ - case '.': break; /* Possibly "." or "..". */ - } - /* Trailing "/.", or "/.." even if not trailing, is trouble. */ - if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1])))) - return true; - } - - return false; -} - -/* Append this to a file name to test whether it is a searchable directory. - On POSIX platforms "/" suffices, but "/./" is sometimes needed on - macOS 10.13 , and should also work on - platforms like AIX 7.2 that need at least "/.". */ - -# if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK -static char const dir_suffix[] = "/"; -# else -static char const dir_suffix[] = "/./"; -# endif - -/* Return true if DIR is a searchable dir, false (setting errno) otherwise. - DIREND points to the NUL byte at the end of the DIR string. - Store garbage into DIREND[0 .. strlen (dir_suffix)]. */ - -static bool -dir_check (char *dir, char *dirend) -{ - strcpy (dirend, dir_suffix); - return file_accessible (dir); -} - -static idx_t -get_path_max (void) -{ -# ifdef PATH_MAX - long int path_max = PATH_MAX; -# else - /* The caller invoked realpath with a null RESOLVED, even though - PATH_MAX is not defined as a constant. The glibc manual says - programs should not do this, and POSIX says the behavior is undefined. - Historically, glibc here used the result of pathconf, or 1024 if that - failed; stay consistent with this (dubious) historical practice. */ - int err = errno; - long int path_max = __pathconf ("/", _PC_PATH_MAX); - __set_errno (err); -# endif - return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX; -} - -/* Scratch buffers used by realpath_stk and managed by __realpath. */ -struct realpath_bufs -{ - struct scratch_buffer rname; - struct scratch_buffer extra; - struct scratch_buffer link; -}; - -static char * -realpath_stk (const char *name, char *resolved, struct realpath_bufs *bufs) -{ - char *dest; - char const *start; - char const *end; - int num_links = 0; - - if (name == NULL) - { - /* As per Single Unix Specification V2 we must return an error if - either parameter is a null pointer. We extend this to allow - the RESOLVED parameter to be NULL in case the we are expected to - allocate the room for the return value. */ - __set_errno (EINVAL); - return NULL; - } - - if (name[0] == '\0') - { - /* As per Single Unix Specification V2 we must return an error if - the name argument points to an empty string. */ - __set_errno (ENOENT); - return NULL; - } - - char *rname = bufs->rname.data; - bool end_in_extra_buffer = false; - bool failed = true; - - /* This is always zero for Posix hosts, but can be 2 for MS-Windows - and MS-DOS X:/foo/bar file names. */ - idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); - - if (!IS_ABSOLUTE_FILE_NAME (name)) - { - while (!__getcwd (bufs->rname.data, bufs->rname.length)) - { - if (errno != ERANGE) - { - dest = rname; - goto error; - } - if (!scratch_buffer_grow (&bufs->rname)) - return NULL; - rname = bufs->rname.data; - } - dest = __rawmemchr (rname, '\0'); - start = name; - prefix_len = FILE_SYSTEM_PREFIX_LEN (rname); - } - else - { - dest = __mempcpy (rname, name, prefix_len); - *dest++ = '/'; - if (DOUBLE_SLASH_IS_DISTINCT_ROOT) - { - if (prefix_len == 0 /* implies ISSLASH (name[0]) */ - && ISSLASH (name[1]) && !ISSLASH (name[2])) - *dest++ = '/'; - *dest = '\0'; - } - start = name + prefix_len; - } - - for ( ; *start; start = end) - { - /* Skip sequence of multiple file name separators. */ - while (ISSLASH (*start)) - ++start; - - /* Find end of component. */ - for (end = start; *end && !ISSLASH (*end); ++end) - /* Nothing. */; - - /* Length of this file name component; it can be zero if a file - name ends in '/'. */ - idx_t startlen = end - start; - - if (startlen == 0) - break; - else if (startlen == 1 && start[0] == '.') - /* nothing */; - else if (startlen == 2 && start[0] == '.' && start[1] == '.') - { - /* Back up to previous component, ignore if at root already. */ - if (dest > rname + prefix_len + 1) - for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) - continue; - if (DOUBLE_SLASH_IS_DISTINCT_ROOT - && dest == rname + 1 && !prefix_len - && ISSLASH (*dest) && !ISSLASH (dest[1])) - dest++; - } - else - { - if (!ISSLASH (dest[-1])) - *dest++ = '/'; - - while (rname + bufs->rname.length - dest - < startlen + sizeof dir_suffix) - { - idx_t dest_offset = dest - rname; - if (!scratch_buffer_grow_preserve (&bufs->rname)) - return NULL; - rname = bufs->rname.data; - dest = rname + dest_offset; - } - - dest = __mempcpy (dest, start, startlen); - *dest = '\0'; - - char *buf; - ssize_t n; - while (true) - { - buf = bufs->link.data; - idx_t bufsize = bufs->link.length; - n = __readlink (rname, buf, bufsize - 1); - if (n < bufsize - 1) - break; - if (!scratch_buffer_grow (&bufs->link)) - return NULL; - } - if (0 <= n) - { - if (++num_links > __eloop_threshold ()) - { - __set_errno (ELOOP); - goto error; - } - - buf[n] = '\0'; - - char *extra_buf = bufs->extra.data; - idx_t end_idx IF_LINT (= 0); - if (end_in_extra_buffer) - end_idx = end - extra_buf; - size_t len = strlen (end); - if (INT_ADD_OVERFLOW (len, n)) - { - __set_errno (ENOMEM); - return NULL; - } - while (bufs->extra.length <= len + n) - { - if (!scratch_buffer_grow_preserve (&bufs->extra)) - return NULL; - extra_buf = bufs->extra.data; - } - if (end_in_extra_buffer) - end = extra_buf + end_idx; - - /* Careful here, end may be a pointer into extra_buf... */ - memmove (&extra_buf[n], end, len + 1); - name = end = memcpy (extra_buf, buf, n); - end_in_extra_buffer = true; - - if (IS_ABSOLUTE_FILE_NAME (buf)) - { - idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); - - dest = __mempcpy (rname, buf, pfxlen); - *dest++ = '/'; /* It's an absolute symlink */ - if (DOUBLE_SLASH_IS_DISTINCT_ROOT) - { - if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen) - *dest++ = '/'; - *dest = '\0'; - } - /* Install the new prefix to be in effect hereafter. */ - prefix_len = pfxlen; - } - else - { - /* Back up to previous component, ignore if at root - already: */ - if (dest > rname + prefix_len + 1) - for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest) - continue; - if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 - && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) - dest++; - } - } - else if (! (suffix_requires_dir_check (end) - ? dir_check (rname, dest) - : errno == EINVAL)) - goto error; - } - } - if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1])) - --dest; - if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len - && ISSLASH (*dest) && !ISSLASH (dest[1])) - dest++; - failed = false; - -error: - *dest++ = '\0'; - if (resolved != NULL) - { - /* Copy the full result on success or partial result if failure was due - to the path not existing or not being accessible. */ - if ((!failed || errno == ENOENT || errno == EACCES) - && dest - rname <= get_path_max ()) - { - strcpy (resolved, rname); - if (failed) - return NULL; - else - return resolved; - } - if (!failed) - __set_errno (ENAMETOOLONG); - return NULL; - } - else - { - if (failed) - return NULL; - else - return __strdup (bufs->rname.data); - } -} - -/* Return the canonical absolute name of file NAME. A canonical name - does not contain any ".", ".." components nor any repeated file name - separators ('/') or symlinks. All file name components must exist. If - RESOLVED is null, the result is malloc'd; otherwise, if the - canonical name is PATH_MAX chars or more, returns null with 'errno' - set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, - returns the name in RESOLVED. If the name cannot be resolved and - RESOLVED is non-NULL, it contains the name of the first component - that cannot be resolved. If the name can be resolved, RESOLVED - holds the same value as the value returned. */ - -char * -__realpath (const char *name, char *resolved) -{ - struct realpath_bufs bufs; - scratch_buffer_init (&bufs.rname); - scratch_buffer_init (&bufs.extra); - scratch_buffer_init (&bufs.link); - char *result = realpath_stk (name, resolved, &bufs); - scratch_buffer_free (&bufs.link); - scratch_buffer_free (&bufs.extra); - scratch_buffer_free (&bufs.rname); - return result; -} -libc_hidden_def (__realpath) -versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); - -#endif /* defined _LIBC || !FUNC_REALPATH_WORKS */ - - -#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) -char * -attribute_compat_text_section -__old_realpath (const char *name, char *resolved) -{ - if (resolved == NULL) - { - __set_errno (EINVAL); - return NULL; - } - - return __realpath (name, resolved); -} -compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); -#endif - - -char * -__canonicalize_file_name (const char *name) -{ - return __realpath (name, NULL); -} -weak_alias (__canonicalize_file_name, canonicalize_file_name) diff --git a/xcompile/lib/careadlinkat.c b/xcompile/lib/careadlinkat.c deleted file mode 100644 index 359d497396c..00000000000 --- a/xcompile/lib/careadlinkat.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Read symbolic links into a buffer without size limitation, relative to fd. - - Copyright (C) 2001, 2003-2004, 2007, 2009-2023 Free Software Foundation, - Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ - -#include - -#include "careadlinkat.h" - -#include "idx.h" -#include "minmax.h" - -#include -#include -#include -#include - -/* Define this independently so that stdint.h is not a prerequisite. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#ifndef SSIZE_MAX -# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) -#endif - -#include "allocator.h" - -enum { STACK_BUF_SIZE = 1024 }; - -/* Act like careadlinkat (see below), with an additional argument - STACK_BUF that can be used as temporary storage. - - If GCC_LINT is defined, do not inline this function with GCC 10.1 - and later, to avoid creating a pointer to the stack that GCC - -Wreturn-local-addr incorrectly complains about. See: - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644 - Although the noinline attribute can hurt performance a bit, no better way - to pacify GCC is known; even an explicit #pragma does not pacify GCC. - When the GCC bug is fixed this workaround should be limited to the - broken GCC versions. */ -#if _GL_GNUC_PREREQ (10, 1) -# if defined GCC_LINT || defined lint -__attribute__ ((__noinline__)) -# elif __OPTIMIZE__ && !__NO_INLINE__ -# define GCC_BOGUS_WRETURN_LOCAL_ADDR -# endif -#endif -static char * -readlink_stk (int fd, char const *filename, - char *buffer, size_t buffer_size, - struct allocator const *alloc, - ssize_t (*preadlinkat) (int, char const *, char *, size_t), - char stack_buf[STACK_BUF_SIZE]) -{ - if (! alloc) - alloc = &stdlib_allocator; - - if (!buffer) - { - buffer = stack_buf; - buffer_size = STACK_BUF_SIZE; - } - - char *buf = buffer; - idx_t buf_size_max = MIN (IDX_MAX, MIN (SSIZE_MAX, SIZE_MAX)); - idx_t buf_size = MIN (buffer_size, buf_size_max); - - while (buf) - { - /* Attempt to read the link into the current buffer. */ - idx_t link_length = preadlinkat (fd, filename, buf, buf_size); - if (link_length < 0) - { - if (buf != buffer) - { - int readlinkat_errno = errno; - alloc->free (buf); - errno = readlinkat_errno; - } - return NULL; - } - - idx_t link_size = link_length; - - if (link_size < buf_size) - { - buf[link_size++] = '\0'; - - if (buf == stack_buf) - { - char *b = alloc->allocate (link_size); - buf_size = link_size; - if (! b) - break; - return memcpy (b, buf, link_size); - } - - if (link_size < buf_size && buf != buffer && alloc->reallocate) - { - /* Shrink BUF before returning it. */ - char *b = alloc->reallocate (buf, link_size); - if (b) - return b; - } - - return buf; - } - - if (buf != buffer) - alloc->free (buf); - - if (buf_size_max / 2 <= buf_size) - { - errno = ENAMETOOLONG; - return NULL; - } - - buf_size = 2 * buf_size + 1; - buf = alloc->allocate (buf_size); - } - - if (alloc->die) - alloc->die (buf_size); - errno = ENOMEM; - return NULL; -} - - -/* Assuming the current directory is FD, get the symbolic link value - of FILENAME as a null-terminated string and put it into a buffer. - If FD is AT_FDCWD, FILENAME is interpreted relative to the current - working directory, as in openat. - - If the link is small enough to fit into BUFFER put it there. - BUFFER's size is BUFFER_SIZE, and BUFFER can be null - if BUFFER_SIZE is zero. - - If the link is not small, put it into a dynamically allocated - buffer managed by ALLOC. It is the caller's responsibility to free - the returned value if it is nonnull and is not BUFFER. A null - ALLOC stands for the standard allocator. - - The PREADLINKAT function specifies how to read links. It operates - like POSIX readlinkat() - - but can assume that its first argument is the same as FD. - - If successful, return the buffer address; otherwise return NULL and - set errno. */ - -char * -careadlinkat (int fd, char const *filename, - char *buffer, size_t buffer_size, - struct allocator const *alloc, - ssize_t (*preadlinkat) (int, char const *, char *, size_t)) -{ - /* Allocate the initial buffer on the stack. This way, in the - common case of a symlink of small size, we get away with a - single small malloc instead of a big malloc followed by a - shrinking realloc. */ - #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR - #warning "GCC might issue a bogus -Wreturn-local-addr warning here." - #warning "See ." - #endif - char stack_buf[STACK_BUF_SIZE]; - return readlink_stk (fd, filename, buffer, buffer_size, alloc, - preadlinkat, stack_buf); -} diff --git a/xcompile/lib/careadlinkat.h b/xcompile/lib/careadlinkat.h deleted file mode 100644 index 201d0415fff..00000000000 --- a/xcompile/lib/careadlinkat.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Read symbolic links into a buffer without size limitation, relative to fd. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ - -#ifndef _GL_CAREADLINKAT_H -#define _GL_CAREADLINKAT_H - -#include -#include - -struct allocator; - -/* Assuming the current directory is FD, get the symbolic link value - of FILENAME as a null-terminated string and put it into a buffer. - If FD is AT_FDCWD, FILENAME is interpreted relative to the current - working directory, as in openat. - - If the link is small enough to fit into BUFFER put it there. - BUFFER's size is BUFFER_SIZE, and BUFFER can be null - if BUFFER_SIZE is zero. - - If the link is not small, put it into a dynamically allocated - buffer managed by ALLOC. It is the caller's responsibility to free - the returned value if it is nonnull and is not BUFFER. - - The PREADLINKAT function specifies how to read links. It operates - like POSIX readlinkat() - - but can assume that its first argument is the same as FD. - - If successful, return the buffer address; otherwise return NULL and - set errno. */ - -char *careadlinkat (int fd, char const *filename, - char *restrict buffer, size_t buffer_size, - struct allocator const *alloc, - ssize_t (*preadlinkat) (int, char const *, - char *, size_t)); - -/* Suitable value for careadlinkat's FD argument. */ -#if HAVE_READLINKAT -/* AT_FDCWD is declared in . */ -#else -/* Define AT_FDCWD independently, so that the careadlinkat module does - not depend on the fcntl-h module. We might as well use the same value - as fcntl-h. */ -# ifndef AT_FDCWD -# define AT_FDCWD (-3041965) -# endif -#endif - -#endif /* _GL_CAREADLINKAT_H */ diff --git a/xcompile/lib/cdefs.h b/xcompile/lib/cdefs.h deleted file mode 100644 index 09a3d19b23b..00000000000 --- a/xcompile/lib/cdefs.h +++ /dev/null @@ -1,707 +0,0 @@ -/* Copyright (C) 1992-2023 Free Software Foundation, Inc. - Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _SYS_CDEFS_H -#define _SYS_CDEFS_H 1 - -/* We are almost always included from features.h. */ -#ifndef _FEATURES_H -# include -#endif - -/* The GNU libc does not support any K&R compilers or the traditional mode - of ISO C compilers anymore. Check for some of the combinations not - supported anymore. */ -#if defined __GNUC__ && !defined __STDC__ -# error "You need a ISO C conforming compiler to use the glibc headers" -#endif - -/* Some user header file might have defined this before. */ -#undef __P -#undef __PMT - -/* Compilers that lack __has_attribute may object to - #if defined __has_attribute && __has_attribute (...) - even though they do not need to evaluate the right-hand side of the &&. - Similarly for __has_builtin, etc. */ -#if (defined __has_attribute \ - && (!defined __clang_minor__ \ - || (defined __apple_build_version__ \ - ? 6000000 <= __apple_build_version__ \ - : 3 < __clang_major__ + (5 <= __clang_minor__)))) -# define __glibc_has_attribute(attr) __has_attribute (attr) -#else -# define __glibc_has_attribute(attr) 0 -#endif -#ifdef __has_builtin -# define __glibc_has_builtin(name) __has_builtin (name) -#else -# define __glibc_has_builtin(name) 0 -#endif -#ifdef __has_extension -# define __glibc_has_extension(ext) __has_extension (ext) -#else -# define __glibc_has_extension(ext) 0 -#endif - -#if defined __GNUC__ || defined __clang__ - -/* All functions, except those with callbacks or those that - synchronize memory, are leaf functions. */ -# if __GNUC_PREREQ (4, 6) && !defined _LIBC -# define __LEAF , __leaf__ -# define __LEAF_ATTR __attribute__ ((__leaf__)) -# else -# define __LEAF -# define __LEAF_ATTR -# endif - -/* GCC can always grok prototypes. For C++ programs we add throw() - to help it optimize the function calls. But this only works with - gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions - as non-throwing using a function attribute since programs can use - the -fexceptions options for C code as well. */ -# if !defined __cplusplus \ - && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__)) -# define __THROW __attribute__ ((__nothrow__ __LEAF)) -# define __THROWNL __attribute__ ((__nothrow__)) -# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct -# define __NTHNL(fct) __attribute__ ((__nothrow__)) fct -# else -# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4) -# if __cplusplus >= 201103L -# define __THROW noexcept (true) -# else -# define __THROW throw () -# endif -# define __THROWNL __THROW -# define __NTH(fct) __LEAF_ATTR fct __THROW -# define __NTHNL(fct) fct __THROW -# else -# define __THROW -# define __THROWNL -# define __NTH(fct) fct -# define __NTHNL(fct) fct -# endif -# endif - -#else /* Not GCC or clang. */ - -# if (defined __cplusplus \ - || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) -# define __inline inline -# else -# define __inline /* No inline functions. */ -# endif - -# define __THROW -# define __THROWNL -# define __NTH(fct) fct - -#endif /* GCC || clang. */ - -/* These two macros are not used in glibc anymore. They are kept here - only because some other projects expect the macros to be defined. */ -#define __P(args) args -#define __PMT(args) args - -/* For these things, GCC behaves the ANSI way normally, - and the non-ANSI way under -traditional. */ - -#define __CONCAT(x,y) x ## y -#define __STRING(x) #x - -/* This is not a typedef so `const __ptr_t' does the right thing. */ -#define __ptr_t void * - - -/* C++ needs to know that types and declarations are C, not C++. */ -#ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -#else -# define __BEGIN_DECLS -# define __END_DECLS -#endif - - -/* Fortify support. */ -#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) -#define __bos0(ptr) __builtin_object_size (ptr, 0) - -/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ -#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \ - || __GNUC_PREREQ (12, 0)) -# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) -# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) -#else -# define __glibc_objsize0(__o) __bos0 (__o) -# define __glibc_objsize(__o) __bos (__o) -#endif - -/* Compile time conditions to choose between the regular, _chk and _chk_warn - variants. These conditions should get evaluated to constant and optimized - away. */ - -#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s)) -#define __glibc_unsigned_or_positive(__l) \ - ((__typeof (__l)) 0 < (__typeof (__l)) -1 \ - || (__builtin_constant_p (__l) && (__l) > 0)) - -/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ - condition can be folded to a constant and if it is true, or unknown (-1) */ -#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ - ((__osz) == (__SIZE_TYPE__) -1 \ - || (__glibc_unsigned_or_positive (__l) \ - && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ - (__s), (__osz))) \ - && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz)))) - -/* Conversely, we know at compile time that the length is unsafe if the - __L * __S <= __OBJSZ condition can be folded to a constant and if it is - false. */ -#define __glibc_unsafe_len(__l, __s, __osz) \ - (__glibc_unsigned_or_positive (__l) \ - && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ - __s, __osz)) \ - && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) - -/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be - declared. */ - -#define __glibc_fortify(f, __l, __s, __osz, ...) \ - (__glibc_safe_or_unknown_len (__l, __s, __osz) \ - ? __ ## f ## _alias (__VA_ARGS__) \ - : (__glibc_unsafe_len (__l, __s, __osz) \ - ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ - : __ ## f ## _chk (__VA_ARGS__, __osz))) \ - -/* Fortify function f, where object size argument passed to f is the number of - elements and not total size. */ - -#define __glibc_fortify_n(f, __l, __s, __osz, ...) \ - (__glibc_safe_or_unknown_len (__l, __s, __osz) \ - ? __ ## f ## _alias (__VA_ARGS__) \ - : (__glibc_unsafe_len (__l, __s, __osz) \ - ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ - : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \ - -#if __GNUC_PREREQ (4,3) -# define __warnattr(msg) __attribute__((__warning__ (msg))) -# define __errordecl(name, msg) \ - extern void name (void) __attribute__((__error__ (msg))) -#else -# define __warnattr(msg) -# define __errordecl(name, msg) extern void name (void) -#endif - -/* Support for flexible arrays. - Headers that should use flexible arrays only if they're "real" - (e.g. only if they won't affect sizeof()) should test - #if __glibc_c99_flexarr_available. */ -#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc -# define __flexarr [] -# define __glibc_c99_flexarr_available 1 -#elif __GNUC_PREREQ (2,97) || defined __clang__ -/* GCC 2.97 and clang support C99 flexible array members as an extension, - even when in C89 mode or compiling C++ (any version). */ -# define __flexarr [] -# define __glibc_c99_flexarr_available 1 -#elif defined __GNUC__ -/* Pre-2.97 GCC did not support C99 flexible arrays but did have - an equivalent extension with slightly different notation. */ -# define __flexarr [0] -# define __glibc_c99_flexarr_available 1 -#else -/* Some other non-C99 compiler. Approximate with [1]. */ -# define __flexarr [1] -# define __glibc_c99_flexarr_available 0 -#endif - - -/* __asm__ ("xyz") is used throughout the headers to rename functions - at the assembly language level. This is wrapped by the __REDIRECT - macro, in order to support compilers that can do this some other - way. When compilers don't support asm-names at all, we have to do - preprocessor tricks instead (which don't have exactly the right - semantics, but it's the best we can do). - - Example: - int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ - -#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4) - -# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) -# ifdef __cplusplus -# define __REDIRECT_NTH(name, proto, alias) \ - name proto __THROW __asm__ (__ASMNAME (#alias)) -# define __REDIRECT_NTHNL(name, proto, alias) \ - name proto __THROWNL __asm__ (__ASMNAME (#alias)) -# else -# define __REDIRECT_NTH(name, proto, alias) \ - name proto __asm__ (__ASMNAME (#alias)) __THROW -# define __REDIRECT_NTHNL(name, proto, alias) \ - name proto __asm__ (__ASMNAME (#alias)) __THROWNL -# endif -# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) -# define __ASMNAME2(prefix, cname) __STRING (prefix) cname - -/* -#elif __SOME_OTHER_COMPILER__ - -# define __REDIRECT(name, proto, alias) name proto; \ - _Pragma("let " #name " = " #alias) -*/ -#endif - -/* GCC and clang have various useful declarations that can be made with - the '__attribute__' syntax. All of the ways we use this do fine if - they are omitted for compilers that don't understand it. */ -#if !(defined __GNUC__ || defined __clang__) -# define __attribute__(xyz) /* Ignore */ -#endif - -/* At some point during the gcc 2.96 development the `malloc' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__) -# define __attribute_malloc__ __attribute__ ((__malloc__)) -#else -# define __attribute_malloc__ /* Ignore */ -#endif - -/* Tell the compiler which arguments to an allocation function - indicate the size of the allocation. */ -#if __GNUC_PREREQ (4, 3) -# define __attribute_alloc_size__(params) \ - __attribute__ ((__alloc_size__ params)) -#else -# define __attribute_alloc_size__(params) /* Ignore. */ -#endif - -/* Tell the compiler which argument to an allocation function - indicates the alignment of the allocation. */ -#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__) -# define __attribute_alloc_align__(param) \ - __attribute__ ((__alloc_align__ param)) -#else -# define __attribute_alloc_align__(param) /* Ignore. */ -#endif - -/* At some point during the gcc 2.96 development the `pure' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__) -# define __attribute_pure__ __attribute__ ((__pure__)) -#else -# define __attribute_pure__ /* Ignore */ -#endif - -/* This declaration tells the compiler that the value is constant. */ -#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__) -# define __attribute_const__ __attribute__ ((__const__)) -#else -# define __attribute_const__ /* Ignore */ -#endif - -#if __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__) -# define __attribute_maybe_unused__ __attribute__ ((__unused__)) -#else -# define __attribute_maybe_unused__ /* Ignore */ -#endif - -/* At some point during the gcc 3.1 development the `used' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. */ -#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__) -# define __attribute_used__ __attribute__ ((__used__)) -# define __attribute_noinline__ __attribute__ ((__noinline__)) -#else -# define __attribute_used__ __attribute__ ((__unused__)) -# define __attribute_noinline__ /* Ignore */ -#endif - -/* Since version 3.2, gcc allows marking deprecated functions. */ -#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__) -# define __attribute_deprecated__ __attribute__ ((__deprecated__)) -#else -# define __attribute_deprecated__ /* Ignore */ -#endif - -/* Since version 4.5, gcc also allows one to specify the message printed - when a deprecated function is used. clang claims to be gcc 4.2, but - may also support this feature. */ -#if __GNUC_PREREQ (4,5) \ - || __glibc_has_extension (__attribute_deprecated_with_message__) -# define __attribute_deprecated_msg__(msg) \ - __attribute__ ((__deprecated__ (msg))) -#else -# define __attribute_deprecated_msg__(msg) __attribute_deprecated__ -#endif - -/* At some point during the gcc 2.8 development the `format_arg' attribute - for functions was introduced. We don't want to use it unconditionally - (although this would be possible) since it generates warnings. - If several `format_arg' attributes are given for the same function, in - gcc-3.0 and older, all but the last one are ignored. In newer gccs, - all designated arguments are considered. */ -#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__) -# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) -#else -# define __attribute_format_arg__(x) /* Ignore */ -#endif - -/* At some point during the gcc 2.97 development the `strfmon' format - attribute for functions was introduced. We don't want to use it - unconditionally (although this would be possible) since it - generates warnings. */ -#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__) -# define __attribute_format_strfmon__(a,b) \ - __attribute__ ((__format__ (__strfmon__, a, b))) -#else -# define __attribute_format_strfmon__(a,b) /* Ignore */ -#endif - -/* The nonnull function attribute marks pointer parameters that - must not be NULL. This has the name __nonnull in glibc, - and __attribute_nonnull__ in files shared with Gnulib to avoid - collision with a different __nonnull in DragonFlyBSD 5.9. */ -#ifndef __attribute_nonnull__ -# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__) -# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params)) -# else -# define __attribute_nonnull__(params) -# endif -#endif -#ifndef __nonnull -# define __nonnull(params) __attribute_nonnull__ (params) -#endif - -/* The returns_nonnull function attribute marks the return type of the function - as always being non-null. */ -#ifndef __returns_nonnull -# if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__returns_nonnull__) -# define __returns_nonnull __attribute__ ((__returns_nonnull__)) -# else -# define __returns_nonnull -# endif -#endif - -/* If fortification mode, we warn about unused results of certain - function calls which can lead to problems. */ -#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__) -# define __attribute_warn_unused_result__ \ - __attribute__ ((__warn_unused_result__)) -# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0 -# define __wur __attribute_warn_unused_result__ -# endif -#else -# define __attribute_warn_unused_result__ /* empty */ -#endif -#ifndef __wur -# define __wur /* Ignore */ -#endif - -/* Forces a function to be always inlined. */ -#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__) -/* The Linux kernel defines __always_inline in stddef.h (283d7573), and - it conflicts with this definition. Therefore undefine it first to - allow either header to be included first. */ -# undef __always_inline -# define __always_inline __inline __attribute__ ((__always_inline__)) -#else -# undef __always_inline -# define __always_inline __inline -#endif - -/* Associate error messages with the source location of the call site rather - than with the source location inside the function. */ -#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__) -# define __attribute_artificial__ __attribute__ ((__artificial__)) -#else -# define __attribute_artificial__ /* Ignore */ -#endif - -/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. Using __GNUC_STDC_INLINE__ - or __GNUC_GNU_INLINE is not a good enough check for gcc because gcc versions - older than 4.3 may define these macros and still not guarantee GNU inlining - semantics. - - clang++ identifies itself as gcc-4.2, but has support for GNU inlining - semantics, that can be checked for by using the __GNUC_STDC_INLINE_ and - __GNUC_GNU_INLINE__ macro definitions. */ -#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \ - || (defined __clang__ && (defined __GNUC_STDC_INLINE__ \ - || defined __GNUC_GNU_INLINE__))) -# if defined __GNUC_STDC_INLINE__ || defined __cplusplus -# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) -# define __extern_always_inline \ - extern __always_inline __attribute__ ((__gnu_inline__)) -# else -# define __extern_inline extern __inline -# define __extern_always_inline extern __always_inline -# endif -#endif - -#ifdef __extern_always_inline -# define __fortify_function __extern_always_inline __attribute_artificial__ -#endif - -/* GCC 4.3 and above allow passing all anonymous arguments of an - __extern_always_inline function to some other vararg function. */ -#if __GNUC_PREREQ (4,3) -# define __va_arg_pack() __builtin_va_arg_pack () -# define __va_arg_pack_len() __builtin_va_arg_pack_len () -#endif - -/* It is possible to compile containing GCC extensions even if GCC is - run in pedantic mode if the uses are carefully marked using the - `__extension__' keyword. But this is not generally available before - version 2.8. */ -#if !(__GNUC_PREREQ (2,8) || defined __clang__) -# define __extension__ /* Ignore */ -#endif - -/* __restrict is known in EGCS 1.2 and above, and in clang. - It works also in C++ mode (outside of arrays), but only when spelled - as '__restrict', not 'restrict'. */ -#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3) -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -# define __restrict restrict -# else -# define __restrict /* Ignore */ -# endif -#endif - -/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is - array_name[restrict] - GCC 3.1 and clang support this. - This syntax is not usable in C++ mode. */ -#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus -# define __restrict_arr __restrict -#else -# ifdef __GNUC__ -# define __restrict_arr /* Not supported in old GCC. */ -# else -# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -# define __restrict_arr restrict -# else -/* Some other non-C99 compiler. */ -# define __restrict_arr /* Not supported. */ -# endif -# endif -#endif - -#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect) -# define __glibc_unlikely(cond) __builtin_expect ((cond), 0) -# define __glibc_likely(cond) __builtin_expect ((cond), 1) -#else -# define __glibc_unlikely(cond) (cond) -# define __glibc_likely(cond) (cond) -#endif - -#if (!defined _Noreturn \ - && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ - && !(__GNUC_PREREQ (4,7) \ - || (3 < __clang_major__ + (5 <= __clang_minor__)))) -# if __GNUC_PREREQ (2,8) -# define _Noreturn __attribute__ ((__noreturn__)) -# else -# define _Noreturn -# endif -#endif - -#if __GNUC_PREREQ (8, 0) -/* Describes a char array whose address can safely be passed as the first - argument to strncpy and strncat, as the char array is not necessarily - a NUL-terminated string. */ -# define __attribute_nonstring__ __attribute__ ((__nonstring__)) -#else -# define __attribute_nonstring__ -#endif - -/* Undefine (also defined in libc-symbols.h). */ -#undef __attribute_copy__ -#if __GNUC_PREREQ (9, 0) -/* Copies attributes from the declaration or type referenced by - the argument. */ -# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg))) -#else -# define __attribute_copy__(arg) -#endif - -#if (!defined _Static_assert && !defined __cplusplus \ - && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ - && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \ - || defined __STRICT_ANSI__)) -# define _Static_assert(expr, diagnostic) \ - extern int (*__Static_assert_function (void)) \ - [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })] -#endif - -/* Gnulib avoids including these, as they don't work on non-glibc or - older glibc platforms. */ -#ifndef __GNULIB_CDEFS -# include -# include -#endif - -#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1 -# ifdef __REDIRECT - -/* Alias name defined automatically. */ -# define __LDBL_REDIR(name, proto) ... unused__ldbl_redir -# define __LDBL_REDIR_DECL(name) \ - extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128")); - -/* Alias name defined automatically, with leading underscores. */ -# define __LDBL_REDIR2_DECL(name) \ - extern __typeof (__##name) __##name \ - __asm (__ASMNAME ("__" #name "ieee128")); - -/* Alias name defined manually. */ -# define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1 -# define __LDBL_REDIR1_DECL(name, alias) \ - extern __typeof (name) name __asm (__ASMNAME (#alias)); - -# define __LDBL_REDIR1_NTH(name, proto, alias) \ - __REDIRECT_NTH (name, proto, alias) -# define __REDIRECT_NTH_LDBL(name, proto, alias) \ - __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128) - -/* Unused. */ -# define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl -# define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth - -# else -_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform"); -# endif -#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH -# define __LDBL_COMPAT 1 -# ifdef __REDIRECT -# define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias) -# define __LDBL_REDIR(name, proto) \ - __LDBL_REDIR1 (name, proto, __nldbl_##name) -# define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias) -# define __LDBL_REDIR_NTH(name, proto) \ - __LDBL_REDIR1_NTH (name, proto, __nldbl_##name) -# define __LDBL_REDIR2_DECL(name) \ - extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name)); -# define __LDBL_REDIR1_DECL(name, alias) \ - extern __typeof (name) name __asm (__ASMNAME (#alias)); -# define __LDBL_REDIR_DECL(name) \ - extern __typeof (name) name __asm (__ASMNAME ("__nldbl_" #name)); -# define __REDIRECT_LDBL(name, proto, alias) \ - __LDBL_REDIR1 (name, proto, __nldbl_##alias) -# define __REDIRECT_NTH_LDBL(name, proto, alias) \ - __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias) -# endif -#endif -#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \ - || !defined __REDIRECT -# define __LDBL_REDIR1(name, proto, alias) name proto -# define __LDBL_REDIR(name, proto) name proto -# define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW -# define __LDBL_REDIR_NTH(name, proto) name proto __THROW -# define __LDBL_REDIR2_DECL(name) -# define __LDBL_REDIR_DECL(name) -# ifdef __REDIRECT -# define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias) -# define __REDIRECT_NTH_LDBL(name, proto, alias) \ - __REDIRECT_NTH (name, proto, alias) -# endif -#endif - -/* __glibc_macro_warning (MESSAGE) issues warning MESSAGE. This is - intended for use in preprocessor macros. - - Note: MESSAGE must be a _single_ string; concatenation of string - literals is not supported. */ -#if __GNUC_PREREQ (4,8) || __glibc_clang_prereq (3,5) -# define __glibc_macro_warning1(message) _Pragma (#message) -# define __glibc_macro_warning(message) \ - __glibc_macro_warning1 (GCC warning message) -#else -# define __glibc_macro_warning(msg) -#endif - -/* Generic selection (ISO C11) is a C-only feature, available in GCC - since version 4.9. Previous versions do not provide generic - selection, even though they might set __STDC_VERSION__ to 201112L, - when in -std=c11 mode. Thus, we must check for !defined __GNUC__ - when testing __STDC_VERSION__ for generic selection support. - On the other hand, Clang also defines __GNUC__, so a clang-specific - check is required to enable the use of generic selection. */ -#if !defined __cplusplus \ - && (__GNUC_PREREQ (4, 9) \ - || __glibc_has_extension (c_generic_selections) \ - || (!defined __GNUC__ && defined __STDC_VERSION__ \ - && __STDC_VERSION__ >= 201112L)) -# define __HAVE_GENERIC_SELECTION 1 -#else -# define __HAVE_GENERIC_SELECTION 0 -#endif - -#if __GNUC_PREREQ (10, 0) -/* Designates a 1-based positional argument ref-index of pointer type - that can be used to access size-index elements of the pointed-to - array according to access mode, or at least one element when - size-index is not provided: - access (access-mode, [, ]) */ -# define __attr_access(x) __attribute__ ((__access__ x)) -/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may - use the access attribute to get object sizes from function definition - arguments, so we can't use them on functions we fortify. Drop the object - size hints for such functions. */ -# if __USE_FORTIFY_LEVEL == 3 -# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o))) -# else -# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s)) -# endif -# if __GNUC_PREREQ (11, 0) -# define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno))) -# else -# define __attr_access_none(argno) -# endif -#else -# define __fortified_attr_access(a, o, s) -# define __attr_access(x) -# define __attr_access_none(argno) -#endif - -#if __GNUC_PREREQ (11, 0) -/* Designates dealloc as a function to call to deallocate objects - allocated by the declared function. */ -# define __attr_dealloc(dealloc, argno) \ - __attribute__ ((__malloc__ (dealloc, argno))) -# define __attr_dealloc_free __attr_dealloc (__builtin_free, 1) -#else -# define __attr_dealloc(dealloc, argno) -# define __attr_dealloc_free -#endif - -/* Specify that a function such as setjmp or vfork may return - twice. */ -#if __GNUC_PREREQ (4, 1) -# define __attribute_returns_twice__ __attribute__ ((__returns_twice__)) -#else -# define __attribute_returns_twice__ /* Ignore. */ -#endif - -#endif /* sys/cdefs.h */ diff --git a/xcompile/lib/cloexec.c b/xcompile/lib/cloexec.c deleted file mode 100644 index e4cecbd2e8a..00000000000 --- a/xcompile/lib/cloexec.c +++ /dev/null @@ -1,83 +0,0 @@ -/* cloexec.c - set or clear the close-on-exec descriptor flag - - Copyright (C) 1991, 2004-2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* The code is taken from glibc/manual/llio.texi */ - -#include - -#include "cloexec.h" - -#include -#include -#include - -/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, - or clear the flag if VALUE is false. - Return 0 on success, or -1 on error with 'errno' set. - - Note that on MingW, this function does NOT protect DESC from being - inherited into spawned children. Instead, either use dup_cloexec - followed by closing the original DESC, or use interfaces such as - open or pipe2 that accept flags like O_CLOEXEC to create DESC - non-inheritable in the first place. */ - -int -set_cloexec_flag (int desc, bool value) -{ -#ifdef F_SETFD - - int flags = fcntl (desc, F_GETFD, 0); - - if (0 <= flags) - { - int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); - - if (flags == newflags - || fcntl (desc, F_SETFD, newflags) != -1) - return 0; - } - - return -1; - -#else /* !F_SETFD */ - - /* Use dup2 to reject invalid file descriptors; the cloexec flag - will be unaffected. */ - if (desc < 0) - { - errno = EBADF; - return -1; - } - if (dup2 (desc, desc) < 0) - /* errno is EBADF here. */ - return -1; - - /* There is nothing we can do on this kind of platform. Punt. */ - return 0; -#endif /* !F_SETFD */ -} - - -/* Duplicates a file handle FD, while marking the copy to be closed - prior to exec or spawn. Returns -1 and sets errno if FD could not - be duplicated. */ - -int -dup_cloexec (int fd) -{ - return fcntl (fd, F_DUPFD_CLOEXEC, 0); -} diff --git a/xcompile/lib/cloexec.h b/xcompile/lib/cloexec.h deleted file mode 100644 index 057fd668c9b..00000000000 --- a/xcompile/lib/cloexec.h +++ /dev/null @@ -1,34 +0,0 @@ -/* cloexec.c - set or clear the close-on-exec descriptor flag - - Copyright (C) 2004, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, - or clear the flag if VALUE is false. - Return 0 on success, or -1 on error with 'errno' set. - - Note that on MingW, this function does NOT protect DESC from being - inherited into spawned children. Instead, either use dup_cloexec - followed by closing the original DESC, or use interfaces such as - open or pipe2 that accept flags like O_CLOEXEC to create DESC - non-inheritable in the first place. */ - -int set_cloexec_flag (int desc, bool value); - -/* Duplicates a file handle FD, while marking the copy to be closed - prior to exec or spawn. Returns -1 and sets errno if FD could not - be duplicated. */ - -int dup_cloexec (int fd); diff --git a/xcompile/lib/close-stream.c b/xcompile/lib/close-stream.c deleted file mode 100644 index ab686bac2ae..00000000000 --- a/xcompile/lib/close-stream.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Close a stream, with nicer error checking than fclose's. - - Copyright (C) 1998-2002, 2004, 2006-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -#include - -#include "close-stream.h" - -#include - -#include "fpending.h" - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -/* Close STREAM. Return 0 if successful, EOF (setting errno) - otherwise. A failure might set errno to 0 if the error number - cannot be determined. - - A failure with errno set to EPIPE may or may not indicate an error - situation worth signaling to the user. See the documentation of the - close_stdout_set_ignore_EPIPE function for details. - - If a program writes *anything* to STREAM, that program should close - STREAM and make sure that it succeeds before exiting. Otherwise, - suppose that you go to the extreme of checking the return status - of every function that does an explicit write to STREAM. The last - printf can succeed in writing to the internal stream buffer, and yet - the fclose(STREAM) could still fail (due e.g., to a disk full error) - when it tries to write out that buffered data. Thus, you would be - left with an incomplete output file and the offending program would - exit successfully. Even calling fflush is not always sufficient, - since some file systems (NFS and CODA) buffer written/flushed data - until an actual close call. - - Besides, it's wasteful to check the return value from every call - that writes to STREAM -- just let the internal stream state record - the failure. That's what the ferror test is checking below. */ - -int -close_stream (FILE *stream) -{ - const bool some_pending = (__fpending (stream) != 0); - const bool prev_fail = (ferror (stream) != 0); - const bool fclose_fail = (fclose (stream) != 0); - - /* Return an error indication if there was a previous failure or if - fclose failed, with one exception: ignore an fclose failure if - there was no previous error, no data remains to be flushed, and - fclose failed with EBADF. That can happen when a program like cp - is invoked like this 'cp a b >&-' (i.e., with standard output - closed) and doesn't generate any output (hence no previous error - and nothing to be flushed). */ - - if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) - { - if (! fclose_fail) - errno = 0; - return EOF; - } - - return 0; -} diff --git a/xcompile/lib/close-stream.h b/xcompile/lib/close-stream.h deleted file mode 100644 index 3b52cc66c3d..00000000000 --- a/xcompile/lib/close-stream.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Close a stream, with nicer error checking than fclose's. - - Copyright (C) 2006-2023 Free Software Foundation, Inc. - - This file is free software: you can 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 file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU 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 . */ - -#include - -int close_stream (FILE *stream); diff --git a/xcompile/lib/copy-file-range.c b/xcompile/lib/copy-file-range.c deleted file mode 100644 index 747a5a8ad1d..00000000000 --- a/xcompile/lib/copy-file-range.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Stub for copy_file_range - Copyright 2019-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#include - -#include - -#if defined __linux__ && HAVE_COPY_FILE_RANGE -# include -#endif - -ssize_t -copy_file_range (int infd, off_t *pinoff, - int outfd, off_t *poutoff, - size_t length, unsigned int flags) -{ -#undef copy_file_range - -#if defined __linux__ && HAVE_COPY_FILE_RANGE - /* The implementation of copy_file_range (which first appeared in - Linux kernel release 4.5) had many issues before release 5.3 - , so fail with ENOSYS for Linux - kernels 5.2 and earlier. - - This workaround, and the configure-time check for Linux, can be - removed when such kernels (released March 2016 through September - 2019) are no longer a consideration. As of January 2021, the - furthest-future planned kernel EOL is December 2024 for kernel - release 4.19. */ - - static signed char ok; - - if (! ok) - { - struct utsname name; - uname (&name); - char *p = name.release; - ok = ((p[1] != '.' || '5' < p[0] - || (p[0] == '5' && (p[3] != '.' || '2' < p[2]))) - ? 1 : -1); - } - - if (0 < ok) - return copy_file_range (infd, pinoff, outfd, poutoff, length, flags); -#endif - - /* There is little need to emulate copy_file_range with read+write, - since programs that use copy_file_range must fall back on - read+write anyway. */ - errno = ENOSYS; - return -1; -} diff --git a/xcompile/lib/count-leading-zeros.c b/xcompile/lib/count-leading-zeros.c deleted file mode 100644 index 949f156eab1..00000000000 --- a/xcompile/lib/count-leading-zeros.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Count the number of leading 0 bits in a word. - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define COUNT_LEADING_ZEROS_INLINE _GL_EXTERN_INLINE -#include "count-leading-zeros.h" diff --git a/xcompile/lib/count-leading-zeros.h b/xcompile/lib/count-leading-zeros.h deleted file mode 100644 index 99151d695bf..00000000000 --- a/xcompile/lib/count-leading-zeros.h +++ /dev/null @@ -1,136 +0,0 @@ -/* count-leading-zeros.h -- counts the number of leading 0 bits in a word. - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Eric Blake. */ - -#ifndef COUNT_LEADING_ZEROS_H -#define COUNT_LEADING_ZEROS_H 1 - -#include -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef COUNT_LEADING_ZEROS_INLINE -# define COUNT_LEADING_ZEROS_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN, - expand to code that computes the number of leading zeros of the local - variable 'x' of type TYPE (an unsigned integer type) and return it - from the current function. */ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \ - || (__clang_major__ >= 4) -# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - return x ? BUILTIN (x) : CHAR_BIT * sizeof x; -#elif _MSC_VER -# pragma intrinsic (_BitScanReverse) -# if defined _M_X64 -# pragma intrinsic (_BitScanReverse64) -# endif -# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - do \ - { \ - unsigned long result; \ - if (MSC_BUILTIN (&result, x)) \ - return CHAR_BIT * sizeof x - 1 - result; \ - return CHAR_BIT * sizeof x; \ - } \ - while (0) -#else -# define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - do \ - { \ - int count; \ - unsigned int leading_32; \ - if (! x) \ - return CHAR_BIT * sizeof x; \ - for (count = 0; \ - (leading_32 = ((x >> (sizeof (TYPE) * CHAR_BIT - 32)) \ - & 0xffffffffU), \ - count < CHAR_BIT * sizeof x - 32 && !leading_32); \ - count += 32) \ - x = x << 31 << 1; \ - return count + count_leading_zeros_32 (leading_32); \ - } \ - while (0) - -/* Compute and return the number of leading zeros in X, - where 0 < X < 2**32. */ -COUNT_LEADING_ZEROS_INLINE int -count_leading_zeros_32 (unsigned int x) -{ - /* - */ - static const char de_Bruijn_lookup[32] = { - 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1, - 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0 - }; - - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - return de_Bruijn_lookup[((x * 0x07c4acddU) & 0xffffffffU) >> 27]; -} -#endif - -/* Compute and return the number of leading zeros in X. */ -COUNT_LEADING_ZEROS_INLINE int -count_leading_zeros (unsigned int x) -{ - COUNT_LEADING_ZEROS (__builtin_clz, _BitScanReverse, unsigned int); -} - -/* Compute and return the number of leading zeros in X. */ -COUNT_LEADING_ZEROS_INLINE int -count_leading_zeros_l (unsigned long int x) -{ - COUNT_LEADING_ZEROS (__builtin_clzl, _BitScanReverse, unsigned long int); -} - -/* Compute and return the number of leading zeros in X. */ -COUNT_LEADING_ZEROS_INLINE int -count_leading_zeros_ll (unsigned long long int x) -{ -#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64 - /* 32-bit MSVC does not have _BitScanReverse64, only _BitScanReverse. */ - unsigned long result; - if (_BitScanReverse (&result, (unsigned long) (x >> 32))) - return CHAR_BIT * sizeof x - 1 - 32 - result; - if (_BitScanReverse (&result, (unsigned long) x)) - return CHAR_BIT * sizeof x - 1 - result; - return CHAR_BIT * sizeof x; -#else - COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64, - unsigned long long int); -#endif -} - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif /* COUNT_LEADING_ZEROS_H */ diff --git a/xcompile/lib/count-one-bits.c b/xcompile/lib/count-one-bits.c deleted file mode 100644 index 8a348f2e5a0..00000000000 --- a/xcompile/lib/count-one-bits.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Count the number of 1-bits in a word. - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE -#include "count-one-bits.h" - -#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) -int popcount_support = -1; -#endif diff --git a/xcompile/lib/count-one-bits.h b/xcompile/lib/count-one-bits.h deleted file mode 100644 index 01a60b77b85..00000000000 --- a/xcompile/lib/count-one-bits.h +++ /dev/null @@ -1,164 +0,0 @@ -/* count-one-bits.h -- counts the number of 1-bits in a word. - Copyright (C) 2007-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Ben Pfaff. */ - -#ifndef COUNT_ONE_BITS_H -#define COUNT_ONE_BITS_H 1 - -#include -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef COUNT_ONE_BITS_INLINE -# define COUNT_ONE_BITS_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN, - expand to code that computes the number of 1-bits of the local - variable 'x' of type TYPE (an unsigned integer type) and return it - from the current function. */ -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ - || (__clang_major__ >= 4) -# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ - return GCC_BUILTIN (x) -#else - -/* Compute and return the number of 1-bits set in the least - significant 32 bits of X. */ -COUNT_ONE_BITS_INLINE int -count_one_bits_32 (unsigned int x) -{ - x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U); - x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U); - x = (x >> 16) + (x & 0xffff); - x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f); - return (x >> 8) + (x & 0x00ff); -} - -/* Expand to code that computes the number of 1-bits of the local - variable 'x' of type TYPE (an unsigned integer type) and return it - from the current function. */ -# define COUNT_ONE_BITS_GENERIC(TYPE) \ - do \ - { \ - int count = 0; \ - int bits; \ - for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \ - { \ - count += count_one_bits_32 (x); \ - x = x >> 31 >> 1; \ - } \ - return count; \ - } \ - while (0) - -# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) - -/* While gcc falls back to its own generic code if the machine - on which it's running doesn't support popcount, with Microsoft's - compiler we need to detect and fallback ourselves. */ - -# if 0 -# include -# else - /* Don't pollute the namespace with too many MSVC intrinsics. */ -# pragma intrinsic (__cpuid) -# pragma intrinsic (__popcnt) -# if defined _M_X64 -# pragma intrinsic (__popcnt64) -# endif -# endif - -# if !defined _M_X64 -static inline __popcnt64 (unsigned long long x) -{ - return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x); -} -# endif - -/* Return nonzero if popcount is supported. */ - -/* 1 if supported, 0 if not supported, -1 if unknown. */ -extern int popcount_support; - -COUNT_ONE_BITS_INLINE int -popcount_supported (void) -{ - if (popcount_support < 0) - { - /* Do as described in - */ - int cpu_info[4]; - __cpuid (cpu_info, 1); - popcount_support = (cpu_info[2] >> 23) & 1; - } - return popcount_support; -} - -# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ - do \ - { \ - if (popcount_supported ()) \ - return MSC_BUILTIN (x); \ - else \ - COUNT_ONE_BITS_GENERIC (TYPE); \ - } \ - while (0) - -# else - -# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \ - COUNT_ONE_BITS_GENERIC (TYPE) - -# endif -#endif - -/* Compute and return the number of 1-bits set in X. */ -COUNT_ONE_BITS_INLINE int -count_one_bits (unsigned int x) -{ - COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int); -} - -/* Compute and return the number of 1-bits set in X. */ -COUNT_ONE_BITS_INLINE int -count_one_bits_l (unsigned long int x) -{ - COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int); -} - -/* Compute and return the number of 1-bits set in X. */ -COUNT_ONE_BITS_INLINE int -count_one_bits_ll (unsigned long long int x) -{ - COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int); -} - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif /* COUNT_ONE_BITS_H */ diff --git a/xcompile/lib/count-trailing-zeros.c b/xcompile/lib/count-trailing-zeros.c deleted file mode 100644 index f6fddab4232..00000000000 --- a/xcompile/lib/count-trailing-zeros.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Count the number of trailing 0 bits in a word. - - Copyright 2013-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE -#include "count-trailing-zeros.h" diff --git a/xcompile/lib/count-trailing-zeros.h b/xcompile/lib/count-trailing-zeros.h deleted file mode 100644 index ef8e164126a..00000000000 --- a/xcompile/lib/count-trailing-zeros.h +++ /dev/null @@ -1,126 +0,0 @@ -/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word. - Copyright 2013-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef COUNT_TRAILING_ZEROS_H -#define COUNT_TRAILING_ZEROS_H 1 - -#include -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef COUNT_TRAILING_ZEROS_INLINE -# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN, - expand to code that computes the number of trailing zeros of the local - variable 'x' of type TYPE (an unsigned integer type) and return it - from the current function. */ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \ - || (__clang_major__ >= 4) -# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - return x ? BUILTIN (x) : CHAR_BIT * sizeof x; -#elif _MSC_VER -# pragma intrinsic (_BitScanForward) -# if defined _M_X64 -# pragma intrinsic (_BitScanForward64) -# endif -# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - do \ - { \ - unsigned long result; \ - return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \ - } \ - while (0) -#else -# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ - do \ - { \ - int count = 0; \ - if (! x) \ - return CHAR_BIT * sizeof x; \ - for (count = 0; \ - (count < CHAR_BIT * sizeof x - 32 \ - && ! (x & 0xffffffffU)); \ - count += 32) \ - x = x >> 31 >> 1; \ - return count + count_trailing_zeros_32 (x); \ - } \ - while (0) - -/* Compute and return the number of trailing zeros in the least - significant 32 bits of X. One of these bits must be nonzero. */ -COUNT_TRAILING_ZEROS_INLINE int -count_trailing_zeros_32 (unsigned int x) -{ - /* - */ - static const char de_Bruijn_lookup[32] = { - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 - }; - return de_Bruijn_lookup[(((x & -x) * 0x077cb531U) & 0xffffffffU) >> 27]; -} -#endif - -/* Compute and return the number of trailing zeros in X. */ -COUNT_TRAILING_ZEROS_INLINE int -count_trailing_zeros (unsigned int x) -{ - COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int); -} - -/* Compute and return the number of trailing zeros in X. */ -COUNT_TRAILING_ZEROS_INLINE int -count_trailing_zeros_l (unsigned long int x) -{ - COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int); -} - -/* Compute and return the number of trailing zeros in X. */ -COUNT_TRAILING_ZEROS_INLINE int -count_trailing_zeros_ll (unsigned long long int x) -{ -#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64 - /* 32-bit MSVC does not have _BitScanForward64, only _BitScanForward. */ - unsigned long result; - if (_BitScanForward (&result, (unsigned long) x)) - return result; - if (_BitScanForward (&result, (unsigned long) (x >> 32))) - return result + 32; - return CHAR_BIT * sizeof x; -#else - COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64, - unsigned long long int); -#endif -} - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif diff --git a/xcompile/lib/diffseq.h b/xcompile/lib/diffseq.h deleted file mode 100644 index dfaf4f295e8..00000000000 --- a/xcompile/lib/diffseq.h +++ /dev/null @@ -1,568 +0,0 @@ -/* Analyze differences between two vectors. - - Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2023 Free Software - Foundation, Inc. - - This program is free software: you can 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 . */ - - -/* The basic idea is to consider two vectors as similar if, when - transforming the first vector into the second vector through a - sequence of edits (inserts and deletes of one element each), - this sequence is short - or equivalently, if the ordered list - of elements that are untouched by these edits is long. For a - good introduction to the subject, read about the "Levenshtein - distance" in Wikipedia. - - The basic algorithm is described in: - "An O(ND) Difference Algorithm and its Variations", Eugene W. Myers, - Algorithmica Vol. 1, 1986, pp. 251-266, - . - See especially section 4.2, which describes the variation used below. - - The basic algorithm was independently discovered as described in: - "Algorithms for Approximate String Matching", Esko Ukkonen, - Information and Control Vol. 64, 1985, pp. 100-118, - . - - Unless the 'find_minimal' flag is set, this code uses the TOO_EXPENSIVE - heuristic, by Paul Eggert, to limit the cost to O(N**1.5 log N) - at the price of producing suboptimal output for large inputs with - many differences. */ - -/* Before including this file, you need to define: - ELEMENT The element type of the vectors being compared. - EQUAL A two-argument macro that tests two elements for - equality. - OFFSET A signed integer type sufficient to hold the - difference between two indices. Usually - something like ptrdiff_t. - EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. - NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. - NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. - NOTE_ORDERED (Optional) A boolean expression saying that - NOTE_DELETE and NOTE_INSERT calls must be - issued in offset order. - EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an - early abort of the computation. - USE_HEURISTIC (Optional) Define if you want to support the - heuristic for large vectors. - - It is also possible to use this file with abstract arrays. In this case, - xvec and yvec are not represented in memory. They only exist conceptually. - In this case, the list of defines above is amended as follows: - ELEMENT Undefined. - EQUAL Undefined. - XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) - A three-argument macro: References xvec[xoff] and - yvec[yoff] and tests these elements for equality. - - Before including this file, you also need to include: - #include - #include "minmax.h" - */ - -/* Maximum value of type OFFSET. */ -#define OFFSET_MAX \ - ((((OFFSET)1 << (sizeof (OFFSET) * CHAR_BIT - 2)) - 1) * 2 + 1) - -/* Default to no early abort. */ -#ifndef EARLY_ABORT -# define EARLY_ABORT(ctxt) false -#endif - -#ifndef NOTE_ORDERED -# define NOTE_ORDERED false -#endif - -/* Use this to suppress gcc's "...may be used before initialized" warnings. - Beware: The Code argument must not contain commas. */ -#ifndef IF_LINT -# if defined GCC_LINT || defined lint -# define IF_LINT(Code) Code -# else -# define IF_LINT(Code) /* empty */ -# endif -#endif - -/* - * Context of comparison operation. - */ -struct context -{ - #ifdef ELEMENT - /* Vectors being compared. */ - ELEMENT const *xvec; - ELEMENT const *yvec; - #endif - - /* Extra fields. */ - EXTRA_CONTEXT_FIELDS - - /* Vector, indexed by diagonal, containing 1 + the X coordinate of the point - furthest along the given diagonal in the forward search of the edit - matrix. */ - OFFSET *fdiag; - - /* Vector, indexed by diagonal, containing the X coordinate of the point - furthest along the given diagonal in the backward search of the edit - matrix. */ - OFFSET *bdiag; - - #ifdef USE_HEURISTIC - /* This corresponds to the diff --speed-large-files flag. With this - heuristic, for vectors with a constant small density of changes, - the algorithm is linear in the vector size. */ - bool heuristic; - #endif - - /* Edit scripts longer than this are too expensive to compute. */ - OFFSET too_expensive; - - /* Snakes bigger than this are considered "big". */ - #define SNAKE_LIMIT 20 -}; - -struct partition -{ - /* Midpoints of this partition. */ - OFFSET xmid; - OFFSET ymid; - - /* True if low half will be analyzed minimally. */ - bool lo_minimal; - - /* Likewise for high half. */ - bool hi_minimal; -}; - - -/* Find the midpoint of the shortest edit script for a specified portion - of the two vectors. - - Scan from the beginnings of the vectors, and simultaneously from the ends, - doing a breadth-first search through the space of edit-sequence. - When the two searches meet, we have found the midpoint of the shortest - edit sequence. - - If FIND_MINIMAL is true, find the minimal edit script regardless of - expense. Otherwise, if the search is too expensive, use heuristics to - stop the search and report a suboptimal answer. - - Set PART->(xmid,ymid) to the midpoint (XMID,YMID). The diagonal number - XMID - YMID equals the number of inserted elements minus the number - of deleted elements (counting only elements before the midpoint). - - Set PART->lo_minimal to true iff the minimal edit script for the - left half of the partition is known; similarly for PART->hi_minimal. - - This function assumes that the first elements of the specified portions - of the two vectors do not match, and likewise that the last elements do not - match. The caller must trim matching elements from the beginning and end - of the portions it is going to specify. - - If we return the "wrong" partitions, the worst this can do is cause - suboptimal diff output. It cannot cause incorrect diff output. */ - -static void -diag (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, bool find_minimal, - struct partition *part, struct context *ctxt) -{ - OFFSET *const fd = ctxt->fdiag; /* Give the compiler a chance. */ - OFFSET *const bd = ctxt->bdiag; /* Additional help for the compiler. */ -#ifdef ELEMENT - ELEMENT const *const xv = ctxt->xvec; /* Still more help for the compiler. */ - ELEMENT const *const yv = ctxt->yvec; /* And more and more . . . */ - #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) -#else - #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) -#endif - const OFFSET dmin = xoff - ylim; /* Minimum valid diagonal. */ - const OFFSET dmax = xlim - yoff; /* Maximum valid diagonal. */ - const OFFSET fmid = xoff - yoff; /* Center diagonal of top-down search. */ - const OFFSET bmid = xlim - ylim; /* Center diagonal of bottom-up search. */ - OFFSET fmin = fmid; - OFFSET fmax = fmid; /* Limits of top-down search. */ - OFFSET bmin = bmid; - OFFSET bmax = bmid; /* Limits of bottom-up search. */ - OFFSET c; /* Cost. */ - bool odd = (fmid - bmid) & 1; /* True if southeast corner is on an odd - diagonal with respect to the northwest. */ - - fd[fmid] = xoff; - bd[bmid] = xlim; - - for (c = 1;; ++c) - { - OFFSET d; /* Active diagonal. */ - bool big_snake = false; - - /* Extend the top-down search by an edit step in each diagonal. */ - if (fmin > dmin) - fd[--fmin - 1] = -1; - else - ++fmin; - if (fmax < dmax) - fd[++fmax + 1] = -1; - else - --fmax; - for (d = fmax; d >= fmin; d -= 2) - { - OFFSET x; - OFFSET y; - OFFSET tlo = fd[d - 1]; - OFFSET thi = fd[d + 1]; - OFFSET x0 = tlo < thi ? thi : tlo + 1; - - for (x = x0, y = x0 - d; - x < xlim && y < ylim && XREF_YREF_EQUAL (x, y); - x++, y++) - continue; - if (x - x0 > SNAKE_LIMIT) - big_snake = true; - fd[d] = x; - if (odd && bmin <= d && d <= bmax && bd[d] <= x) - { - part->xmid = x; - part->ymid = y; - part->lo_minimal = part->hi_minimal = true; - return; - } - } - - /* Similarly extend the bottom-up search. */ - if (bmin > dmin) - bd[--bmin - 1] = OFFSET_MAX; - else - ++bmin; - if (bmax < dmax) - bd[++bmax + 1] = OFFSET_MAX; - else - --bmax; - for (d = bmax; d >= bmin; d -= 2) - { - OFFSET x; - OFFSET y; - OFFSET tlo = bd[d - 1]; - OFFSET thi = bd[d + 1]; - OFFSET x0 = tlo < thi ? tlo : thi - 1; - - for (x = x0, y = x0 - d; - xoff < x && yoff < y && XREF_YREF_EQUAL (x - 1, y - 1); - x--, y--) - continue; - if (x0 - x > SNAKE_LIMIT) - big_snake = true; - bd[d] = x; - if (!odd && fmin <= d && d <= fmax && x <= fd[d]) - { - part->xmid = x; - part->ymid = y; - part->lo_minimal = part->hi_minimal = true; - return; - } - } - - if (find_minimal) - continue; - -#ifdef USE_HEURISTIC - bool heuristic = ctxt->heuristic; -#else - bool heuristic = false; -#endif - - /* Heuristic: check occasionally for a diagonal that has made lots - of progress compared with the edit distance. If we have any - such, find the one that has made the most progress and return it - as if it had succeeded. - - With this heuristic, for vectors with a constant small density - of changes, the algorithm is linear in the vector size. */ - - if (200 < c && big_snake && heuristic) - { - { - OFFSET best = 0; - - for (d = fmax; d >= fmin; d -= 2) - { - OFFSET dd = d - fmid; - OFFSET x = fd[d]; - OFFSET y = x - d; - OFFSET v = (x - xoff) * 2 - dd; - - if (v > 12 * (c + (dd < 0 ? -dd : dd))) - { - if (v > best - && xoff + SNAKE_LIMIT <= x && x < xlim - && yoff + SNAKE_LIMIT <= y && y < ylim) - { - /* We have a good enough best diagonal; now insist - that it end with a significant snake. */ - int k; - - for (k = 1; XREF_YREF_EQUAL (x - k, y - k); k++) - if (k == SNAKE_LIMIT) - { - best = v; - part->xmid = x; - part->ymid = y; - break; - } - } - } - } - if (best > 0) - { - part->lo_minimal = true; - part->hi_minimal = false; - return; - } - } - - { - OFFSET best = 0; - - for (d = bmax; d >= bmin; d -= 2) - { - OFFSET dd = d - bmid; - OFFSET x = bd[d]; - OFFSET y = x - d; - OFFSET v = (xlim - x) * 2 + dd; - - if (v > 12 * (c + (dd < 0 ? -dd : dd))) - { - if (v > best - && xoff < x && x <= xlim - SNAKE_LIMIT - && yoff < y && y <= ylim - SNAKE_LIMIT) - { - /* We have a good enough best diagonal; now insist - that it end with a significant snake. */ - int k; - - for (k = 0; XREF_YREF_EQUAL (x + k, y + k); k++) - if (k == SNAKE_LIMIT - 1) - { - best = v; - part->xmid = x; - part->ymid = y; - break; - } - } - } - } - if (best > 0) - { - part->lo_minimal = false; - part->hi_minimal = true; - return; - } - } - } - - /* Heuristic: if we've gone well beyond the call of duty, give up - and report halfway between our best results so far. */ - if (c >= ctxt->too_expensive) - { - OFFSET fxybest; - OFFSET fxbest IF_LINT (= 0); - OFFSET bxybest; - OFFSET bxbest IF_LINT (= 0); - - /* Find forward diagonal that maximizes X + Y. */ - fxybest = -1; - for (d = fmax; d >= fmin; d -= 2) - { - OFFSET x = MIN (fd[d], xlim); - OFFSET y = x - d; - if (ylim < y) - { - x = ylim + d; - y = ylim; - } - if (fxybest < x + y) - { - fxybest = x + y; - fxbest = x; - } - } - - /* Find backward diagonal that minimizes X + Y. */ - bxybest = OFFSET_MAX; - for (d = bmax; d >= bmin; d -= 2) - { - OFFSET x = MAX (xoff, bd[d]); - OFFSET y = x - d; - if (y < yoff) - { - x = yoff + d; - y = yoff; - } - if (x + y < bxybest) - { - bxybest = x + y; - bxbest = x; - } - } - - /* Use the better of the two diagonals. */ - if ((xlim + ylim) - bxybest < fxybest - (xoff + yoff)) - { - part->xmid = fxbest; - part->ymid = fxybest - fxbest; - part->lo_minimal = true; - part->hi_minimal = false; - } - else - { - part->xmid = bxbest; - part->ymid = bxybest - bxbest; - part->lo_minimal = false; - part->hi_minimal = true; - } - return; - } - } - #undef XREF_YREF_EQUAL -} - - -/* Compare in detail contiguous subsequences of the two vectors - which are known, as a whole, to match each other. - - The subsequence of vector 0 is [XOFF, XLIM) and likewise for vector 1. - - Note that XLIM, YLIM are exclusive bounds. All indices into the vectors - are origin-0. - - If FIND_MINIMAL, find a minimal difference no matter how - expensive it is. - - The results are recorded by invoking NOTE_DELETE and NOTE_INSERT. - - Return false if terminated normally, or true if terminated through early - abort. */ - -static bool -compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, - bool find_minimal, struct context *ctxt) -{ -#ifdef ELEMENT - ELEMENT const *xv = ctxt->xvec; /* Help the compiler. */ - ELEMENT const *yv = ctxt->yvec; - #define XREF_YREF_EQUAL(x,y) EQUAL (xv[x], yv[y]) -#else - #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) -#endif - - while (true) - { - /* Slide down the bottom initial diagonal. */ - while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) - { - xoff++; - yoff++; - } - - /* Slide up the top initial diagonal. */ - while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) - { - xlim--; - ylim--; - } - - /* Handle simple cases. */ - if (xoff == xlim) - { - while (yoff < ylim) - { - NOTE_INSERT (ctxt, yoff); - if (EARLY_ABORT (ctxt)) - return true; - yoff++; - } - break; - } - if (yoff == ylim) - { - while (xoff < xlim) - { - NOTE_DELETE (ctxt, xoff); - if (EARLY_ABORT (ctxt)) - return true; - xoff++; - } - break; - } - - struct partition part; - - /* Find a point of correspondence in the middle of the vectors. */ - diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt); - - /* Use the partitions to split this problem into subproblems. */ - OFFSET xoff1, xlim1, yoff1, ylim1, xoff2, xlim2, yoff2, ylim2; - bool find_minimal1, find_minimal2; - if (!NOTE_ORDERED - && ((xlim + ylim) - (part.xmid + part.ymid) - < (part.xmid + part.ymid) - (xoff + yoff))) - { - /* The second problem is smaller and the caller doesn't - care about order, so do the second problem first to - lessen recursion. */ - xoff1 = part.xmid; xlim1 = xlim; - yoff1 = part.ymid; ylim1 = ylim; - find_minimal1 = part.hi_minimal; - - xoff2 = xoff; xlim2 = part.xmid; - yoff2 = yoff; ylim2 = part.ymid; - find_minimal2 = part.lo_minimal; - } - else - { - xoff1 = xoff; xlim1 = part.xmid; - yoff1 = yoff; ylim1 = part.ymid; - find_minimal1 = part.lo_minimal; - - xoff2 = part.xmid; xlim2 = xlim; - yoff2 = part.ymid; ylim2 = ylim; - find_minimal2 = part.hi_minimal; - } - - /* Recurse to do one subproblem. */ - bool early = compareseq (xoff1, xlim1, yoff1, ylim1, find_minimal1, ctxt); - if (early) - return early; - - /* Iterate to do the other subproblem. */ - xoff = xoff2; xlim = xlim2; - yoff = yoff2; ylim = ylim2; - find_minimal = find_minimal2; - } - - return false; - #undef XREF_YREF_EQUAL -} - -#undef ELEMENT -#undef EQUAL -#undef OFFSET -#undef EXTRA_CONTEXT_FIELDS -#undef NOTE_DELETE -#undef NOTE_INSERT -#undef EARLY_ABORT -#undef USE_HEURISTIC -#undef XVECREF_YVECREF_EQUAL -#undef OFFSET_MAX diff --git a/xcompile/lib/dirent.in.h b/xcompile/lib/dirent.in.h deleted file mode 100644 index 2aaabd054a8..00000000000 --- a/xcompile/lib/dirent.in.h +++ /dev/null @@ -1,321 +0,0 @@ -/* A GNU-like . - Copyright (C) 2006-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _@GUARD_PREFIX@_DIRENT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_DIRENT_H@ -# @INCLUDE_NEXT@ @NEXT_DIRENT_H@ -#endif - -#ifndef _@GUARD_PREFIX@_DIRENT_H -#define _@GUARD_PREFIX@_DIRENT_H - -/* Get ino_t. Needed on some systems, including glibc 2.8. */ -#include - -#if !@HAVE_DIRENT_H@ -/* Define types DIR and 'struct dirent'. */ -# if !GNULIB_defined_struct_dirent -struct dirent -{ - char d_type; - char d_name[1]; -}; -/* Possible values for 'd_type'. */ -# define DT_UNKNOWN 0 -# define DT_FIFO 1 /* FIFO */ -# define DT_CHR 2 /* character device */ -# define DT_DIR 4 /* directory */ -# define DT_BLK 6 /* block device */ -# define DT_REG 8 /* regular file */ -# define DT_LNK 10 /* symbolic link */ -# define DT_SOCK 12 /* socket */ -# define DT_WHT 14 /* whiteout */ -typedef struct gl_directory DIR; -# define GNULIB_defined_struct_dirent 1 -# endif -#endif - -/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers - that can be freed by passing them as the Ith argument to the - function F. */ -#ifndef _GL_ATTRIBUTE_DEALLOC -# if __GNUC__ >= 11 -# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) -# else -# define _GL_ATTRIBUTE_DEALLOC(f, i) -# endif -#endif - -/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly - allocated memory. */ -/* Applies to: functions. */ -#ifndef _GL_ATTRIBUTE_MALLOC -# if __GNUC__ >= 3 || defined __clang__ -# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) -# else -# define _GL_ATTRIBUTE_MALLOC -# endif -#endif - -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The attribute __pure__ was added in gcc 2.96. */ -#ifndef _GL_ATTRIBUTE_PURE -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ -# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define _GL_ATTRIBUTE_PURE /* empty */ -# endif -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Declare overridden functions. */ - -#if @GNULIB_CLOSEDIR@ -# if @REPLACE_CLOSEDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef closedir -# define closedir rpl_closedir -# define GNULIB_defined_closedir 1 -# endif -_GL_FUNCDECL_RPL (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (closedir, int, (DIR *dirp)); -# else -# if !@HAVE_CLOSEDIR@ -_GL_FUNCDECL_SYS (closedir, int, (DIR *dirp) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (closedir, int, (DIR *dirp)); -# endif -_GL_CXXALIASWARN (closedir); -#elif defined GNULIB_POSIXCHECK -# undef closedir -# if HAVE_RAW_DECL_CLOSEDIR -_GL_WARN_ON_USE (closedir, "closedir is not portable - " - "use gnulib module closedir for portability"); -# endif -#endif - -#if @GNULIB_OPENDIR@ -# if @REPLACE_OPENDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef opendir -# define opendir rpl_opendir -# define GNULIB_defined_opendir 1 -# endif -_GL_FUNCDECL_RPL (opendir, DIR *, - (const char *dir_name) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -_GL_CXXALIAS_RPL (opendir, DIR *, (const char *dir_name)); -# else -# if !@HAVE_OPENDIR@ || __GNUC__ >= 11 -_GL_FUNCDECL_SYS (opendir, DIR *, - (const char *dir_name) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -# endif -_GL_CXXALIAS_SYS (opendir, DIR *, (const char *dir_name)); -# endif -_GL_CXXALIASWARN (opendir); -#else -# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined opendir -/* For -Wmismatched-dealloc: Associate opendir with closedir or - rpl_closedir. */ -_GL_FUNCDECL_SYS (opendir, DIR *, - (const char *dir_name) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -# endif -# if defined GNULIB_POSIXCHECK -# undef opendir -# if HAVE_RAW_DECL_OPENDIR -_GL_WARN_ON_USE (opendir, "opendir is not portable - " - "use gnulib module opendir for portability"); -# endif -# endif -#endif - -#if @GNULIB_READDIR@ -# if !@HAVE_READDIR@ -_GL_FUNCDECL_SYS (readdir, struct dirent *, (DIR *dirp) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (readdir, struct dirent *, (DIR *dirp)); -_GL_CXXALIASWARN (readdir); -#elif defined GNULIB_POSIXCHECK -# undef readdir -# if HAVE_RAW_DECL_READDIR -_GL_WARN_ON_USE (readdir, "readdir is not portable - " - "use gnulib module readdir for portability"); -# endif -#endif - -#if @GNULIB_REWINDDIR@ -# if !@HAVE_REWINDDIR@ -_GL_FUNCDECL_SYS (rewinddir, void, (DIR *dirp) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (rewinddir, void, (DIR *dirp)); -_GL_CXXALIASWARN (rewinddir); -#elif defined GNULIB_POSIXCHECK -# undef rewinddir -# if HAVE_RAW_DECL_REWINDDIR -_GL_WARN_ON_USE (rewinddir, "rewinddir is not portable - " - "use gnulib module rewinddir for portability"); -# endif -#endif - -#if @GNULIB_DIRFD@ -/* Return the file descriptor associated with the given directory stream, - or -1 if none exists. */ -# if @REPLACE_DIRFD@ -/* On kLIBC, dirfd() is a macro that does not work. Undefine it. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) || defined dirfd -# undef dirfd -# define dirfd rpl_dirfd -# endif -_GL_FUNCDECL_RPL (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (dirfd, int, (DIR *)); - -# ifdef __KLIBC__ -/* Gnulib internal hooks needed to maintain the dirfd metadata. */ -_GL_EXTERN_C int _gl_register_dirp_fd (int fd, DIR *dirp) - _GL_ARG_NONNULL ((2)); -_GL_EXTERN_C void _gl_unregister_dirp_fd (int fd); -# endif -# else -# if defined __cplusplus && defined GNULIB_NAMESPACE && defined dirfd - /* dirfd is defined as a macro and not as a function. - Turn it into a function and get rid of the macro. */ -static inline int (dirfd) (DIR *dp) { return dirfd (dp); } -# undef dirfd -# endif -# if !(@HAVE_DECL_DIRFD@ || defined dirfd) -_GL_FUNCDECL_SYS (dirfd, int, (DIR *) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (dirfd, int, (DIR *)); -# endif -_GL_CXXALIASWARN (dirfd); -#elif defined GNULIB_POSIXCHECK -# undef dirfd -# if HAVE_RAW_DECL_DIRFD -_GL_WARN_ON_USE (dirfd, "dirfd is unportable - " - "use gnulib module dirfd for portability"); -# endif -#endif - -#if @GNULIB_FDOPENDIR@ -/* Open a directory stream visiting the given directory file - descriptor. Return NULL and set errno if fd is not visiting a - directory. On success, this function consumes fd (it will be - implicitly closed either by this function or by a subsequent - closedir). */ -# if @REPLACE_FDOPENDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fdopendir -# define fdopendir rpl_fdopendir -# endif -_GL_FUNCDECL_RPL (fdopendir, DIR *, - (int fd) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -_GL_CXXALIAS_RPL (fdopendir, DIR *, (int fd)); -# else -# if !@HAVE_FDOPENDIR@ || !@HAVE_DECL_FDOPENDIR@ || __GNUC__ >= 11 -_GL_FUNCDECL_SYS (fdopendir, DIR *, - (int fd) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -# endif -_GL_CXXALIAS_SYS (fdopendir, DIR *, (int fd)); -# endif -_GL_CXXALIASWARN (fdopendir); -#else -# if @GNULIB_CLOSEDIR@ && __GNUC__ >= 11 && !defined fdopendir -/* For -Wmismatched-dealloc: Associate fdopendir with closedir or - rpl_closedir. */ -_GL_FUNCDECL_SYS (fdopendir, DIR *, - (int fd) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (closedir, 1)); -# endif -# if defined GNULIB_POSIXCHECK -# undef fdopendir -# if HAVE_RAW_DECL_FDOPENDIR -_GL_WARN_ON_USE (fdopendir, "fdopendir is unportable - " - "use gnulib module fdopendir for portability"); -# endif -# endif -#endif - -#if @GNULIB_SCANDIR@ -/* Scan the directory DIR, calling FILTER on each directory entry. - Entries for which FILTER returns nonzero are individually malloc'd, - sorted using qsort with CMP, and collected in a malloc'd array in - *NAMELIST. Returns the number of entries selected, or -1 on error. */ -# if !@HAVE_SCANDIR@ -_GL_FUNCDECL_SYS (scandir, int, - (const char *dir, struct dirent ***namelist, - int (*filter) (const struct dirent *), - int (*cmp) (const struct dirent **, const struct dirent **)) - _GL_ARG_NONNULL ((1, 2, 4))); -# endif -/* Need to cast, because on glibc systems, the fourth parameter is - int (*cmp) (const void *, const void *). */ -_GL_CXXALIAS_SYS_CAST (scandir, int, - (const char *dir, struct dirent ***namelist, - int (*filter) (const struct dirent *), - int (*cmp) (const struct dirent **, const struct dirent **))); -_GL_CXXALIASWARN (scandir); -#elif defined GNULIB_POSIXCHECK -# undef scandir -# if HAVE_RAW_DECL_SCANDIR -_GL_WARN_ON_USE (scandir, "scandir is unportable - " - "use gnulib module scandir for portability"); -# endif -#endif - -#if @GNULIB_ALPHASORT@ -/* Compare two 'struct dirent' entries alphabetically. */ -# if !@HAVE_ALPHASORT@ -_GL_FUNCDECL_SYS (alphasort, int, - (const struct dirent **, const struct dirent **) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif -/* Need to cast, because on glibc systems, the parameters are - (const void *, const void *). */ -_GL_CXXALIAS_SYS_CAST (alphasort, int, - (const struct dirent **, const struct dirent **)); -_GL_CXXALIASWARN (alphasort); -#elif defined GNULIB_POSIXCHECK -# undef alphasort -# if HAVE_RAW_DECL_ALPHASORT -_GL_WARN_ON_USE (alphasort, "alphasort is unportable - " - "use gnulib module alphasort for portability"); -# endif -#endif - - -#endif /* _@GUARD_PREFIX@_DIRENT_H */ -#endif /* _@GUARD_PREFIX@_DIRENT_H */ diff --git a/xcompile/lib/dirfd.c b/xcompile/lib/dirfd.c deleted file mode 100644 index b2b1d25cdbd..00000000000 --- a/xcompile/lib/dirfd.c +++ /dev/null @@ -1,98 +0,0 @@ -/* dirfd.c -- return the file descriptor associated with an open DIR* - - Copyright (C) 2001, 2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Jim Meyering. */ - -#include - -#include -#include - -#ifdef __KLIBC__ -# include -# include - -static struct dirp_fd_list -{ - DIR *dirp; - int fd; - struct dirp_fd_list *next; -} *dirp_fd_start = NULL; - -/* Register fd associated with dirp to dirp_fd_list. */ -int -_gl_register_dirp_fd (int fd, DIR *dirp) -{ - struct dirp_fd_list *new_dirp_fd = malloc (sizeof *new_dirp_fd); - if (!new_dirp_fd) - return -1; - - new_dirp_fd->dirp = dirp; - new_dirp_fd->fd = fd; - new_dirp_fd->next = dirp_fd_start; - - dirp_fd_start = new_dirp_fd; - - return 0; -} - -/* Unregister fd from dirp_fd_list with closing it */ -void -_gl_unregister_dirp_fd (int fd) -{ - struct dirp_fd_list *dirp_fd; - struct dirp_fd_list *dirp_fd_prev; - - for (dirp_fd_prev = NULL, dirp_fd = dirp_fd_start; dirp_fd; - dirp_fd_prev = dirp_fd, dirp_fd = dirp_fd->next) - { - if (dirp_fd->fd == fd) - { - if (dirp_fd_prev) - dirp_fd_prev->next = dirp_fd->next; - else /* dirp_fd == dirp_fd_start */ - dirp_fd_start = dirp_fd_start->next; - - close (fd); - free (dirp_fd); - break; - } - } -} -#endif - -int -dirfd (DIR *dir_p) -{ - int fd = DIR_TO_FD (dir_p); - if (fd == -1) -#ifndef __KLIBC__ - errno = ENOTSUP; -#else - { - struct dirp_fd_list *dirp_fd; - - for (dirp_fd = dirp_fd_start; dirp_fd; dirp_fd = dirp_fd->next) - if (dirp_fd->dirp == dir_p) - return dirp_fd->fd; - - errno = EINVAL; - } -#endif - - return fd; -} diff --git a/xcompile/lib/dtoastr.c b/xcompile/lib/dtoastr.c deleted file mode 100644 index 66b50995c79..00000000000 --- a/xcompile/lib/dtoastr.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Convert 'double' to accurate string. - - Copyright (C) 2010-2023 Free Software Foundation, Inc. - - This file is free software: you can 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 file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU 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 . */ - -#define LENGTH 2 -#include "ftoastr.c" diff --git a/xcompile/lib/dtotimespec.c b/xcompile/lib/dtotimespec.c deleted file mode 100644 index 28a44b69171..00000000000 --- a/xcompile/lib/dtotimespec.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Convert double to timespec. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Paul Eggert */ - -/* Convert the double value SEC to a struct timespec. Round toward - positive infinity. On overflow, return an extremal value. */ - -#include - -#include "timespec.h" - -#include "intprops.h" - -struct timespec -dtotimespec (double sec) -{ - if (! (TYPE_MINIMUM (time_t) < sec)) - return make_timespec (TYPE_MINIMUM (time_t), 0); - else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) - return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1); - else - { - time_t s = sec; - double frac = TIMESPEC_HZ * (sec - s); - long ns = frac; - ns += ns < frac; - s += ns / TIMESPEC_HZ; - ns %= TIMESPEC_HZ; - - if (ns < 0) - { - s--; - ns += TIMESPEC_HZ; - } - - return make_timespec (s, ns); - } -} diff --git a/xcompile/lib/dup2.c b/xcompile/lib/dup2.c deleted file mode 100644 index 7d197ca3123..00000000000 --- a/xcompile/lib/dup2.c +++ /dev/null @@ -1,189 +0,0 @@ -/* Duplicate an open file descriptor to a specified file descriptor. - - Copyright (C) 1999, 2004-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Paul Eggert */ - -#include - -/* Specification. */ -#include - -#include -#include - -#undef dup2 - -#if defined _WIN32 && ! defined __CYGWIN__ - -/* Get declarations of the native Windows API functions. */ -# define WIN32_LEAN_AND_MEAN -# include - -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -# include "msvc-inval.h" -# endif - -/* Get _get_osfhandle. */ -# if GNULIB_MSVC_NOTHROW -# include "msvc-nothrow.h" -# else -# include -# endif - -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -static int -dup2_nothrow (int fd, int desired_fd) -{ - int result; - - TRY_MSVC_INVAL - { - result = _dup2 (fd, desired_fd); - } - CATCH_MSVC_INVAL - { - errno = EBADF; - result = -1; - } - DONE_MSVC_INVAL; - - return result; -} -# else -# define dup2_nothrow _dup2 -# endif - -static int -ms_windows_dup2 (int fd, int desired_fd) -{ - int result; - - /* If fd is closed, mingw hangs on dup2 (fd, fd). If fd is open, - dup2 (fd, fd) returns 0, but all further attempts to use fd in - future dup2 calls will hang. */ - if (fd == desired_fd) - { - if ((HANDLE) _get_osfhandle (fd) == INVALID_HANDLE_VALUE) - { - errno = EBADF; - return -1; - } - return fd; - } - - /* Wine 1.0.1 return 0 when desired_fd is negative but not -1: - https://bugs.winehq.org/show_bug.cgi?id=21289 */ - if (desired_fd < 0) - { - errno = EBADF; - return -1; - } - - result = dup2_nothrow (fd, desired_fd); - - if (result == 0) - result = desired_fd; - - return result; -} - -# define dup2 ms_windows_dup2 - -#elif defined __KLIBC__ - -# include - -static int -klibc_dup2dirfd (int fd, int desired_fd) -{ - int tempfd; - int dupfd; - - tempfd = open ("NUL", O_RDONLY); - if (tempfd == -1) - return -1; - - if (tempfd == desired_fd) - { - close (tempfd); - - char path[_MAX_PATH]; - if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) - return -1; - - return open(path, O_RDONLY); - } - - dupfd = klibc_dup2dirfd (fd, desired_fd); - - close (tempfd); - - return dupfd; -} - -static int -klibc_dup2 (int fd, int desired_fd) -{ - int dupfd; - struct stat sbuf; - - dupfd = dup2 (fd, desired_fd); - if (dupfd == -1 && errno == ENOTSUP \ - && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) - { - close (desired_fd); - - return klibc_dup2dirfd (fd, desired_fd); - } - - return dupfd; -} - -# define dup2 klibc_dup2 -#endif - -int -rpl_dup2 (int fd, int desired_fd) -{ - int result; - -#ifdef F_GETFL - /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. - On Cygwin 1.5.x, dup2 (1, 1) returns 0. - On Cygwin 1.7.17, dup2 (1, -1) dumps core. - On Cygwin 1.7.25, dup2 (1, 256) can dump core. - On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ -# if HAVE_SETDTABLESIZE - setdtablesize (desired_fd + 1); -# endif - if (desired_fd < 0) - fd = desired_fd; - if (fd == desired_fd) - return fcntl (fd, F_GETFL) == -1 ? -1 : fd; -#endif - - result = dup2 (fd, desired_fd); - - /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ - if (result == -1 && errno == EMFILE) - errno = EBADF; -#if REPLACE_FCHDIR - if (fd != desired_fd && result != -1) - result = _gl_register_dup (fd, result); -#endif - return result; -} diff --git a/xcompile/lib/dynarray.h b/xcompile/lib/dynarray.h deleted file mode 100644 index 9155910934f..00000000000 --- a/xcompile/lib/dynarray.h +++ /dev/null @@ -1,284 +0,0 @@ -/* Type-safe arrays which grow dynamically. - Copyright 2021-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert and Bruno Haible, 2021. */ - -#ifndef _GL_DYNARRAY_H -#define _GL_DYNARRAY_H - -/* Before including this file, you need to define: - - DYNARRAY_STRUCT - The struct tag of dynamic array to be defined. - - DYNARRAY_ELEMENT - The type name of the element type. Elements are copied - as if by memcpy, and can change address as the dynamic - array grows. - - DYNARRAY_PREFIX - The prefix of the functions which are defined. - - The following parameters are optional: - - DYNARRAY_ELEMENT_FREE - DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the - contents of elements. E is of type DYNARRAY_ELEMENT *. - - DYNARRAY_ELEMENT_INIT - DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new - element. E is of type DYNARRAY_ELEMENT *. - If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is - defined, new elements are automatically zero-initialized. - Otherwise, new elements have undefined contents. - - DYNARRAY_INITIAL_SIZE - The size of the statically allocated array (default: - at least 2, more elements if they fit into 128 bytes). - Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, - there is no statically allocated array at, and all non-empty - arrays are heap-allocated. - - DYNARRAY_FINAL_TYPE - The name of the type which holds the final array. If not - defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE - must be a struct type, with members of type DYNARRAY_ELEMENT and - size_t at the start (in this order). - - These macros are undefined after this header file has been - included. - - The following types are provided (their members are private to the - dynarray implementation): - - struct DYNARRAY_STRUCT - - The following functions are provided: - */ - -/* Initialize a dynamic array object. This must be called before any - use of the object. */ -#if 0 -static void - DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *list); -#endif - -/* Deallocate the dynamic array and its elements. */ -#if 0 -static void - DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *list); -#endif - -/* Return true if the dynamic array is in an error state. */ -#if 0 -static bool - DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *list); -#endif - -/* Mark the dynamic array as failed. All elements are deallocated as - a side effect. */ -#if 0 -static void - DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *list); -#endif - -/* Return the number of elements which have been added to the dynamic - array. */ -#if 0 -static size_t - DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *list); -#endif - -/* Return a pointer to the first array element, if any. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -#if 0 -static DYNARRAY_ELEMENT * - DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *list); -#endif - -/* Return a pointer one element past the last array element. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -#if 0 -static DYNARRAY_ELEMENT * - DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *list); -#endif - -/* Return a pointer to the array element at INDEX. Terminate the - process if INDEX is out of bounds. */ -#if 0 -static DYNARRAY_ELEMENT * - DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *list, size_t index); -#endif - -/* Add ITEM at the end of the array, enlarging it by one element. - Mark *LIST as failed if the dynamic array allocation size cannot be - increased. */ -#if 0 -static void - DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *list, - DYNARRAY_ELEMENT item); -#endif - -/* Allocate a place for a new element in *LIST and return a pointer to - it. The pointer can be NULL if the dynamic array cannot be - enlarged due to a memory allocation failure. */ -#if 0 -static DYNARRAY_ELEMENT * - DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *list); -#endif - -/* Change the size of *LIST to SIZE. If SIZE is larger than the - existing size, new elements are added (which can be initialized). - Otherwise, the list is truncated, and elements are freed. Return - false on memory allocation failure (and mark *LIST as failed). */ -#if 0 -static bool - DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *list, size_t size); -#endif - -/* Remove the last element of LIST if it is present. */ -#if 0 -static void - DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *list); -#endif - -/* Remove all elements from the list. The elements are freed, but the - list itself is not. */ -#if 0 -static void - DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *list); -#endif - -#if defined DYNARRAY_FINAL_TYPE -/* Transfer the dynamic array to a permanent location at *RESULT. - Returns true on success on false on allocation failure. In either - case, *LIST is re-initialized and can be reused. A NULL pointer is - stored in *RESULT if LIST refers to an empty list. On success, the - pointer in *RESULT is heap-allocated and must be deallocated using - free. */ -#if 0 -static bool - DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list, - DYNARRAY_FINAL_TYPE *result); -#endif -#else /* !defined DYNARRAY_FINAL_TYPE */ -/* Transfer the dynamic array to a heap-allocated array and return a - pointer to it. The pointer is NULL if memory allocation fails, or - if the array is empty, so this function should be used only for - arrays which are known not be empty (usually because they always - have a sentinel at the end). If LENGTHP is not NULL, the array - length is written to *LENGTHP. *LIST is re-initialized and can be - reused. */ -#if 0 -static DYNARRAY_ELEMENT * - DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list, - size_t *lengthp); -#endif -#endif - -/* A minimal example which provides a growing list of integers can be - defined like this: - - struct int_array - { - // Pointer to result array followed by its length, - // as required by DYNARRAY_FINAL_TYPE. - int *array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_int - #define DYNARRAY_ELEMENT int - #define DYNARRAY_PREFIX dynarray_int_ - #define DYNARRAY_FINAL_TYPE struct int_array - #include - - To create a three-element array with elements 1, 2, 3, use this - code: - - struct dynarray_int dyn; - dynarray_int_init (&dyn); - for (int i = 1; i <= 3; ++i) - { - int *place = dynarray_int_emplace (&dyn); - assert (place != NULL); - *place = i; - } - struct int_array result; - bool ok = dynarray_int_finalize (&dyn, &result); - assert (ok); - assert (result.length == 3); - assert (result.array[0] == 1); - assert (result.array[1] == 2); - assert (result.array[2] == 3); - free (result.array); - - If the elements contain resources which must be freed, define - DYNARRAY_ELEMENT_FREE appropriately, like this: - - struct str_array - { - char **array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_str - #define DYNARRAY_ELEMENT char * - #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) - #define DYNARRAY_PREFIX dynarray_str_ - #define DYNARRAY_FINAL_TYPE struct str_array - #include - */ - - -/* The implementation is imported from glibc. */ - -/* Avoid possible conflicts with symbols exported by the GNU libc. */ -#define __libc_dynarray_at_failure gl_dynarray_at_failure -#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge -#define __libc_dynarray_finalize gl_dynarray_finalize -#define __libc_dynarray_resize_clear gl_dynarray_resize_clear -#define __libc_dynarray_resize gl_dynarray_resize - -#if defined DYNARRAY_STRUCT || defined DYNARRAY_ELEMENT || defined DYNARRAY_PREFIX - -# ifndef _GL_LIKELY -/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ -# define _GL_LIKELY(cond) __builtin_expect ((cond), 1) -# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0) -# endif - -/* Define auxiliary structs and declare auxiliary functions, common to all - instantiations of dynarray. */ -# include - -/* Define the instantiation, specified through - DYNARRAY_STRUCT - DYNARRAY_ELEMENT - DYNARRAY_PREFIX - etc. */ -# include - -#else - -/* This file is being included from one of the malloc/dynarray_*.c files. */ -# include - -#endif - -#endif /* _GL_DYNARRAY_H */ diff --git a/xcompile/lib/eloop-threshold.h b/xcompile/lib/eloop-threshold.h deleted file mode 100644 index 510f261795d..00000000000 --- a/xcompile/lib/eloop-threshold.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Threshold at which to diagnose ELOOP. Generic version. - Copyright (C) 2012-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _ELOOP_THRESHOLD_H -#define _ELOOP_THRESHOLD_H 1 - -#include -#ifdef _LIBC -# include -# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) -#else -# include -# include "minmax.h" -# define __sysconf sysconf -# if (!defined SYMLOOP_MAX \ - && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX)) -# define SYMLOOP_MAX 8 -# endif -#endif - -/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic - links that can be reliably traversed in the resolution of a - pathname in the absence of a loop." This makes it a minimum that - we should certainly accept. But it leaves open the possibility - that more might sometimes work--just not "reliably". - - For example, Linux implements a complex policy whereby there is a - small limit on the number of direct symlink traversals (a symlink - to a symlink to a symlink), but larger limit on the total number of - symlink traversals overall. Hence the SYMLOOP_MAX number should be - the small one, but the limit library functions enforce on users - should be the larger one. - - So, we use the larger of the reported SYMLOOP_MAX (if any) and our - own constant MIN_ELOOP_THRESHOLD, below. This constant should be - large enough that it never rules out a file name and directory tree - that the underlying system (i.e. calls to 'open' et al) would - resolve successfully. It should be small enough that actual loops - are detected without a huge number of iterations. */ - -#ifndef MIN_ELOOP_THRESHOLD -# define MIN_ELOOP_THRESHOLD 40 -#endif - -/* Return the maximum number of symlink traversals to permit - before diagnosing ELOOP. */ -static inline unsigned int _GL_ATTRIBUTE_CONST -__eloop_threshold (void) -{ -#ifdef SYMLOOP_MAX - const int symloop_max = SYMLOOP_MAX; -#else - /* The function is marked 'const' even though we use memory and - call a function, because sysconf is required to return the - same value in every call and so it must always be safe to - call __eloop_threshold exactly once and reuse the value. */ - static long int sysconf_symloop_max; - if (sysconf_symloop_max == 0) - sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX); - const unsigned int symloop_max = (sysconf_symloop_max <= 0 - ? _POSIX_SYMLOOP_MAX - : sysconf_symloop_max); -#endif - - return MAX (symloop_max, MIN_ELOOP_THRESHOLD); -} - -#endif /* eloop-threshold.h */ diff --git a/xcompile/lib/errno.in.h b/xcompile/lib/errno.in.h deleted file mode 100644 index 3dda9c260e6..00000000000 --- a/xcompile/lib/errno.in.h +++ /dev/null @@ -1,279 +0,0 @@ -/* A POSIX-like . - - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _@GUARD_PREFIX@_ERRNO_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_ERRNO_H@ - -#ifndef _@GUARD_PREFIX@_ERRNO_H -#define _@GUARD_PREFIX@_ERRNO_H - - -/* On native Windows platforms, many macros are not defined. */ -# if defined _WIN32 && ! defined __CYGWIN__ - -/* These are the same values as defined by MSVC 10, for interoperability. */ - -# ifndef ENOMSG -# define ENOMSG 122 -# define GNULIB_defined_ENOMSG 1 -# endif - -# ifndef EIDRM -# define EIDRM 111 -# define GNULIB_defined_EIDRM 1 -# endif - -# ifndef ENOLINK -# define ENOLINK 121 -# define GNULIB_defined_ENOLINK 1 -# endif - -# ifndef EPROTO -# define EPROTO 134 -# define GNULIB_defined_EPROTO 1 -# endif - -# ifndef EBADMSG -# define EBADMSG 104 -# define GNULIB_defined_EBADMSG 1 -# endif - -# ifndef EOVERFLOW -# define EOVERFLOW 132 -# define GNULIB_defined_EOVERFLOW 1 -# endif - -# ifndef ENOTSUP -# define ENOTSUP 129 -# define GNULIB_defined_ENOTSUP 1 -# endif - -# ifndef ENETRESET -# define ENETRESET 117 -# define GNULIB_defined_ENETRESET 1 -# endif - -# ifndef ECONNABORTED -# define ECONNABORTED 106 -# define GNULIB_defined_ECONNABORTED 1 -# endif - -# ifndef ECANCELED -# define ECANCELED 105 -# define GNULIB_defined_ECANCELED 1 -# endif - -# ifndef EOWNERDEAD -# define EOWNERDEAD 133 -# define GNULIB_defined_EOWNERDEAD 1 -# endif - -# ifndef ENOTRECOVERABLE -# define ENOTRECOVERABLE 127 -# define GNULIB_defined_ENOTRECOVERABLE 1 -# endif - -# ifndef EINPROGRESS -# define EINPROGRESS 112 -# define EALREADY 103 -# define ENOTSOCK 128 -# define EDESTADDRREQ 109 -# define EMSGSIZE 115 -# define EPROTOTYPE 136 -# define ENOPROTOOPT 123 -# define EPROTONOSUPPORT 135 -# define EOPNOTSUPP 130 -# define EAFNOSUPPORT 102 -# define EADDRINUSE 100 -# define EADDRNOTAVAIL 101 -# define ENETDOWN 116 -# define ENETUNREACH 118 -# define ECONNRESET 108 -# define ENOBUFS 119 -# define EISCONN 113 -# define ENOTCONN 126 -# define ETIMEDOUT 138 -# define ECONNREFUSED 107 -# define ELOOP 114 -# define EHOSTUNREACH 110 -# define EWOULDBLOCK 140 -# define GNULIB_defined_ESOCK 1 -# endif - -# ifndef ETXTBSY -# define ETXTBSY 139 -# define ENODATA 120 /* not required by POSIX */ -# define ENOSR 124 /* not required by POSIX */ -# define ENOSTR 125 /* not required by POSIX */ -# define ETIME 137 /* not required by POSIX */ -# define EOTHER 131 /* not required by POSIX */ -# define GNULIB_defined_ESTREAMS 1 -# endif - -/* These are intentionally the same values as the WSA* error numbers, defined - in . */ -# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */ -# define EPFNOSUPPORT 10046 /* not required by POSIX */ -# define ESHUTDOWN 10058 /* not required by POSIX */ -# define ETOOMANYREFS 10059 /* not required by POSIX */ -# define EHOSTDOWN 10064 /* not required by POSIX */ -# define EPROCLIM 10067 /* not required by POSIX */ -# define EUSERS 10068 /* not required by POSIX */ -# define EDQUOT 10069 -# define ESTALE 10070 -# define EREMOTE 10071 /* not required by POSIX */ -# define GNULIB_defined_EWINSOCK 1 - -# endif - - -/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros - EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */ -# if @EMULTIHOP_HIDDEN@ -# define EMULTIHOP @EMULTIHOP_VALUE@ -# define GNULIB_defined_EMULTIHOP 1 -# endif -# if @ENOLINK_HIDDEN@ -# define ENOLINK @ENOLINK_VALUE@ -# define GNULIB_defined_ENOLINK 1 -# endif -# if @EOVERFLOW_HIDDEN@ -# define EOVERFLOW @EOVERFLOW_VALUE@ -# define GNULIB_defined_EOVERFLOW 1 -# endif - - -/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, - EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. - Likewise, on NonStop Kernel, EDQUOT is not defined. - Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, - HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. - - Note: When one of these systems defines some of these macros some day, - binaries will have to be recompiled so that they recognizes the new - errno values from the system. */ - -# ifndef ENOMSG -# define ENOMSG 2000 -# define GNULIB_defined_ENOMSG 1 -# endif - -# ifndef EIDRM -# define EIDRM 2001 -# define GNULIB_defined_EIDRM 1 -# endif - -# ifndef ENOLINK -# define ENOLINK 2002 -# define GNULIB_defined_ENOLINK 1 -# endif - -# ifndef EPROTO -# define EPROTO 2003 -# define GNULIB_defined_EPROTO 1 -# endif - -# ifndef EMULTIHOP -# define EMULTIHOP 2004 -# define GNULIB_defined_EMULTIHOP 1 -# endif - -# ifndef EBADMSG -# define EBADMSG 2005 -# define GNULIB_defined_EBADMSG 1 -# endif - -# ifndef EOVERFLOW -# define EOVERFLOW 2006 -# define GNULIB_defined_EOVERFLOW 1 -# endif - -# ifndef ENOTSUP -# define ENOTSUP 2007 -# define GNULIB_defined_ENOTSUP 1 -# endif - -# ifndef ENETRESET -# define ENETRESET 2011 -# define GNULIB_defined_ENETRESET 1 -# endif - -# ifndef ECONNABORTED -# define ECONNABORTED 2012 -# define GNULIB_defined_ECONNABORTED 1 -# endif - -# ifndef ESTALE -# define ESTALE 2009 -# define GNULIB_defined_ESTALE 1 -# endif - -# ifndef EDQUOT -# define EDQUOT 2010 -# define GNULIB_defined_EDQUOT 1 -# endif - -# ifndef ECANCELED -# define ECANCELED 2008 -# define GNULIB_defined_ECANCELED 1 -# endif - -/* On many platforms, the macros EOWNERDEAD and ENOTRECOVERABLE are not - defined. */ - -# ifndef EOWNERDEAD -# if defined __sun - /* Use the same values as defined for Solaris >= 8, for - interoperability. */ -# define EOWNERDEAD 58 -# define ENOTRECOVERABLE 59 -# elif defined _WIN32 && ! defined __CYGWIN__ - /* We have a conflict here: pthreads-win32 defines these values - differently than MSVC 10. It's hairy to decide which one to use. */ -# if defined __MINGW32__ && !defined USE_WINDOWS_THREADS - /* Use the same values as defined by pthreads-win32, for - interoperability. */ -# define EOWNERDEAD 43 -# define ENOTRECOVERABLE 44 -# else - /* Use the same values as defined by MSVC 10, for - interoperability. */ -# define EOWNERDEAD 133 -# define ENOTRECOVERABLE 127 -# endif -# else -# define EOWNERDEAD 2013 -# define ENOTRECOVERABLE 2014 -# endif -# define GNULIB_defined_EOWNERDEAD 1 -# define GNULIB_defined_ENOTRECOVERABLE 1 -# endif - -# ifndef EILSEQ -# define EILSEQ 2015 -# define GNULIB_defined_EILSEQ 1 -# endif - -#endif /* _@GUARD_PREFIX@_ERRNO_H */ -#endif /* _@GUARD_PREFIX@_ERRNO_H */ diff --git a/xcompile/lib/euidaccess.c b/xcompile/lib/euidaccess.c deleted file mode 100644 index c2ecbeff52a..00000000000 --- a/xcompile/lib/euidaccess.c +++ /dev/null @@ -1,226 +0,0 @@ -/* euidaccess -- check if effective user id can access file - - Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2023 Free - Software Foundation, Inc. - - This file is part of the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by David MacKenzie and Torbjorn Granlund. - Adapted for GNU C library by Roland McGrath. */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include -#include -#if defined _WIN32 && ! defined __CYGWIN__ -# include -#else -# include "root-uid.h" -#endif - -#if HAVE_LIBGEN_H -# include -#endif - -#include -#ifndef __set_errno -# define __set_errno(val) errno = (val) -#endif - -#if defined EACCES && !defined EACCESS -# define EACCESS EACCES -#endif - -#ifndef F_OK -# define F_OK 0 -# define X_OK 1 -# define W_OK 2 -# define R_OK 4 -#endif - - -#ifdef _LIBC - -# define access __access -# define getuid __getuid -# define getgid __getgid -# define geteuid __geteuid -# define getegid __getegid -# define group_member __group_member -# define euidaccess __euidaccess -# undef stat -# define stat stat64 - -#endif - -/* Return 0 if the user has permission of type MODE on FILE; - otherwise, return -1 and set 'errno'. - Like access, except that it uses the effective user and group - id's instead of the real ones, and it does not always check for read-only - file system, text busy, etc. */ - -int -euidaccess (const char *file, int mode) -{ -#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */ - return faccessat (AT_FDCWD, file, mode, AT_EACCESS); -#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */ - return access (file, mode | EFF_ONLY_OK); -#elif defined ACC_SELF /* AIX */ - return accessx (file, mode, ACC_SELF); -#elif HAVE_EACCESS /* FreeBSD */ - return eaccess (file, mode); -#elif defined _WIN32 && ! defined __CYGWIN__ /* mingw */ - return _access (file, mode); -#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, BeOS */ - - uid_t uid = getuid (); - gid_t gid = getgid (); - uid_t euid = geteuid (); - gid_t egid = getegid (); - struct stat stats; - -# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS - - /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to - return the correct result even if this would make it - nonreentrant. Define this only if your entire application is - safe even if the uid or gid might temporarily change. If your - application uses signal handlers or threads it is probably not - safe. */ - - if (mode == F_OK) - { - int result = stat (file, &stats); - return result != 0 && errno == EOVERFLOW ? 0 : result; - } - else - { - int result; - int saved_errno; - - if (uid != euid) - setreuid (euid, uid); - if (gid != egid) - setregid (egid, gid); - - result = access (file, mode); - saved_errno = errno; - - /* Restore them. */ - if (uid != euid) - setreuid (uid, euid); - if (gid != egid) - setregid (gid, egid); - - errno = saved_errno; - return result; - } - -# else - - /* The following code assumes the traditional Unix model, and is not - correct on systems that have ACLs or the like. However, it's - better than nothing, and it is reentrant. */ - - unsigned int granted; - if (uid == euid && gid == egid) - /* If we are not set-uid or set-gid, access does the same. */ - return access (file, mode); - - if (stat (file, &stats) == -1) - return mode == F_OK && errno == EOVERFLOW ? 0 : -1; - - /* The super-user can read and write any file, and execute any file - that anyone can execute. */ - if (euid == ROOT_UID - && ((mode & X_OK) == 0 - || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))) - return 0; - - /* Convert the mode to traditional form, clearing any bogus bits. */ - if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0) - mode &= 7; - else - mode = ((mode & R_OK ? 4 : 0) - + (mode & W_OK ? 2 : 0) - + (mode & X_OK ? 1 : 0)); - - if (mode == 0) - return 0; /* The file exists. */ - - /* Convert the file's permission bits to traditional form. */ - if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6) - && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3) - && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0)) - granted = stats.st_mode; - else - granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0) - + (stats.st_mode & S_IWUSR ? 2 << 6 : 0) - + (stats.st_mode & S_IXUSR ? 1 << 6 : 0) - + (stats.st_mode & S_IRGRP ? 4 << 3 : 0) - + (stats.st_mode & S_IWGRP ? 2 << 3 : 0) - + (stats.st_mode & S_IXGRP ? 1 << 3 : 0) - + (stats.st_mode & S_IROTH ? 4 << 0 : 0) - + (stats.st_mode & S_IWOTH ? 2 << 0 : 0) - + (stats.st_mode & S_IXOTH ? 1 << 0 : 0)); - - if (euid == stats.st_uid) - granted >>= 6; - else if (egid == stats.st_gid || group_member (stats.st_gid)) - granted >>= 3; - - if ((mode & ~granted) == 0) - return 0; - __set_errno (EACCESS); - return -1; - -# endif -#endif -} -#undef euidaccess -#ifdef weak_alias -weak_alias (__euidaccess, euidaccess) -#endif - -#ifdef TEST -# include -# include -# include - -int -main (int argc, char **argv) -{ - char *file; - int mode; - int err; - - if (argc < 3) - abort (); - file = argv[1]; - mode = atoi (argv[2]); - - err = euidaccess (file, mode); - printf ("%d\n", err); - if (err != 0) - error (0, errno, "%s", file); - exit (0); -} -#endif diff --git a/xcompile/lib/execinfo.c b/xcompile/lib/execinfo.c deleted file mode 100644 index 2048d00f5fb..00000000000 --- a/xcompile/lib/execinfo.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Information about executables. - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define _GL_EXECINFO_INLINE _GL_EXTERN_INLINE -#include "execinfo.h" diff --git a/xcompile/lib/execinfo.in.h b/xcompile/lib/execinfo.in.h deleted file mode 100644 index ff9293b6327..00000000000 --- a/xcompile/lib/execinfo.in.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Information about executables. - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This program 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 program is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef _GL_EXECINFO_H -#define _GL_EXECINFO_H - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_EXECINFO_INLINE -# define _GL_EXECINFO_INLINE _GL_INLINE -#endif - -_GL_EXECINFO_INLINE int -backtrace (void **buffer, int size) -{ - (void) buffer; - (void) size; - return 0; -} - -_GL_EXECINFO_INLINE char ** -backtrace_symbols (void *const *buffer, int size) -{ - (void) buffer; - (void) size; - return 0; -} - -_GL_EXECINFO_INLINE void -backtrace_symbols_fd (void *const *buffer, int size, int fd) -{ - (void) buffer; - (void) size; - (void) fd; -} - -_GL_INLINE_HEADER_END - -#endif diff --git a/xcompile/lib/explicit_bzero.c b/xcompile/lib/explicit_bzero.c deleted file mode 100644 index c33cab9e6d5..00000000000 --- a/xcompile/lib/explicit_bzero.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Erasure of sensitive data, generic implementation. - Copyright (C) 2016-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* An assembler implementation of explicit_bzero can be created as an - assembler alias of an optimized bzero implementation. - Architecture-specific implementations also need to define - __explicit_bzero_chk. */ - -#if !_LIBC -# include -#endif - -/* memset_s need this define */ -#if HAVE_MEMSET_S -# define __STDC_WANT_LIB_EXT1__ 1 -#endif - -#include - -#if defined _WIN32 && !defined __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -#endif - -#if _LIBC -/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero - redirects to that. */ -# undef explicit_bzero -#endif - -/* Set LEN bytes of S to 0. The compiler will not delete a call to - this function, even if S is dead after the call. */ -void -explicit_bzero (void *s, size_t len) -{ -#if defined _WIN32 && !defined __CYGWIN__ - (void) SecureZeroMemory (s, len); -#elif HAVE_EXPLICIT_MEMSET - explicit_memset (s, '\0', len); -#elif HAVE_MEMSET_S - (void) memset_s (s, len, '\0', len); -#elif defined __GNUC__ && !defined __clang__ - memset (s, '\0', len); - /* Compiler barrier. */ - asm volatile ("" ::: "memory"); -#elif defined __clang__ - memset (s, '\0', len); - /* Compiler barrier. */ - /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the - whole thing is dead and eliminates it. Use 'g' to work around this - problem. See . */ - __asm__ volatile ("" : : "g"(s) : "memory"); -#else - /* Invoke memset through a volatile function pointer. This defeats compiler - optimizations. */ - void * (* const volatile volatile_memset) (void *, int, size_t) = memset; - (void) volatile_memset (s, '\0', len); -#endif -} diff --git a/xcompile/lib/faccessat.c b/xcompile/lib/faccessat.c deleted file mode 100644 index ac8977cfd65..00000000000 --- a/xcompile/lib/faccessat.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Check the access rights of a file relative to an open directory. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Eric Blake */ - -/* If the user's config.h happens to include , let it include only - the system's here, so that orig_faccessat doesn't recurse to - rpl_faccessat. */ -#define _GL_INCLUDING_UNISTD_H -#include - -/* Specification. */ -#include - -#include -#include -#include -#include -#include -#undef _GL_INCLUDING_UNISTD_H - -#if HAVE_FACCESSAT -static int -orig_faccessat (int fd, char const *name, int mode, int flag) -{ - return faccessat (fd, name, mode, flag); -} -#endif - -/* Write "unistd.h" here, not , otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include - above. */ -#include "unistd.h" - -#ifndef HAVE_ACCESS -/* Mingw lacks access, but it also lacks real vs. effective ids, so - the gnulib euidaccess module is good enough. */ -# undef access -# define access euidaccess -#endif - -#if HAVE_FACCESSAT - -int -rpl_faccessat (int fd, char const *file, int mode, int flag) -{ - int result = orig_faccessat (fd, file, mode, flag); - - if (result == 0 && file[strlen (file) - 1] == '/') - { - struct stat st; - result = fstatat (fd, file, &st, 0); - if (result == 0 && !S_ISDIR (st.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } - - return result; -} - -#else /* !HAVE_FACCESSAT */ - -/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory - open on descriptor FD. If possible, do it without changing the - working directory. Otherwise, resort to using save_cwd/fchdir, then - (access|euidaccess)/restore_cwd. If either the save_cwd or the - restore_cwd fails, then give a diagnostic and exit nonzero. - Note that this implementation only supports AT_EACCESS, although some - native versions also support AT_SYMLINK_NOFOLLOW. */ - -# define AT_FUNC_NAME faccessat -# define AT_FUNC_F1 euidaccess -# define AT_FUNC_F2 access -# define AT_FUNC_USE_F1_COND AT_EACCESS -# define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag -# define AT_FUNC_POST_FILE_ARGS , mode -# include "at-func.c" - -#endif diff --git a/xcompile/lib/fchmodat.c b/xcompile/lib/fchmodat.c deleted file mode 100644 index a7b70a2af2c..00000000000 --- a/xcompile/lib/fchmodat.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Change the protections of file relative to an open directory. - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Jim Meyering and Paul Eggert */ - -/* If the user's config.h happens to include , let it include only - the system's here, so that orig_fchmodat doesn't recurse to - rpl_fchmodat. */ -#define __need_system_sys_stat_h -#include - -/* Specification. */ -#include -#undef __need_system_sys_stat_h - -#if HAVE_FCHMODAT -static int -orig_fchmodat (int dir, char const *file, mode_t mode, int flags) -{ - return fchmodat (dir, file, mode, flags); -} -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef __osf__ -/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include - above. */ -# include "sys/stat.h" -#else -# include -#endif - -#include - -/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory - open on descriptor FD. If possible, do it without changing the - working directory. Otherwise, resort to using save_cwd/fchdir, - then (chmod|lchmod)/restore_cwd. If either the save_cwd or the - restore_cwd fails, then give a diagnostic and exit nonzero. - Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW - on a system without lchmod support causes this function to fail. */ - -#if HAVE_FCHMODAT -int -fchmodat (int dir, char const *file, mode_t mode, int flags) -{ -# if HAVE_NEARLY_WORKING_FCHMODAT - /* Correct the trailing slash handling. */ - size_t len = strlen (file); - if (len && file[len - 1] == '/') - { - struct stat st; - if (fstatat (dir, file, &st, flags & AT_SYMLINK_NOFOLLOW) < 0) - return -1; - if (!S_ISDIR (st.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } -# endif - -# if NEED_FCHMODAT_NONSYMLINK_FIX - if (flags == AT_SYMLINK_NOFOLLOW) - { -# if HAVE_READLINKAT - char readlink_buf[1]; - -# ifdef O_PATH - /* Open a file descriptor with O_NOFOLLOW, to make sure we don't - follow symbolic links, if /proc is mounted. O_PATH is used to - avoid a failure if the file is not readable. - Cf. */ - int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) - return fd; - - int err; - if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) - err = EOPNOTSUPP; - else if (errno == EINVAL) - { - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; - } - else - err = errno == ENOENT ? -1 : errno; - - close (fd); - - errno = err; - if (0 <= err) - return err == 0 ? 0 : -1; -# endif - - /* O_PATH + /proc is not supported. */ - - if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf)) - { - errno = EOPNOTSUPP; - return -1; - } -# endif - - /* Fall back on orig_fchmodat with no flags, despite a possible race. */ - flags = 0; - } -# endif - - return orig_fchmodat (dir, file, mode, flags); -} -#else -# define AT_FUNC_NAME fchmodat -# define AT_FUNC_F1 lchmod -# define AT_FUNC_F2 chmod -# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW -# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag -# define AT_FUNC_POST_FILE_ARGS , mode -# include "at-func.c" -#endif diff --git a/xcompile/lib/fcntl.c b/xcompile/lib/fcntl.c deleted file mode 100644 index e220800845b..00000000000 --- a/xcompile/lib/fcntl.c +++ /dev/null @@ -1,629 +0,0 @@ -/* Provide file descriptor control. - - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Eric Blake . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include -#include - -#ifdef __KLIBC__ -# define INCL_DOS -# include -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ -/* Get declarations of the native Windows API functions. */ -# define WIN32_LEAN_AND_MEAN -# include - -/* Get _get_osfhandle. */ -# if GNULIB_MSVC_NOTHROW -# include "msvc-nothrow.h" -# else -# include -# endif - -/* Upper bound on getdtablesize(). See lib/getdtablesize.c. */ -# define OPEN_MAX_MAX 0x10000 - -/* Duplicate OLDFD into the first available slot of at least NEWFD, - which must be positive, with FLAGS determining whether the duplicate - will be inheritable. */ -static int -dupfd (int oldfd, int newfd, int flags) -{ - /* Mingw has no way to create an arbitrary fd. Iterate until all - file descriptors less than newfd are filled up. */ - HANDLE curr_process = GetCurrentProcess (); - HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd); - unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT]; - unsigned int fds_to_close_bound = 0; - int result; - BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE; - int mode; - - if (newfd < 0 || getdtablesize () <= newfd) - { - errno = EINVAL; - return -1; - } - if (old_handle == INVALID_HANDLE_VALUE - || (mode = _setmode (oldfd, O_BINARY)) == -1) - { - /* oldfd is not open, or is an unassigned standard file - descriptor. */ - errno = EBADF; - return -1; - } - _setmode (oldfd, mode); - flags |= mode; - - for (;;) - { - HANDLE new_handle; - int duplicated_fd; - unsigned int index; - - if (!DuplicateHandle (curr_process, /* SourceProcessHandle */ - old_handle, /* SourceHandle */ - curr_process, /* TargetProcessHandle */ - (PHANDLE) &new_handle, /* TargetHandle */ - (DWORD) 0, /* DesiredAccess */ - inherit, /* InheritHandle */ - DUPLICATE_SAME_ACCESS)) /* Options */ - { - switch (GetLastError ()) - { - case ERROR_TOO_MANY_OPEN_FILES: - errno = EMFILE; - break; - case ERROR_INVALID_HANDLE: - case ERROR_INVALID_TARGET_HANDLE: - case ERROR_DIRECT_ACCESS_HANDLE: - errno = EBADF; - break; - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_FUNCTION: - case ERROR_INVALID_ACCESS: - errno = EINVAL; - break; - default: - errno = EACCES; - break; - } - result = -1; - break; - } - duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags); - if (duplicated_fd < 0) - { - CloseHandle (new_handle); - result = -1; - break; - } - if (newfd <= duplicated_fd) - { - result = duplicated_fd; - break; - } - - /* Set the bit duplicated_fd in fds_to_close[]. */ - index = (unsigned int) duplicated_fd / CHAR_BIT; - if (fds_to_close_bound <= index) - { - if (sizeof fds_to_close <= index) - /* Need to increase OPEN_MAX_MAX. */ - abort (); - memset (fds_to_close + fds_to_close_bound, '\0', - index + 1 - fds_to_close_bound); - fds_to_close_bound = index + 1; - } - fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT); - } - - /* Close the previous fds that turned out to be too small. */ - { - int saved_errno = errno; - unsigned int duplicated_fd; - - for (duplicated_fd = 0; - duplicated_fd < fds_to_close_bound * CHAR_BIT; - duplicated_fd++) - if ((fds_to_close[duplicated_fd / CHAR_BIT] - >> (duplicated_fd % CHAR_BIT)) - & 1) - close (duplicated_fd); - - errno = saved_errno; - } - -# if REPLACE_FCHDIR - if (0 <= result) - result = _gl_register_dup (oldfd, result); -# endif - return result; -} -#endif /* W32 */ - -/* Forward declarations, because we '#undef fcntl' in the middle of this - compilation unit. */ -/* Our implementation of fcntl (fd, F_DUPFD, target). */ -static int rpl_fcntl_DUPFD (int fd, int target); -/* Our implementation of fcntl (fd, F_DUPFD_CLOEXEC, target). */ -static int rpl_fcntl_DUPFD_CLOEXEC (int fd, int target); -#ifdef __KLIBC__ -/* Adds support for fcntl on directories. */ -static int klibc_fcntl (int fd, int action, /* arg */...); -#endif - - -/* Perform the specified ACTION on the file descriptor FD, possibly - using the argument ARG further described below. This replacement - handles the following actions, and forwards all others on to the - native fcntl. An unrecognized ACTION returns -1 with errno set to - EINVAL. - - F_DUPFD - duplicate FD, with int ARG being the minimum target fd. - If successful, return the duplicate, which will be inheritable; - otherwise return -1 and set errno. - - F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum - target fd. If successful, return the duplicate, which will not be - inheritable; otherwise return -1 and set errno. - - F_GETFD - ARG need not be present. If successful, return a - non-negative value containing the descriptor flags of FD (only - FD_CLOEXEC is portable, but other flags may be present); otherwise - return -1 and set errno. */ - -int -fcntl (int fd, int action, /* arg */...) -#undef fcntl -#ifdef __KLIBC__ -# define fcntl klibc_fcntl -#endif -{ - va_list arg; - int result = -1; - va_start (arg, action); - switch (action) - { - case F_DUPFD: - { - int target = va_arg (arg, int); - result = rpl_fcntl_DUPFD (fd, target); - break; - } - - case F_DUPFD_CLOEXEC: - { - int target = va_arg (arg, int); - result = rpl_fcntl_DUPFD_CLOEXEC (fd, target); - break; - } - -#if !HAVE_FCNTL - case F_GETFD: - { -# if defined _WIN32 && ! defined __CYGWIN__ - HANDLE handle = (HANDLE) _get_osfhandle (fd); - DWORD flags; - if (handle == INVALID_HANDLE_VALUE - || GetHandleInformation (handle, &flags) == 0) - errno = EBADF; - else - result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC; -# else /* !W32 */ - /* Use dup2 to reject invalid file descriptors. No way to - access this information, so punt. */ - if (0 <= dup2 (fd, fd)) - result = 0; -# endif /* !W32 */ - break; - } /* F_GETFD */ -#endif /* !HAVE_FCNTL */ - - /* Implementing F_SETFD on mingw is not trivial - there is no - API for changing the O_NOINHERIT bit on an fd, and merely - changing the HANDLE_FLAG_INHERIT bit on the underlying handle - can lead to odd state. It may be possible by duplicating the - handle, using _open_osfhandle with the right flags, then - using dup2 to move the duplicate onto the original, but that - is not supported for now. */ - - default: - { -#if HAVE_FCNTL - switch (action) - { - #ifdef F_BARRIERFSYNC /* macOS */ - case F_BARRIERFSYNC: - #endif - #ifdef F_CHKCLEAN /* macOS */ - case F_CHKCLEAN: - #endif - #ifdef F_CLOSEM /* NetBSD, HP-UX */ - case F_CLOSEM: - #endif - #ifdef F_FLUSH_DATA /* macOS */ - case F_FLUSH_DATA: - #endif - #ifdef F_FREEZE_FS /* macOS */ - case F_FREEZE_FS: - #endif - #ifdef F_FULLFSYNC /* macOS */ - case F_FULLFSYNC: - #endif - #ifdef F_GETCONFINED /* macOS */ - case F_GETCONFINED: - #endif - #ifdef F_GETDEFAULTPROTLEVEL /* macOS */ - case F_GETDEFAULTPROTLEVEL: - #endif - #ifdef F_GETFD /* POSIX */ - case F_GETFD: - #endif - #ifdef F_GETFL /* POSIX */ - case F_GETFL: - #endif - #ifdef F_GETLEASE /* Linux */ - case F_GETLEASE: - #endif - #ifdef F_GETNOSIGPIPE /* macOS */ - case F_GETNOSIGPIPE: - #endif - #ifdef F_GETOWN /* POSIX */ - case F_GETOWN: - #endif - #ifdef F_GETPIPE_SZ /* Linux */ - case F_GETPIPE_SZ: - #endif - #ifdef F_GETPROTECTIONCLASS /* macOS */ - case F_GETPROTECTIONCLASS: - #endif - #ifdef F_GETPROTECTIONLEVEL /* macOS */ - case F_GETPROTECTIONLEVEL: - #endif - #ifdef F_GET_SEALS /* Linux */ - case F_GET_SEALS: - #endif - #ifdef F_GETSIG /* Linux */ - case F_GETSIG: - #endif - #ifdef F_MAXFD /* NetBSD */ - case F_MAXFD: - #endif - #ifdef F_RECYCLE /* macOS */ - case F_RECYCLE: - #endif - #ifdef F_SETFIFOENH /* HP-UX */ - case F_SETFIFOENH: - #endif - #ifdef F_THAW_FS /* macOS */ - case F_THAW_FS: - #endif - /* These actions take no argument. */ - result = fcntl (fd, action); - break; - - #ifdef F_ADD_SEALS /* Linux */ - case F_ADD_SEALS: - #endif - #ifdef F_BADFD /* Solaris */ - case F_BADFD: - #endif - #ifdef F_CHECK_OPENEVT /* macOS */ - case F_CHECK_OPENEVT: - #endif - #ifdef F_DUP2FD /* FreeBSD, AIX, Solaris */ - case F_DUP2FD: - #endif - #ifdef F_DUP2FD_CLOEXEC /* FreeBSD, Solaris */ - case F_DUP2FD_CLOEXEC: - #endif - #ifdef F_DUP2FD_CLOFORK /* Solaris */ - case F_DUP2FD_CLOFORK: - #endif - #ifdef F_DUPFD /* POSIX */ - case F_DUPFD: - #endif - #ifdef F_DUPFD_CLOEXEC /* POSIX */ - case F_DUPFD_CLOEXEC: - #endif - #ifdef F_DUPFD_CLOFORK /* Solaris */ - case F_DUPFD_CLOFORK: - #endif - #ifdef F_GETXFL /* Solaris */ - case F_GETXFL: - #endif - #ifdef F_GLOBAL_NOCACHE /* macOS */ - case F_GLOBAL_NOCACHE: - #endif - #ifdef F_MAKECOMPRESSED /* macOS */ - case F_MAKECOMPRESSED: - #endif - #ifdef F_MOVEDATAEXTENTS /* macOS */ - case F_MOVEDATAEXTENTS: - #endif - #ifdef F_NOCACHE /* macOS */ - case F_NOCACHE: - #endif - #ifdef F_NODIRECT /* macOS */ - case F_NODIRECT: - #endif - #ifdef F_NOTIFY /* Linux */ - case F_NOTIFY: - #endif - #ifdef F_OPLKACK /* IRIX */ - case F_OPLKACK: - #endif - #ifdef F_OPLKREG /* IRIX */ - case F_OPLKREG: - #endif - #ifdef F_RDAHEAD /* macOS */ - case F_RDAHEAD: - #endif - #ifdef F_SETBACKINGSTORE /* macOS */ - case F_SETBACKINGSTORE: - #endif - #ifdef F_SETCONFINED /* macOS */ - case F_SETCONFINED: - #endif - #ifdef F_SETFD /* POSIX */ - case F_SETFD: - #endif - #ifdef F_SETFL /* POSIX */ - case F_SETFL: - #endif - #ifdef F_SETLEASE /* Linux */ - case F_SETLEASE: - #endif - #ifdef F_SETNOSIGPIPE /* macOS */ - case F_SETNOSIGPIPE: - #endif - #ifdef F_SETOWN /* POSIX */ - case F_SETOWN: - #endif - #ifdef F_SETPIPE_SZ /* Linux */ - case F_SETPIPE_SZ: - #endif - #ifdef F_SETPROTECTIONCLASS /* macOS */ - case F_SETPROTECTIONCLASS: - #endif - #ifdef F_SETSIG /* Linux */ - case F_SETSIG: - #endif - #ifdef F_SINGLE_WRITER /* macOS */ - case F_SINGLE_WRITER: - #endif - /* These actions take an 'int' argument. */ - { - int x = va_arg (arg, int); - result = fcntl (fd, action, x); - } - break; - - default: - /* Other actions take a pointer argument. */ - { - void *p = va_arg (arg, void *); - result = fcntl (fd, action, p); - } - break; - } -#else - errno = EINVAL; -#endif - break; - } - } - va_end (arg); - return result; -} - -static int -rpl_fcntl_DUPFD (int fd, int target) -{ - int result; -#if !HAVE_FCNTL - result = dupfd (fd, target, 0); -#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR - /* Detect invalid target; needed for cygwin 1.5.x. */ - if (target < 0 || getdtablesize () <= target) - { - result = -1; - errno = EINVAL; - } - else - { - /* Haiku alpha 2 loses fd flags on original. */ - int flags = fcntl (fd, F_GETFD); - if (flags < 0) - result = -1; - else - { - result = fcntl (fd, F_DUPFD, target); - if (0 <= result && fcntl (fd, F_SETFD, flags) == -1) - { - int saved_errno = errno; - close (result); - result = -1; - errno = saved_errno; - } -# if REPLACE_FCHDIR - if (0 <= result) - result = _gl_register_dup (fd, result); -# endif - } - } -#else - result = fcntl (fd, F_DUPFD, target); -#endif - return result; -} - -static int -rpl_fcntl_DUPFD_CLOEXEC (int fd, int target) -{ - int result; -#if !HAVE_FCNTL - result = dupfd (fd, target, O_CLOEXEC); -#else /* HAVE_FCNTL */ -# if defined __NetBSD__ || defined __HAIKU__ - /* On NetBSD 9.0, the system fcntl (fd, F_DUPFD_CLOEXEC, target) - has only the same effect as fcntl (fd, F_DUPFD, target). */ - /* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets - the FD_CLOEXEC flag on fd, not on target. Therefore avoid the - system fcntl in this case. */ -# define have_dupfd_cloexec -1 -# else - /* Try the system call first, if the headers claim it exists - (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we - may be running with a glibc that has the macro but with an - older kernel that does not support it. Cache the - information on whether the system call really works, but - avoid caching failure if the corresponding F_DUPFD fails - for any reason. 0 = unknown, 1 = yes, -1 = no. */ - static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0; - if (0 <= have_dupfd_cloexec) - { - result = fcntl (fd, F_DUPFD_CLOEXEC, target); - if (0 <= result || errno != EINVAL) - { - have_dupfd_cloexec = 1; -# if REPLACE_FCHDIR - if (0 <= result) - result = _gl_register_dup (fd, result); -# endif - } - else - { - result = rpl_fcntl_DUPFD (fd, target); - if (result >= 0) - have_dupfd_cloexec = -1; - } - } - else -# endif - result = rpl_fcntl_DUPFD (fd, target); - if (0 <= result && have_dupfd_cloexec == -1) - { - int flags = fcntl (result, F_GETFD); - if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1) - { - int saved_errno = errno; - close (result); - errno = saved_errno; - result = -1; - } - } -#endif /* HAVE_FCNTL */ - return result; -} - -#undef fcntl - -#ifdef __KLIBC__ - -static int -klibc_fcntl (int fd, int action, /* arg */...) -{ - va_list arg_ptr; - int arg; - struct stat sbuf; - int result; - - va_start (arg_ptr, action); - arg = va_arg (arg_ptr, int); - result = fcntl (fd, action, arg); - /* EPERM for F_DUPFD, ENOTSUP for others */ - if (result == -1 && (errno == EPERM || errno == ENOTSUP) - && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) - { - ULONG ulMode; - - switch (action) - { - case F_DUPFD: - /* Find available fd */ - while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) - arg++; - - result = dup2 (fd, arg); - break; - - /* Using underlying APIs is right ? */ - case F_GETFD: - if (DosQueryFHState (fd, &ulMode)) - break; - - result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; - break; - - case F_SETFD: - if (arg & ~FD_CLOEXEC) - break; - - if (DosQueryFHState (fd, &ulMode)) - break; - - if (arg & FD_CLOEXEC) - ulMode |= OPEN_FLAGS_NOINHERIT; - else - ulMode &= ~OPEN_FLAGS_NOINHERIT; - - /* Filter supported flags. */ - ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR - | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); - - if (DosSetFHState (fd, ulMode)) - break; - - result = 0; - break; - - case F_GETFL: - result = 0; - break; - - case F_SETFL: - if (arg != 0) - break; - - result = 0; - break; - - default: - errno = EINVAL; - break; - } - } - - va_end (arg_ptr); - - return result; -} - -#endif diff --git a/xcompile/lib/fcntl.in.h b/xcompile/lib/fcntl.in.h deleted file mode 100644 index e034eaf9f5a..00000000000 --- a/xcompile/lib/fcntl.in.h +++ /dev/null @@ -1,445 +0,0 @@ -/* Like , but with non-working flags defined to 0. - - Copyright (C) 2006-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Paul Eggert */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined __need_system_fcntl_h -/* Special invocation convention. */ - -/* Needed before . - May also define off_t to a 64-bit type on native Windows. */ -#include -/* On some systems other than glibc, is a prerequisite of - . On glibc systems, we would like to avoid namespace pollution. - But on glibc systems, includes inside an - extern "C" { ... } block, which leads to errors in C++ mode with the - overridden from gnulib. These errors are known to be gone - with g++ version >= 4.3. */ -#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) -# include -#endif -#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ - -/* Native Windows platforms declare open(), creat() in . */ -#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ - && (defined _WIN32 && ! defined __CYGWIN__) -# include -#endif - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_FCNTL_H - -/* Needed before . - May also define off_t to a 64-bit type on native Windows. */ -#include -/* On some systems other than glibc, is a prerequisite of - . On glibc systems, we would like to avoid namespace pollution. - But on glibc systems, includes inside an - extern "C" { ... } block, which leads to errors in C++ mode with the - overridden from gnulib. These errors are known to be gone - with g++ version >= 4.3. */ -#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && (defined __ICC || !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))) -# include -#endif -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_FCNTL_H@ - -/* Native Windows platforms declare open(), creat() in . */ -#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \ - && (defined _WIN32 && ! defined __CYGWIN__) -# include -#endif - -#ifndef _@GUARD_PREFIX@_FCNTL_H -#define _@GUARD_PREFIX@_FCNTL_H - -#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */ -# include -#endif - - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Declare overridden functions. */ - -#if @GNULIB_CREAT@ -# if @REPLACE_CREAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef creat -# define creat rpl_creat -# endif -_GL_FUNCDECL_RPL (creat, int, (const char *filename, mode_t mode) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (creat, int, (const char *filename, mode_t mode)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef creat -# define creat _creat -# endif -_GL_CXXALIAS_MDA (creat, int, (const char *filename, mode_t mode)); -# else -_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode)); -# endif -_GL_CXXALIASWARN (creat); -#elif defined GNULIB_POSIXCHECK -# undef creat -/* Assume creat is always declared. */ -_GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - " - "use gnulib module creat for portability"); -#elif @GNULIB_MDA_CREAT@ -/* On native Windows, map 'creat' to '_creat', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::creat always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef creat -# define creat _creat -# endif -/* Need to cast, because in mingw the last argument is 'int mode'. */ -_GL_CXXALIAS_MDA_CAST (creat, int, (const char *filename, mode_t mode)); -# else -_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode)); -# endif -_GL_CXXALIASWARN (creat); -#endif - -#if @GNULIB_FCNTL@ -# if @REPLACE_FCNTL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fcntl -# define fcntl rpl_fcntl -# endif -_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...)); -_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...)); -# if !GNULIB_defined_rpl_fcntl -# define GNULIB_defined_rpl_fcntl 1 -# endif -# else -# if !@HAVE_FCNTL@ -_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...)); -# if !GNULIB_defined_fcntl -# define GNULIB_defined_fcntl 1 -# endif -# endif -_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...)); -# endif -_GL_CXXALIASWARN (fcntl); -#elif defined GNULIB_POSIXCHECK -# undef fcntl -# if HAVE_RAW_DECL_FCNTL -_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - " - "use gnulib module fcntl for portability"); -# endif -#endif - -#if @GNULIB_OPEN@ -# if @REPLACE_OPEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef open -# define open rpl_open -# endif -_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef open -# define open _open -# endif -_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); -# else -_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); -# endif -/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a - default argument. _GL_CXXALIASWARN does not work in this case. */ -# if !defined __hpux -_GL_CXXALIASWARN (open); -# endif -#elif defined GNULIB_POSIXCHECK -# undef open -/* Assume open is always declared. */ -_GL_WARN_ON_USE (open, "open is not always POSIX compliant - " - "use gnulib module open for portability"); -#elif @GNULIB_MDA_OPEN@ -/* On native Windows, map 'open' to '_open', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::open always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef open -# define open _open -# endif -_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); -# else -_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); -# endif -# if !defined __hpux -_GL_CXXALIASWARN (open); -# endif -#endif - -#if @GNULIB_OPENAT@ -# if @REPLACE_OPENAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef openat -# define openat rpl_openat -# endif -_GL_FUNCDECL_RPL (openat, int, - (int fd, char const *file, int flags, /* mode_t mode */ ...) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (openat, int, - (int fd, char const *file, int flags, /* mode_t mode */ ...)); -# else -# if !@HAVE_OPENAT@ -_GL_FUNCDECL_SYS (openat, int, - (int fd, char const *file, int flags, /* mode_t mode */ ...) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (openat, int, - (int fd, char const *file, int flags, /* mode_t mode */ ...)); -# endif -_GL_CXXALIASWARN (openat); -#elif defined GNULIB_POSIXCHECK -# undef openat -# if HAVE_RAW_DECL_OPENAT -_GL_WARN_ON_USE (openat, "openat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -/* Fix up the FD_* macros, only known to be missing on mingw. */ - -#ifndef FD_CLOEXEC -# define FD_CLOEXEC 1 -#endif - -/* Fix up the supported F_* macros. Intentionally leave other F_* - macros undefined. Only known to be missing on mingw. */ - -#ifndef F_DUPFD_CLOEXEC -# define F_DUPFD_CLOEXEC 0x40000000 -/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */ -# define GNULIB_defined_F_DUPFD_CLOEXEC 1 -#else -# define GNULIB_defined_F_DUPFD_CLOEXEC 0 -#endif - -#ifndef F_DUPFD -# define F_DUPFD 1 -#endif - -#ifndef F_GETFD -# define F_GETFD 2 -#endif - -/* Fix up the O_* macros. */ - -/* AIX 7.1 with XL C 12.1 defines O_CLOEXEC, O_NOFOLLOW, and O_TTY_INIT - to values outside 'int' range, so omit these misdefinitions. - But avoid namespace pollution on non-AIX systems. */ -#ifdef _AIX -# include -# if defined O_CLOEXEC && ! (INT_MIN <= O_CLOEXEC && O_CLOEXEC <= INT_MAX) -# undef O_CLOEXEC -# endif -# if defined O_NOFOLLOW && ! (INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) -# undef O_NOFOLLOW -# endif -# if defined O_TTY_INIT && ! (INT_MIN <= O_TTY_INIT && O_TTY_INIT <= INT_MAX) -# undef O_TTY_INIT -# endif -#endif - -#if !defined O_DIRECT && defined O_DIRECTIO -/* Tru64 spells it 'O_DIRECTIO'. */ -# define O_DIRECT O_DIRECTIO -#endif - -#if !defined O_CLOEXEC && defined O_NOINHERIT -/* Mingw spells it 'O_NOINHERIT'. */ -# define O_CLOEXEC O_NOINHERIT -#endif - -#ifndef O_CLOEXEC -# define O_CLOEXEC 0x40000000 /* Try to not collide with system O_* flags. */ -# define GNULIB_defined_O_CLOEXEC 1 -#else -# define GNULIB_defined_O_CLOEXEC 0 -#endif - -#ifndef O_DIRECT -# define O_DIRECT 0 -#endif - -#ifndef O_DIRECTORY -# define O_DIRECTORY 0 -#endif - -#ifndef O_DSYNC -# define O_DSYNC 0 -#endif - -#ifndef O_EXEC -# define O_EXEC O_RDONLY /* This is often close enough in older systems. */ -#endif - -#ifndef O_IGNORE_CTTY -# define O_IGNORE_CTTY 0 -#endif - -#ifndef O_NDELAY -# define O_NDELAY 0 -#endif - -#ifndef O_NOATIME -# define O_NOATIME 0 -#endif - -#ifndef O_NONBLOCK -# define O_NONBLOCK O_NDELAY -#endif - -/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero - value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY - or to 0 as fallback. */ -#if @GNULIB_NONBLOCKING@ -# if O_NONBLOCK -# define GNULIB_defined_O_NONBLOCK 0 -# else -# define GNULIB_defined_O_NONBLOCK 1 -# undef O_NONBLOCK -# define O_NONBLOCK 0x40000000 -# endif -#endif - -#ifndef O_NOCTTY -# define O_NOCTTY 0 -#endif - -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif - -#ifndef O_NOLINK -# define O_NOLINK 0 -#endif - -#ifndef O_NOLINKS -# define O_NOLINKS 0 -#endif - -#ifndef O_NOTRANS -# define O_NOTRANS 0 -#endif - -#ifndef O_RSYNC -# define O_RSYNC 0 -#endif - -#ifndef O_SEARCH -# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */ -#endif - -#ifndef O_SYNC -# define O_SYNC 0 -#endif - -#ifndef O_TTY_INIT -# define O_TTY_INIT 0 -#endif - -#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) -# undef O_ACCMODE -# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH) -#endif - -/* For systems that distinguish between text and binary I/O. - O_BINARY is usually declared in fcntl.h */ -#if !defined O_BINARY && defined _O_BINARY - /* For MSC-compatible compilers. */ -# define O_BINARY _O_BINARY -# define O_TEXT _O_TEXT -#endif - -#if defined __BEOS__ || defined __HAIKU__ - /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */ -# undef O_BINARY -# undef O_TEXT -#endif - -#ifndef O_BINARY -# define O_BINARY 0 -# define O_TEXT 0 -#endif - -/* Fix up the AT_* macros. */ - -/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its - value exceeds INT_MAX, so its use as an int doesn't conform to the - C standard, and GCC and Sun C complain in some cases. If the bug - is present, undef AT_FDCWD here, so it can be redefined below. */ -#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 -# undef AT_FDCWD -#endif - -/* Use the same bit pattern as Solaris 9, but with the proper - signedness. The bit pattern is important, in case this actually is - Solaris with the above workaround. */ -#ifndef AT_FDCWD -# define AT_FDCWD (-3041965) -#endif - -/* Use the same values as Solaris 9. This shouldn't matter, but - there's no real reason to differ. */ -#ifndef AT_SYMLINK_NOFOLLOW -# define AT_SYMLINK_NOFOLLOW 4096 -#endif - -#ifndef AT_REMOVEDIR -# define AT_REMOVEDIR 1 -#endif - -/* Solaris 9 lacks these two, so just pick unique values. */ -#ifndef AT_SYMLINK_FOLLOW -# define AT_SYMLINK_FOLLOW 2 -#endif - -#ifndef AT_EACCESS -# define AT_EACCESS 4 -#endif - -/* Ignore this flag if not supported. */ -#ifndef AT_NO_AUTOMOUNT -# define AT_NO_AUTOMOUNT 0 -#endif - -#endif /* _@GUARD_PREFIX@_FCNTL_H */ -#endif /* _@GUARD_PREFIX@_FCNTL_H */ -#endif diff --git a/xcompile/lib/fdopendir.c b/xcompile/lib/fdopendir.c deleted file mode 100644 index aa841e3e819..00000000000 --- a/xcompile/lib/fdopendir.c +++ /dev/null @@ -1,249 +0,0 @@ -/* provide a replacement fdopendir function - Copyright (C) 2004-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Jim Meyering */ - -#include - -#include - -#include -#include - -#if !HAVE_FDOPENDIR - -# include "openat.h" -# include "openat-priv.h" -# include "save-cwd.h" - -# if GNULIB_DIRENT_SAFER -# include "dirent--.h" -# endif - -# ifndef REPLACE_FCHDIR -# define REPLACE_FCHDIR 0 -# endif - -static DIR *fdopendir_with_dup (int, int, struct saved_cwd const *); -static DIR *fd_clone_opendir (int, struct saved_cwd const *); - -/* Replacement for POSIX fdopendir. - - First, try to simulate it via opendir ("/proc/self/fd/..."). Failing - that, simulate it by using fchdir metadata, or by doing - save_cwd/fchdir/opendir(".")/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - - If successful, the resulting stream is based on FD in - implementations where streams are based on file descriptors and in - applications where no other thread or signal handler allocates or - frees file descriptors. In other cases, consult dirfd on the result - to find out whether FD is still being used. - - Otherwise, this function works just like POSIX fdopendir. - - W A R N I N G: - - Unlike other fd-related functions, this one places constraints on FD. - If this function returns successfully, FD is under control of the - dirent.h system, and the caller should not close or modify the state of - FD other than by the dirent.h functions. */ -# ifdef __KLIBC__ -# include - -DIR * -fdopendir (int fd) -{ - char path[_MAX_PATH]; - DIR *dirp; - - /* Get a path from fd */ - if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) - return NULL; - - dirp = opendir (path); - if (!dirp) - return NULL; - - /* Unregister fd registered by opendir() */ - _gl_unregister_dirp_fd (dirfd (dirp)); - - /* Register our fd */ - if (_gl_register_dirp_fd (fd, dirp)) - { - int saved_errno = errno; - - closedir (dirp); - - errno = saved_errno; - - dirp = NULL; - } - - return dirp; -} -# else -DIR * -fdopendir (int fd) -{ - DIR *dir = fdopendir_with_dup (fd, -1, NULL); - - if (! REPLACE_FCHDIR && ! dir) - { - int saved_errno = errno; - if (EXPECTED_ERRNO (saved_errno)) - { - struct saved_cwd cwd; - if (save_cwd (&cwd) != 0) - openat_save_fail (errno); - dir = fdopendir_with_dup (fd, -1, &cwd); - saved_errno = errno; - free_cwd (&cwd); - errno = saved_errno; - } - } - - return dir; -} -# endif - -/* Like fdopendir, except that if OLDER_DUPFD is not -1, it is known - to be a dup of FD which is less than FD - 1 and which will be - closed by the caller and not otherwise used by the caller. This - function makes sure that FD is closed and all file descriptors less - than FD are open, and then calls fd_clone_opendir on a dup of FD. - That way, barring race conditions, fd_clone_opendir returns a - stream whose file descriptor is FD. - - If REPLACE_FCHDIR or CWD is null, use opendir ("/proc/self/fd/...", - falling back on fchdir metadata. Otherwise, CWD is a saved version - of the working directory; use fchdir/opendir(".")/restore_cwd(CWD). */ -static DIR * -fdopendir_with_dup (int fd, int older_dupfd, struct saved_cwd const *cwd) -{ - int dupfd = dup (fd); - if (dupfd < 0 && errno == EMFILE) - dupfd = older_dupfd; - if (dupfd < 0) - return NULL; - else - { - DIR *dir; - int saved_errno; - if (dupfd < fd - 1 && dupfd != older_dupfd) - { - dir = fdopendir_with_dup (fd, dupfd, cwd); - saved_errno = errno; - } - else - { - close (fd); - dir = fd_clone_opendir (dupfd, cwd); - saved_errno = errno; - if (! dir) - { - int fd1 = dup (dupfd); - if (fd1 != fd) - openat_save_fail (fd1 < 0 ? errno : EBADF); - } - } - - if (dupfd != older_dupfd) - close (dupfd); - errno = saved_errno; - return dir; - } -} - -/* Like fdopendir, except the result controls a clone of FD. It is - the caller's responsibility both to close FD and (if the result is - not null) to closedir the result. */ -static DIR * -fd_clone_opendir (int fd, struct saved_cwd const *cwd) -{ - if (REPLACE_FCHDIR || ! cwd) - { - DIR *dir = NULL; - int saved_errno = EOPNOTSUPP; - char buf[OPENAT_BUFFER_SIZE]; - char *proc_file = openat_proc_name (buf, fd, "."); - if (proc_file) - { - dir = opendir (proc_file); - saved_errno = errno; - if (proc_file != buf) - free (proc_file); - } -# if REPLACE_FCHDIR - if (! dir && EXPECTED_ERRNO (saved_errno)) - { - char const *name = _gl_directory_name (fd); - DIR *dp = name ? opendir (name) : NULL; - - /* The caller has done an elaborate dance to arrange for opendir to - consume just the right file descriptor. If dirfd returns -1, - though, we're on a system like mingw where opendir does not - consume a file descriptor. Consume it via 'dup' instead. */ - if (dp && dirfd (dp) < 0) - dup (fd); - - return dp; - } -# endif - errno = saved_errno; - return dir; - } - else - { - if (fchdir (fd) != 0) - return NULL; - else - { - DIR *dir = opendir ("."); - int saved_errno = errno; - if (restore_cwd (cwd) != 0) - openat_restore_fail (errno); - errno = saved_errno; - return dir; - } - } -} - -#else /* HAVE_FDOPENDIR */ - -# include -# include - -# undef fdopendir - -/* Like fdopendir, but work around GNU/Hurd bug by validating FD. */ - -DIR * -rpl_fdopendir (int fd) -{ - struct stat st; - if (fstat (fd, &st)) - return NULL; - if (!S_ISDIR (st.st_mode)) - { - errno = ENOTDIR; - return NULL; - } - return fdopendir (fd); -} - -#endif /* HAVE_FDOPENDIR */ diff --git a/xcompile/lib/file-has-acl.c b/xcompile/lib/file-has-acl.c deleted file mode 100644 index b31a2ea2523..00000000000 --- a/xcompile/lib/file-has-acl.c +++ /dev/null @@ -1,621 +0,0 @@ -/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -/* Without this pragma, gcc 4.7.0 20120126 may suggest that the - file_has_acl function might be candidate for attribute 'const' */ -#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__ -# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" -#endif - -#include - -#include "acl.h" - -#include "acl-internal.h" - -#if USE_ACL && GETXATTR_WITH_POSIX_ACLS -# include -# include -# include -# include -# ifndef XATTR_NAME_NFSV4_ACL -# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" -# endif - -enum { - /* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */ - ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001, - ACE4_IDENTIFIER_GROUP = 0x00000040 -}; - -/* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial. - -1 upon failure to determine it. Possibly change errno. Assume that - the ACL is valid, except avoid undefined behavior even if invalid. - - See . The NFSv4 acls are - defined in Internet RFC 7530 and as such, every NFSv4 server - supporting ACLs should support NFSv4 ACLs (they differ from from - POSIX draft ACLs). The ACLs can be obtained via the - nfsv4-acl-tools, e.g., the nfs4_getfacl command. Gnulib provides - only basic support of NFSv4 ACLs, i.e., recognize trivial vs - nontrivial ACLs. */ - -static int -acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) -{ - enum { BYTES_PER_NETWORK_UINT = 4}; - - /* Grab the number of aces in the acl. */ - nbytes -= BYTES_PER_NETWORK_UINT; - if (nbytes < 0) - return -1; - uint32_t num_aces = ntohl (*xattr++); - if (6 < num_aces) - return 1; - int ace_found = 0; - - for (int ace_n = 0; ace_n < num_aces; ace_n++) - { - /* Get the acl type and flag. Skip the mask; it's too risky to - test it and it does not seem to be needed. Get the wholen. */ - nbytes -= 4 * BYTES_PER_NETWORK_UINT; - if (nbytes < 0) - return -1; - uint32_t type = ntohl (xattr[0]); - uint32_t flag = ntohl (xattr[1]); - uint32_t wholen = ntohl (xattr[3]); - xattr += 4; - int whowords = (wholen / BYTES_PER_NETWORK_UINT - + (wholen % BYTES_PER_NETWORK_UINT != 0)); - int64_t wholen4 = whowords; - wholen4 *= BYTES_PER_NETWORK_UINT; - - /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or - ACE4_ACCESS_DENIED_ACE_TYPE. */ - if (ACE4_ACCESS_DENIED_ACE_TYPE < type) - return 1; - - /* RFC 7530 says FLAG should be 0, but be generous to NetApp and - also accept the group flag. */ - if (flag & ~ACE4_IDENTIFIER_GROUP) - return 1; - - /* Get the who string. Check NBYTES - WHOLEN4 before storing - into NBYTES, to avoid truncation on conversion. */ - if (nbytes - wholen4 < 0) - return -1; - nbytes -= wholen4; - - /* For a trivial ACL, max 6 (typically 3) ACEs, 3 allow, 3 deny. - Check that there is at most one ACE of each TYPE and WHO. */ - int who2 - = (wholen == 6 && memcmp (xattr, "OWNER@", 6) == 0 ? 0 - : wholen == 6 && memcmp (xattr, "GROUP@", 6) == 0 ? 2 - : wholen == 9 && memcmp (xattr, "EVERYONE@", 9) == 0 ? 4 - : -1); - if (who2 < 0) - return 1; - int ace_found_bit = 1 << (who2 | type); - if (ace_found & ace_found_bit) - return 1; - ace_found |= ace_found_bit; - - xattr += whowords; - } - - return 0; -} -#endif - -/* Return 1 if NAME has a nontrivial access control list, - 0 if ACLs are not supported, or if NAME has no or only a base ACL, - and -1 (setting errno) on error. Note callers can determine - if ACLs are not supported as errno is set in that case also. - SB must be set to the stat buffer of NAME, - obtained through stat() or lstat(). */ - -int -file_has_acl (char const *name, struct stat const *sb) -{ -#if USE_ACL - if (! S_ISLNK (sb->st_mode)) - { - -# if GETXATTR_WITH_POSIX_ACLS - - ssize_t ret; - int initial_errno = errno; - - ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0); - if (ret < 0 && errno == ENODATA) - ret = 0; - else if (ret > 0) - return 1; - - if (ret == 0 && S_ISDIR (sb->st_mode)) - { - ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0); - if (ret < 0 && errno == ENODATA) - ret = 0; - else if (ret > 0) - return 1; - } - - if (ret < 0) - { - /* Check for NFSv4 ACLs. The max length of a trivial - ACL is 6 words for owner, 6 for group, 7 for everyone, - all times 2 because there are both allow and deny ACEs. - There are 6 words for owner because of type, flag, mask, - wholen, "OWNER@"+pad and similarly for group; everyone is - another word to hold "EVERYONE@". */ - uint32_t xattr[2 * (6 + 6 + 7)]; - - ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, sizeof xattr); - if (ret < 0) - switch (errno) - { - case ENODATA: return 0; - case ERANGE : return 1; /* ACL must be nontrivial. */ - } - else - { - /* It looks like a trivial ACL, but investigate further. */ - ret = acl_nfs4_nontrivial (xattr, ret); - if (ret < 0) - { - errno = EINVAL; - return ret; - } - errno = initial_errno; - } - } - if (ret < 0) - return - acl_errno_valid (errno); - return ret; - -# elif HAVE_ACL_GET_FILE - - /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ - /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - int ret; - - if (HAVE_ACL_EXTENDED_FILE) /* Linux */ - { - /* On Linux, acl_extended_file is an optimized function: It only - makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for - ACL_TYPE_DEFAULT. */ - ret = acl_extended_file (name); - } - else /* FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ - { -# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) - always return NULL / EINVAL. There is no point in making - these two useless calls. The real ACL is retrieved through - acl_get_file (name, ACL_TYPE_EXTENDED). */ - acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED); - if (acl) - { - ret = acl_extended_nontrivial (acl); - acl_free (acl); - } - else - ret = -1; -# else /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ - acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); - if (acl) - { - int saved_errno; - - ret = acl_access_nontrivial (acl); - saved_errno = errno; - acl_free (acl); - errno = saved_errno; -# if HAVE_ACL_FREE_TEXT /* Tru64 */ - /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always - returns NULL with errno not set. There is no point in - making this call. */ -# else /* FreeBSD, IRIX, Cygwin >= 2.5 */ - /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory - either both succeed or both fail; it depends on the - file system. Therefore there is no point in making the second - call if the first one already failed. */ - if (ret == 0 && S_ISDIR (sb->st_mode)) - { - acl = acl_get_file (name, ACL_TYPE_DEFAULT); - if (acl) - { -# ifdef __CYGWIN__ /* Cygwin >= 2.5 */ - ret = acl_access_nontrivial (acl); - saved_errno = errno; - acl_free (acl); - errno = saved_errno; -# else - ret = (0 < acl_entries (acl)); - acl_free (acl); -# endif - } - else - ret = -1; - } -# endif - } - else - ret = -1; -# endif - } - if (ret < 0) - return - acl_errno_valid (errno); - return ret; - -# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ - -# if defined ACL_NO_TRIVIAL - - /* Solaris 10 (newer version), which has additional API declared in - (acl_t) and implemented in libsec (acl_set, acl_trivial, - acl_fromtext, ...). */ - return acl_trivial (name); - -# else /* Solaris, Cygwin, general case */ - - /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions - of Unixware. The acl() call returns the access and default ACL both - at once. */ - { - /* Initially, try to read the entries into a stack-allocated buffer. - Use malloc if it does not fit. */ - enum - { - alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */ - alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t)) - }; - aclent_t buf[alloc_init]; - size_t alloc = alloc_init; - aclent_t *entries = buf; - aclent_t *malloced = NULL; - int count; - - for (;;) - { - count = acl (name, GETACL, alloc, entries); - if (count < 0 && errno == ENOSPC) - { - /* Increase the size of the buffer. */ - free (malloced); - if (alloc > alloc_max / 2) - { - errno = ENOMEM; - return -1; - } - alloc = 2 * alloc; /* <= alloc_max */ - entries = malloced = - (aclent_t *) malloc (alloc * sizeof (aclent_t)); - if (entries == NULL) - { - errno = ENOMEM; - return -1; - } - continue; - } - break; - } - if (count < 0) - { - if (errno == ENOSYS || errno == ENOTSUP) - ; - else - { - free (malloced); - return -1; - } - } - else if (count == 0) - ; - else - { - /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin - returns only 3 entries for files with no ACL. But this is safe: - If there are more than 4 entries, there cannot be only the - "user::", "group::", "other:", and "mask:" entries. */ - if (count > 4) - { - free (malloced); - return 1; - } - - if (acl_nontrivial (count, entries)) - { - free (malloced); - return 1; - } - } - free (malloced); - } - -# ifdef ACE_GETACL - /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 - file systems (whereas the other ones are used in UFS file systems). */ - { - /* Initially, try to read the entries into a stack-allocated buffer. - Use malloc if it does not fit. */ - enum - { - alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ - alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) - }; - ace_t buf[alloc_init]; - size_t alloc = alloc_init; - ace_t *entries = buf; - ace_t *malloced = NULL; - int count; - - for (;;) - { - count = acl (name, ACE_GETACL, alloc, entries); - if (count < 0 && errno == ENOSPC) - { - /* Increase the size of the buffer. */ - free (malloced); - if (alloc > alloc_max / 2) - { - errno = ENOMEM; - return -1; - } - alloc = 2 * alloc; /* <= alloc_max */ - entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); - if (entries == NULL) - { - errno = ENOMEM; - return -1; - } - continue; - } - break; - } - if (count < 0) - { - if (errno == ENOSYS || errno == EINVAL) - ; - else - { - free (malloced); - return -1; - } - } - else if (count == 0) - ; - else - { - /* In the old (original Solaris 10) convention: - If there are more than 3 entries, there cannot be only the - ACE_OWNER, ACE_GROUP, ACE_OTHER entries. - In the newer Solaris 10 and Solaris 11 convention: - If there are more than 6 entries, there cannot be only the - ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with - NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with - NEW_ACE_ACCESS_DENIED_ACE_TYPE. */ - if (count > 6) - { - free (malloced); - return 1; - } - - if (acl_ace_nontrivial (count, entries)) - { - free (malloced); - return 1; - } - } - free (malloced); - } -# endif - - return 0; -# endif - -# elif HAVE_GETACL /* HP-UX */ - - { - struct acl_entry entries[NACLENTRIES]; - int count; - - count = getacl (name, NACLENTRIES, entries); - - if (count < 0) - { - /* ENOSYS is seen on newer HP-UX versions. - EOPNOTSUPP is typically seen on NFS mounts. - ENOTSUP was seen on Quantum StorNext file systems (cvfs). */ - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) - ; - else - return -1; - } - else if (count == 0) - return 0; - else /* count > 0 */ - { - if (count > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory - allocation. */ - abort (); - - /* If there are more than 3 entries, there cannot be only the - (uid,%), (%,gid), (%,%) entries. */ - if (count > 3) - return 1; - - { - struct stat statbuf; - - if (stat (name, &statbuf) == -1 && errno != EOVERFLOW) - return -1; - - return acl_nontrivial (count, entries); - } - } - } - -# if HAVE_ACLV_H /* HP-UX >= 11.11 */ - - { - struct acl entries[NACLVENTRIES]; - int count; - - count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries); - - if (count < 0) - { - /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23. - EINVAL is seen on NFS in HP-UX 11.31. */ - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - ; - else - return -1; - } - else if (count == 0) - return 0; - else /* count > 0 */ - { - if (count > NACLVENTRIES) - /* If NACLVENTRIES cannot be trusted, use dynamic memory - allocation. */ - abort (); - - /* If there are more than 4 entries, there cannot be only the - four base ACL entries. */ - if (count > 4) - return 1; - - return aclv_nontrivial (count, entries); - } - } - -# endif - -# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ - - acl_type_t type; - char aclbuf[1024]; - void *acl = aclbuf; - size_t aclsize = sizeof (aclbuf); - mode_t mode; - - for (;;) - { - /* The docs say that type being 0 is equivalent to ACL_ANY, but it - is not true, in AIX 5.3. */ - type.u64 = ACL_ANY; - if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0) - break; - if (errno == ENOSYS) - return 0; - if (errno != ENOSPC) - { - if (acl != aclbuf) - free (acl); - return -1; - } - aclsize = 2 * aclsize; - if (acl != aclbuf) - free (acl); - acl = malloc (aclsize); - if (acl == NULL) - { - errno = ENOMEM; - return -1; - } - } - - if (type.u64 == ACL_AIXC) - { - int result = acl_nontrivial ((struct acl *) acl); - if (acl != aclbuf) - free (acl); - return result; - } - else if (type.u64 == ACL_NFS4) - { - int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl); - if (acl != aclbuf) - free (acl); - return result; - } - else - { - /* A newer type of ACL has been introduced in the system. - We should better support it. */ - if (acl != aclbuf) - free (acl); - errno = EINVAL; - return -1; - } - -# elif HAVE_STATACL /* older AIX */ - - union { struct acl a; char room[4096]; } u; - - if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0) - return -1; - - return acl_nontrivial (&u.a); - -# elif HAVE_ACLSORT /* NonStop Kernel */ - - { - struct acl entries[NACLENTRIES]; - int count; - - count = acl ((char *) name, ACL_GET, NACLENTRIES, entries); - - if (count < 0) - { - if (errno == ENOSYS || errno == ENOTSUP) - ; - else - return -1; - } - else if (count == 0) - return 0; - else /* count > 0 */ - { - if (count > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory - allocation. */ - abort (); - - /* If there are more than 4 entries, there cannot be only the - four base ACL entries. */ - if (count > 4) - return 1; - - return acl_nontrivial (count, entries); - } - } - -# endif - } -#endif - - return 0; -} diff --git a/xcompile/lib/filemode.c b/xcompile/lib/filemode.c deleted file mode 100644 index 318d287f27d..00000000000 --- a/xcompile/lib/filemode.c +++ /dev/null @@ -1,166 +0,0 @@ -/* filemode.c -- make a string describing file modes - - Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2023 Free - Software Foundation, Inc. - - This program is free software: you can 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 . */ - -#include - -#include "filemode.h" - -#if ! HAVE_DECL_STRMODE - -/* Return a character indicating the type of file described by - file mode BITS: - '-' regular file - 'b' block special file - 'c' character special file - 'C' high performance ("contiguous data") file - 'd' directory - 'D' door - 'l' symbolic link - 'm' multiplexed file (7th edition Unix; obsolete) - 'n' network special file (HP-UX) - 'p' fifo (named pipe) - 'P' port - 's' socket - 'w' whiteout (4.4BSD) - '?' some other file type */ - -static char -ftypelet (mode_t bits) -{ - /* These are the most common, so test for them first. */ - if (S_ISREG (bits)) - return '-'; - if (S_ISDIR (bits)) - return 'd'; - - /* Other letters standardized by POSIX 1003.1-2004. */ - if (S_ISBLK (bits)) - return 'b'; - if (S_ISCHR (bits)) - return 'c'; - if (S_ISLNK (bits)) - return 'l'; - if (S_ISFIFO (bits)) - return 'p'; - - /* Other file types (though not letters) standardized by POSIX. */ - if (S_ISSOCK (bits)) - return 's'; - - /* Nonstandard file types. */ - if (S_ISCTG (bits)) - return 'C'; - if (S_ISDOOR (bits)) - return 'D'; - if (S_ISMPB (bits) || S_ISMPC (bits) || S_ISMPX (bits)) - return 'm'; - if (S_ISNWK (bits)) - return 'n'; - if (S_ISPORT (bits)) - return 'P'; - if (S_ISWHT (bits)) - return 'w'; - - return '?'; -} - -/* Like filemodestring, but rely only on MODE. */ - -void -strmode (mode_t mode, char *str) -{ - str[0] = ftypelet (mode); - str[1] = mode & S_IRUSR ? 'r' : '-'; - str[2] = mode & S_IWUSR ? 'w' : '-'; - str[3] = (mode & S_ISUID - ? (mode & S_IXUSR ? 's' : 'S') - : (mode & S_IXUSR ? 'x' : '-')); - str[4] = mode & S_IRGRP ? 'r' : '-'; - str[5] = mode & S_IWGRP ? 'w' : '-'; - str[6] = (mode & S_ISGID - ? (mode & S_IXGRP ? 's' : 'S') - : (mode & S_IXGRP ? 'x' : '-')); - str[7] = mode & S_IROTH ? 'r' : '-'; - str[8] = mode & S_IWOTH ? 'w' : '-'; - str[9] = (mode & S_ISVTX - ? (mode & S_IXOTH ? 't' : 'T') - : (mode & S_IXOTH ? 'x' : '-')); - str[10] = ' '; - str[11] = '\0'; -} - -#endif /* ! HAVE_DECL_STRMODE */ - -/* filemodestring - fill in string STR with an ls-style ASCII - representation of the st_mode field of file stats block STATP. - 12 characters are stored in STR. - The characters stored in STR are: - - 0 File type, as in ftypelet above, except that other letters are used - for files whose type cannot be determined solely from st_mode: - - 'F' semaphore - 'Q' message queue - 'S' shared memory object - 'T' typed memory object - - 1 'r' if the owner may read, '-' otherwise. - - 2 'w' if the owner may write, '-' otherwise. - - 3 'x' if the owner may execute, 's' if the file is - set-user-id, '-' otherwise. - 'S' if the file is set-user-id, but the execute - bit isn't set. - - 4 'r' if group members may read, '-' otherwise. - - 5 'w' if group members may write, '-' otherwise. - - 6 'x' if group members may execute, 's' if the file is - set-group-id, '-' otherwise. - 'S' if it is set-group-id but not executable. - - 7 'r' if any user may read, '-' otherwise. - - 8 'w' if any user may write, '-' otherwise. - - 9 'x' if any user may execute, 't' if the file is "sticky" - (will be retained in swap space after execution), '-' - otherwise. - 'T' if the file is sticky but not executable. - - 10 ' ' for compatibility with 4.4BSD strmode, - since this interface does not support ACLs. - - 11 '\0'. */ - -void -filemodestring (struct stat const *statp, char *str) -{ - strmode (statp->st_mode, str); - - if (S_TYPEISSEM (statp)) - str[0] = 'F'; - else if (S_TYPEISMQ (statp)) - str[0] = 'Q'; - else if (S_TYPEISSHM (statp)) - str[0] = 'S'; - else if (S_TYPEISTMO (statp)) - str[0] = 'T'; -} diff --git a/xcompile/lib/filemode.h b/xcompile/lib/filemode.h deleted file mode 100644 index 15a8dcc3760..00000000000 --- a/xcompile/lib/filemode.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Make a string describing file modes. - - Copyright (C) 1998-1999, 2003, 2006, 2009-2023 Free Software Foundation, - Inc. - - This program is free software: you can 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 . */ - -#ifndef FILEMODE_H_ - -# include -# include - -/* Get the declaration of strmode. */ -# if HAVE_DECL_STRMODE -# include /* Mac OS X, FreeBSD, OpenBSD */ -# include /* NetBSD */ -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -# if !HAVE_DECL_STRMODE -extern void strmode (mode_t mode, char *str); -# endif - -extern void filemodestring (struct stat const *statp, char *str); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/xcompile/lib/filename.h b/xcompile/lib/filename.h deleted file mode 100644 index a2400a9dfe3..00000000000 --- a/xcompile/lib/filename.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Basic filename support macros. - Copyright (C) 2001-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* From Paul Eggert and Jim Meyering. */ - -#ifndef _FILENAME_H -#define _FILENAME_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Filename support. - ISSLASH(C) tests whether C is a directory separator - character. - HAS_DEVICE(Filename) tests whether Filename contains a device - specification. - FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification - at the beginning of Filename, - index of the part consisting of - alternating components and slashes. - FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - 1 when a non-empty device specification - can be followed by an empty or relative - part, - 0 when a non-empty device specification - must be followed by a slash, - 0 when device specification don't exist. - IS_ABSOLUTE_FILE_NAME(Filename) - tests whether Filename is independent of - any notion of "current directory". - IS_RELATIVE_FILE_NAME(Filename) - tests whether Filename may be concatenated - to a directory filename. - Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a - relative file name! - IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device - or directory specification. - */ -#if defined _WIN32 || defined __CYGWIN__ \ - || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__ - /* Native Windows, Cygwin, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') - /* Internal macro: Tests whether a character is a drive letter. */ -# define _IS_DRIVE_LETTER(C) \ - (((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z')) - /* Help the compiler optimizing it. This assumes ASCII. */ -# undef _IS_DRIVE_LETTER -# define _IS_DRIVE_LETTER(C) \ - (((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a') -# define HAS_DEVICE(Filename) \ - (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':') -# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0) -# ifdef __CYGWIN__ -# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 -# else - /* On native Windows, OS/2, DOS, the system has the notion of a - "current directory" on each drive. */ -# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1 -# endif -# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE -# define IS_ABSOLUTE_FILE_NAME(Filename) \ - ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)]) -# else -# define IS_ABSOLUTE_FILE_NAME(Filename) \ - (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)) -# endif -# define IS_RELATIVE_FILE_NAME(Filename) \ - (! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))) -# define IS_FILE_NAME_WITH_DIR(Filename) \ - (strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \ - || HAS_DEVICE (Filename)) -#else - /* Unix */ -# define ISSLASH(C) ((C) == '/') -# define HAS_DEVICE(Filename) ((void) (Filename), 0) -# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0) -# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 -# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0]) -# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0])) -# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL) -#endif - -/* Deprecated macros. For backward compatibility with old users of the - 'filename' module. */ -#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME -#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR - - -#ifdef __cplusplus -} -#endif - -#endif /* _FILENAME_H */ diff --git a/xcompile/lib/filevercmp.c b/xcompile/lib/filevercmp.c deleted file mode 100644 index 78e1faff536..00000000000 --- a/xcompile/lib/filevercmp.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Compare file names containing version numbers. - - Copyright (C) 1995 Ian Jackson - Copyright (C) 2001 Anthony Towns - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#include -#include "filevercmp.h" - -#include -#include -#include - -/* Return the length of a prefix of S that corresponds to the suffix - defined by this extended regular expression in the C locale: - (\.[A-Za-z~][A-Za-z0-9~]*)*$ - Use the longest suffix matching this regular expression, - except do not use all of S as a suffix if S is nonempty. - If *LEN is -1, S is a string; set *LEN to S's length. - Otherwise, *LEN should be nonnegative, S is a char array, - and *LEN does not change. */ -static idx_t -file_prefixlen (char const *s, ptrdiff_t *len) -{ - size_t n = *len; /* SIZE_MAX if N == -1. */ - idx_t prefixlen = 0; - - for (idx_t i = 0; ; ) - { - if (*len < 0 ? !s[i] : i == n) - { - *len = i; - return prefixlen; - } - - i++; - prefixlen = i; - while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) - || s[i + 1] == '~')) - for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) - continue; - } -} - -/* Return a version sort comparison value for S's byte at position POS. - S has length LEN. If POS == LEN, sort before all non-'~' bytes. */ - -static int -order (char const *s, idx_t pos, idx_t len) -{ - if (pos == len) - return -1; - - unsigned char c = s[pos]; - if (c_isdigit (c)) - return 0; - else if (c_isalpha (c)) - return c; - else if (c == '~') - return -2; - else - { - static_assert (UCHAR_MAX <= (INT_MAX - 1 - 2) / 2); - return c + UCHAR_MAX + 1; - } -} - -/* slightly modified verrevcmp function from dpkg - S1, S2 - compared char array - S1_LEN, S2_LEN - length of arrays to be scanned - - This implements the algorithm for comparison of version strings - specified by Debian and now widely adopted. The detailed - specification can be found in the Debian Policy Manual in the - section on the 'Version' control field. This version of the code - implements that from s5.6.12 of Debian Policy v3.8.0.1 - https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version */ -static int _GL_ATTRIBUTE_PURE -verrevcmp (const char *s1, idx_t s1_len, const char *s2, idx_t s2_len) -{ - idx_t s1_pos = 0; - idx_t s2_pos = 0; - while (s1_pos < s1_len || s2_pos < s2_len) - { - int first_diff = 0; - while ((s1_pos < s1_len && !c_isdigit (s1[s1_pos])) - || (s2_pos < s2_len && !c_isdigit (s2[s2_pos]))) - { - int s1_c = order (s1, s1_pos, s1_len); - int s2_c = order (s2, s2_pos, s2_len); - if (s1_c != s2_c) - return s1_c - s2_c; - s1_pos++; - s2_pos++; - } - while (s1_pos < s1_len && s1[s1_pos] == '0') - s1_pos++; - while (s2_pos < s2_len && s2[s2_pos] == '0') - s2_pos++; - while (s1_pos < s1_len && s2_pos < s2_len - && c_isdigit (s1[s1_pos]) && c_isdigit (s2[s2_pos])) - { - if (!first_diff) - first_diff = s1[s1_pos] - s2[s2_pos]; - s1_pos++; - s2_pos++; - } - if (s1_pos < s1_len && c_isdigit (s1[s1_pos])) - return 1; - if (s2_pos < s2_len && c_isdigit (s2[s2_pos])) - return -1; - if (first_diff) - return first_diff; - } - return 0; -} - -/* Compare version strings S1 and S2. - See filevercmp.h for function description. */ -int -filevercmp (const char *s1, const char *s2) -{ - return filenvercmp (s1, -1, s2, -1); -} - -/* Compare versions A (of length ALEN) and B (of length BLEN). - See filevercmp.h for function description. */ -int -filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen) -{ - /* Special case for empty versions. */ - bool aempty = alen < 0 ? !a[0] : !alen; - bool bempty = blen < 0 ? !b[0] : !blen; - if (aempty) - return -!bempty; - if (bempty) - return 1; - - /* Special cases for leading ".": "." sorts first, then "..", then - other names with leading ".", then other names. */ - if (a[0] == '.') - { - if (b[0] != '.') - return -1; - - bool adot = alen < 0 ? !a[1] : alen == 1; - bool bdot = blen < 0 ? !b[1] : blen == 1; - if (adot) - return -!bdot; - if (bdot) - return 1; - - bool adotdot = a[1] == '.' && (alen < 0 ? !a[2] : alen == 2); - bool bdotdot = b[1] == '.' && (blen < 0 ? !b[2] : blen == 2); - if (adotdot) - return -!bdotdot; - if (bdotdot) - return 1; - } - else if (b[0] == '.') - return 1; - - /* Cut file suffixes. */ - idx_t aprefixlen = file_prefixlen (a, &alen); - idx_t bprefixlen = file_prefixlen (b, &blen); - - /* If both suffixes are empty, a second pass would return the same thing. */ - bool one_pass_only = aprefixlen == alen && bprefixlen == blen; - - int result = verrevcmp (a, aprefixlen, b, bprefixlen); - - /* Return the initial result if nonzero, or if no second pass is needed. - Otherwise, restore the suffixes and try again. */ - return result || one_pass_only ? result : verrevcmp (a, alen, b, blen); -} diff --git a/xcompile/lib/filevercmp.h b/xcompile/lib/filevercmp.h deleted file mode 100644 index 6b81ab32a7f..00000000000 --- a/xcompile/lib/filevercmp.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Compare file names containing version numbers. - - Copyright (C) 1995 Ian Jackson - Copyright (C) 2001 Anthony Towns - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#ifndef FILEVERCMP_H -#define FILEVERCMP_H - -#include - -/* Compare strings A and B as file names containing version numbers, - and return an integer that is negative, zero, or positive depending - on whether A compares less than, equal to, or greater than B. - - Use the following version sort algorithm: - - 1. Compare the strings' maximal-length non-digit prefixes lexically. - If there is a difference return that difference. - Otherwise discard the prefixes and continue with the next step. - - 2. Compare the strings' maximal-length digit prefixes, using - numeric comparison of the numbers represented by each prefix. - (Treat an empty prefix as zero; this can happen only at string end.) - If there is a difference, return that difference. - Otherwise discard the prefixes and continue with the next step. - - 3. If both strings are empty, return 0. Otherwise continue with step 1. - - In version sort, lexical comparison is left to right, byte by byte, - using the byte's numeric value (0-255), except that: - - 1. ASCII letters sort before other bytes. - 2. A tilde sorts before anything, even an empty string. - - In addition to the version sort rules, the following strings have - special priority and sort before all other strings (listed in order): - - 1. The empty string. - 2. ".". - 3. "..". - 4. Strings starting with "." sort before other strings. - - Before comparing two strings where both begin with non-".", - or where both begin with "." but neither is "." or "..", - suffixes matching the C-locale extended regular expression - (\.[A-Za-z~][A-Za-z0-9~]*)*$ are removed and the strings compared - without them, using version sort without special priority; - if they do not compare equal, this comparison result is used and - the suffixes are effectively ignored. Otherwise, the entire - strings are compared using version sort. When removing a suffix - from a nonempty string, remove the maximal-length suffix such that - the remaining string is nonempty. - - This function is intended to be a replacement for strverscmp. */ -int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE; - -/* Like filevercmp, except compare the byte arrays A (of length ALEN) - and B (of length BLEN) so that A and B can contain '\0', which - sorts just before '\1'. But if ALEN is -1 treat A as a string - terminated by '\0', and similarly for BLEN. */ -int filenvercmp (char const *a, ptrdiff_t alen, char const *b, ptrdiff_t blen) - _GL_ATTRIBUTE_PURE; - -#endif /* FILEVERCMP_H */ diff --git a/xcompile/lib/fingerprint.c b/xcompile/lib/fingerprint.c deleted file mode 100644 index d83de2245e8..00000000000 --- a/xcompile/lib/fingerprint.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Placeholder fingerprint for Emacs - -Copyright 2019-2023 Free Software Foundation, Inc. - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can 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. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see . */ - -#include - -#include "fingerprint.h" - -/* This random fingerprint was generated by the shell command: - - shuf -i 0-255 -n 32 -r | awk '{printf " 0x%.02X,\n", $0}' - - In the final Emacs executable, this random fingerprint is replaced - by a fingerprint of the temporary Emacs executable that was built - along the way. */ - -volatile unsigned char fingerprint[] = - { - 0xDE, - 0x86, - 0xBB, - 0x99, - 0xFF, - 0xF5, - 0x46, - 0x9A, - 0x9E, - 0x3F, - 0x9F, - 0x5D, - 0x9A, - 0xDF, - 0xF0, - 0x91, - 0xBD, - 0xCD, - 0xC1, - 0xE8, - 0x0C, - 0x16, - 0x1E, - 0xAF, - 0xB8, - 0x6C, - 0xE2, - 0x2B, - 0xB1, - 0x24, - 0xCE, - 0xB0, - }; diff --git a/xcompile/lib/fingerprint.h b/xcompile/lib/fingerprint.h deleted file mode 100644 index 0bb099ceeee..00000000000 --- a/xcompile/lib/fingerprint.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Header file for the Emacs build fingerprint. - -Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc. - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can 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. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see . */ - -#ifndef EMACS_FINGERPRINT_H -#define EMACS_FINGERPRINT_H - -/* We generate fingerprint.c and fingerprint.o from all the sources in - Emacs. This way, we have a unique value that we can use to pair - data files (like a dump file) with a specific build of Emacs. */ -extern volatile unsigned char fingerprint[32]; - -#endif diff --git a/xcompile/lib/flexmember.h b/xcompile/lib/flexmember.h deleted file mode 100644 index a6cc876a6d5..00000000000 --- a/xcompile/lib/flexmember.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Sizes of structs with flexible array members. - - Copyright 2016-2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . - - Written by Paul Eggert. */ - -#include - -/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. - On older platforms without _Alignof, use a pessimistic bound that is - safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. - On newer platforms, use _Alignof to get a tighter bound. */ - -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 -# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) -#else -# define FLEXALIGNOF(type) _Alignof (type) -#endif - -/* Yield a properly aligned upper bound on the size of a struct of - type TYPE with a flexible array member named MEMBER that is - followed by N bytes of other data. The result is suitable as an - argument to malloc. For example: - - struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; }; - struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char))); - - FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N), - since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is - it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size - that causes malloc to yield a pointer that is not properly aligned - for TYPE; for example, if sizeof (int) == alignof (int) == 4, - malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent - to malloc (7) and might yield a pointer that is not a multiple of 4 - (which means the pointer is not properly aligned for struct s), - whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is - equivalent to malloc (8) and must yield a pointer that is a - multiple of 4. - - Yield a value less than N if and only if arithmetic overflow occurs. */ - -#define FLEXSIZEOF(type, member, n) \ - ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \ - & ~ (FLEXALIGNOF (type) - 1)) diff --git a/xcompile/lib/fpending.c b/xcompile/lib/fpending.c deleted file mode 100644 index e57155e586e..00000000000 --- a/xcompile/lib/fpending.c +++ /dev/null @@ -1,63 +0,0 @@ -/* fpending.c -- return the number of pending output bytes on a stream - Copyright (C) 2000, 2004, 2006-2007, 2009-2023 Free Software Foundation, - Inc. - - This program is free software: you can 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 . */ - -/* Written by Jim Meyering. */ - -#include - -/* Specification. */ -#include "fpending.h" - -#include "stdio-impl.h" - -/* This file is not used on systems that already have the __fpending function, - namely glibc >= 2.2, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.34, - Android API >= 23. */ - -/* Return the number of pending (aka buffered, unflushed) - bytes on the stream, FP, that is open for writing. */ -size_t -__fpending (FILE *fp) -{ - /* Most systems provide FILE as a struct and the necessary bitmask in - , because they need it for implementing getc() and putc() as - fast macros. */ -#if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 - /* GNU libc, BeOS, Haiku, Linux libc5 */ - return fp->_IO_write_ptr - fp->_IO_write_base; -#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__ - /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */ - return fp_->_p - fp_->_bf._base; -#elif defined __EMX__ /* emx+gcc */ - return fp->_ptr - fp->_buffer; -#elif defined __minix /* Minix */ - return fp_->_ptr - fp_->_buf; -#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */ - return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0); -#elif defined __UCLIBC__ /* uClibc */ - return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0); -#elif defined __QNX__ /* QNX */ - return (fp->_Mode & 0x2000 /*_MWRITE*/ ? fp->_Next - fp->_Buf : 0); -#elif defined __MINT__ /* Atari FreeMiNT */ - return fp->__bufp - fp->__buffer; -#elif defined EPLAN9 /* Plan9 */ - return fp->wp - fp->buf; -#else -# error "Please port gnulib fpending.c to your platform!" - return 1; -#endif -} diff --git a/xcompile/lib/fpending.h b/xcompile/lib/fpending.h deleted file mode 100644 index 5e860db6810..00000000000 --- a/xcompile/lib/fpending.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Declare __fpending. - - Copyright (C) 2000, 2003, 2005-2006, 2009-2023 Free Software Foundation, - Inc. - - This program is free software: you can 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 . - - Written by Jim Meyering. */ - -#include -#include -#if HAVE_STDIO_EXT_H -# include -#endif - -#if !HAVE_DECL___FPENDING -size_t __fpending (FILE *) _GL_ATTRIBUTE_PURE; -#endif diff --git a/xcompile/lib/free.c b/xcompile/lib/free.c deleted file mode 100644 index 372a6b0fecf..00000000000 --- a/xcompile/lib/free.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Make free() preserve errno. - - Copyright (C) 2003, 2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Paul Eggert */ - -#include - -/* Specification. */ -#include - -/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */ -#if !HAVE_FREE_POSIX - -# include - -void -rpl_free (void *p) -# undef free -{ -# if defined __GNUC__ && !defined __clang__ - /* An invalid GCC optimization - - would optimize away the assignments in the code below, when link-time - optimization (LTO) is enabled. Make the code more complicated, so that - GCC does not grok how to optimize it. */ - int err[2]; - err[0] = errno; - err[1] = errno; - errno = 0; - free (p); - errno = err[errno == 0]; -# else - int err = errno; - free (p); - errno = err; -# endif -} - -#endif diff --git a/xcompile/lib/fstatat.c b/xcompile/lib/fstatat.c deleted file mode 100644 index 372965ef5f6..00000000000 --- a/xcompile/lib/fstatat.c +++ /dev/null @@ -1,148 +0,0 @@ -/* Work around an fstatat bug on Solaris 9. - - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert and Jim Meyering. */ - -/* If the user's config.h happens to include , let it include only - the system's here, so that orig_fstatat doesn't recurse to - rpl_fstatat. */ -#define __need_system_sys_stat_h -#include - -/* Get the original definition of fstatat. It might be defined as a macro. */ -#include -#include -#undef __need_system_sys_stat_h - -#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG -static int -orig_fstatat (int fd, char const *filename, struct stat *buf, int flags) -{ - return fstatat (fd, filename, buf, flags); -} -#endif - -#ifdef __osf__ -/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include - above. */ -# include "sys/stat.h" -#else -# include -#endif - -#include "stat-time.h" - -#include -#include -#include -#include - -#if HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG - -# ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK -# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0 -# endif - -static int -normal_fstatat (int fd, char const *file, struct stat *st, int flag) -{ - return stat_time_normalize (orig_fstatat (fd, file, st, flag), st); -} - -/* fstatat should always follow symbolic links that end in /, but on - Solaris 9 it doesn't if AT_SYMLINK_NOFOLLOW is specified. - Likewise, trailing slash on a non-directory should be an error. - These are the same problems that lstat.c and stat.c address, so - solve it in a similar way. - - AIX 7.1 fstatat (AT_FDCWD, ..., 0) always fails, which is a bug. - Work around this bug if FSTATAT_AT_FDCWD_0_BROKEN is nonzero. */ - -int -rpl_fstatat (int fd, char const *file, struct stat *st, int flag) -{ - int result = normal_fstatat (fd, file, st, flag); - size_t len; - - if (LSTAT_FOLLOWS_SLASHED_SYMLINK || result != 0) - return result; - len = strlen (file); - if (flag & AT_SYMLINK_NOFOLLOW) - { - /* Fix lstat behavior. */ - if (file[len - 1] != '/' || S_ISDIR (st->st_mode)) - return 0; - if (!S_ISLNK (st->st_mode)) - { - errno = ENOTDIR; - return -1; - } - result = normal_fstatat (fd, file, st, flag & ~AT_SYMLINK_NOFOLLOW); - } - /* Fix stat behavior. */ - if (result == 0 && !S_ISDIR (st->st_mode) && file[len - 1] == '/') - { - errno = ENOTDIR; - return -1; - } - return result; -} - -#else /* ! (HAVE_FSTATAT && HAVE_WORKING_FSTATAT_ZERO_FLAG) */ - -/* On mingw, the gnulib defines 'stat' as a function-like - macro; but using it in AT_FUNC_F2 causes compilation failure - because the preprocessor sees a use of a macro that requires two - arguments but is only given one. Hence, we need an inline - forwarder to get past the preprocessor. */ -static int -stat_func (char const *name, struct stat *st) -{ - return stat (name, st); -} - -/* Likewise, if there is no native 'lstat', then the gnulib - defined it as stat, which also needs adjustment. */ -# if !HAVE_LSTAT -# undef lstat -# define lstat stat_func -# endif - -/* Replacement for Solaris' function by the same name. - - First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). - Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - Otherwise, this function works just like Solaris' fstatat. */ - -# define AT_FUNC_NAME fstatat -# define AT_FUNC_F1 lstat -# define AT_FUNC_F2 stat_func -# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW -# define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag -# define AT_FUNC_POST_FILE_ARGS , st -# include "at-func.c" -# undef AT_FUNC_NAME -# undef AT_FUNC_F1 -# undef AT_FUNC_F2 -# undef AT_FUNC_USE_F1_COND -# undef AT_FUNC_POST_FILE_PARAM_DECLS -# undef AT_FUNC_POST_FILE_ARGS - -#endif /* !HAVE_FSTATAT */ diff --git a/xcompile/lib/fsusage.c b/xcompile/lib/fsusage.c deleted file mode 100644 index f6f4b1c35fd..00000000000 --- a/xcompile/lib/fsusage.c +++ /dev/null @@ -1,233 +0,0 @@ -/* fsusage.c -- return space usage of mounted file systems - - Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2023 Free Software - Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#include - -#include "fsusage.h" - -#include -#include - -#if STAT_STATVFS || STAT_STATVFS64 /* POSIX 1003.1-2001 (and later) with XSI */ -# include -#else -/* Don't include backward-compatibility files unless they're needed. - Eventually we'd like to remove all this cruft. */ -# include -# include -# include -#if HAVE_SYS_PARAM_H -# include -#endif -#if HAVE_SYS_MOUNT_H -# include -#endif -#if HAVE_SYS_VFS_H -# include -#endif -# if HAVE_SYS_FS_S5PARAM_H /* Fujitsu UXP/V */ -# include -# endif -# if HAVE_SYS_STATFS_H -# include -# endif -#endif - -/* Many space usage primitives use all 1 bits to denote a value that is - not applicable or unknown. Propagate this information by returning - a uintmax_t value that is all 1 bits if X is all 1 bits, even if X - is unsigned and narrower than uintmax_t. */ -#define PROPAGATE_ALL_ONES(x) \ - ((sizeof (x) < sizeof (uintmax_t) \ - && (~ (x) == (sizeof (x) < sizeof (int) \ - ? - (1 << (sizeof (x) * CHAR_BIT)) \ - : 0))) \ - ? UINTMAX_MAX : (uintmax_t) (x)) - -/* Extract the top bit of X as an uintmax_t value. */ -#define EXTRACT_TOP_BIT(x) ((x) \ - & ((uintmax_t) 1 << (sizeof (x) * CHAR_BIT - 1))) - -/* If a value is negative, many space usage primitives store it into an - integer variable by assignment, even if the variable's type is unsigned. - So, if a space usage variable X's top bit is set, convert X to the - uintmax_t value V such that (- (uintmax_t) V) is the negative of - the original value. If X's top bit is clear, just yield X. - Use PROPAGATE_TOP_BIT if the original value might be negative; - otherwise, use PROPAGATE_ALL_ONES. */ -#define PROPAGATE_TOP_BIT(x) ((x) | ~ (EXTRACT_TOP_BIT (x) - 1)) - -#ifdef STAT_STATVFS -/* Return true if statvfs works. This is false for statvfs on systems - with GNU libc on Linux kernels before 2.6.36, which stats all - preceding entries in /proc/mounts; that makes df hang if even one - of the corresponding file systems is hard-mounted but not available. */ -# if ! (__linux__ && (__GLIBC__ || __UCLIBC__)) -/* The FRSIZE fallback is not required in this case. */ -# undef STAT_STATFS2_FRSIZE -static int statvfs_works (void) { return 1; } -# else -# include /* for strverscmp */ -# include -# include -# define STAT_STATFS2_BSIZE 1 - -static int -statvfs_works (void) -{ - static int statvfs_works_cache = -1; - struct utsname name; - if (statvfs_works_cache < 0) - statvfs_works_cache = (uname (&name) == 0 - && 0 <= strverscmp (name.release, "2.6.36")); - return statvfs_works_cache; -} -# endif -#endif - - -/* Fill in the fields of FSP with information about space usage for - the file system on which FILE resides. - DISK is the device on which FILE is mounted, for space-getting - methods that need to know it. - Return 0 if successful, -1 if not. When returning -1, ensure that - ERRNO is either a system error value, or zero if DISK is NULL - on a system that requires a non-NULL value. */ -int -get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) -{ -#ifdef STAT_STATVFS /* POSIX, except pre-2.6.36 glibc/Linux */ - - if (statvfs_works ()) - { - struct statvfs vfsd; - - if (statvfs (file, &vfsd) < 0) - return -1; - - /* f_frsize isn't guaranteed to be supported. */ - fsp->fsu_blocksize = (vfsd.f_frsize - ? PROPAGATE_ALL_ONES (vfsd.f_frsize) - : PROPAGATE_ALL_ONES (vfsd.f_bsize)); - - fsp->fsu_blocks = PROPAGATE_ALL_ONES (vfsd.f_blocks); - fsp->fsu_bfree = PROPAGATE_ALL_ONES (vfsd.f_bfree); - fsp->fsu_bavail = PROPAGATE_TOP_BIT (vfsd.f_bavail); - fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (vfsd.f_bavail) != 0; - fsp->fsu_files = PROPAGATE_ALL_ONES (vfsd.f_files); - fsp->fsu_ffree = PROPAGATE_ALL_ONES (vfsd.f_ffree); - return 0; - } - -#endif - -#if defined STAT_STATVFS64 /* AIX */ - - struct statvfs64 fsd; - - if (statvfs64 (file, &fsd) < 0) - return -1; - - /* f_frsize isn't guaranteed to be supported. */ - fsp->fsu_blocksize = (fsd.f_frsize - ? PROPAGATE_ALL_ONES (fsd.f_frsize) - : PROPAGATE_ALL_ONES (fsd.f_bsize)); - -#elif defined STAT_STATFS3_OSF1 /* OSF/1 */ - - struct statfs fsd; - - if (statfs (file, &fsd, sizeof (struct statfs)) != 0) - return -1; - - fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); - -#elif defined STAT_STATFS2_FRSIZE /* 2.6 < glibc/Linux < 2.6.36 */ - - struct statfs fsd; - - if (statfs (file, &fsd) < 0) - return -1; - - fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_frsize); - -#elif defined STAT_STATFS2_BSIZE /* glibc/Linux < 2.6, 4.3BSD, SunOS 4, \ - Mac OS X < 10.4, FreeBSD < 5.0, \ - NetBSD < 3.0, OpenBSD < 4.4 */ - - struct statfs fsd; - - if (statfs (file, &fsd) < 0) - return -1; - - fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_bsize); - -# ifdef STATFS_TRUNCATES_BLOCK_COUNTS - - /* In SunOS 4.1.2, 4.1.3, and 4.1.3_U1, the block counts in the - struct statfs are truncated to 2GB. These conditions detect that - truncation, presumably without botching the 4.1.1 case, in which - the values are not truncated. The correct counts are stored in - undocumented spare fields. */ - if (fsd.f_blocks == 0x7fffffff / fsd.f_bsize && fsd.f_spare[0] > 0) - { - fsd.f_blocks = fsd.f_spare[0]; - fsd.f_bfree = fsd.f_spare[1]; - fsd.f_bavail = fsd.f_spare[2]; - } -# endif /* STATFS_TRUNCATES_BLOCK_COUNTS */ - -#elif defined STAT_STATFS2_FSIZE /* 4.4BSD and older NetBSD */ - - struct statfs fsd; - - if (statfs (file, &fsd) < 0) - return -1; - - fsp->fsu_blocksize = PROPAGATE_ALL_ONES (fsd.f_fsize); - -#elif defined STAT_STATFS4 /* SVR3, old Irix */ - - struct statfs fsd; - - if (statfs (file, &fsd, sizeof fsd, 0) < 0) - return -1; - - /* Empirically, the block counts on most SVR3 and SVR3-derived - systems seem to always be in terms of 512-byte blocks, - no matter what value f_bsize has. */ - fsp->fsu_blocksize = 512; - -#endif - -#if (defined STAT_STATVFS64 || defined STAT_STATFS3_OSF1 \ - || defined STAT_STATFS2_FRSIZE || defined STAT_STATFS2_BSIZE \ - || defined STAT_STATFS2_FSIZE || defined STAT_STATFS4) - - fsp->fsu_blocks = PROPAGATE_ALL_ONES (fsd.f_blocks); - fsp->fsu_bfree = PROPAGATE_ALL_ONES (fsd.f_bfree); - fsp->fsu_bavail = PROPAGATE_TOP_BIT (fsd.f_bavail); - fsp->fsu_bavail_top_bit_set = EXTRACT_TOP_BIT (fsd.f_bavail) != 0; - fsp->fsu_files = PROPAGATE_ALL_ONES (fsd.f_files); - fsp->fsu_ffree = PROPAGATE_ALL_ONES (fsd.f_ffree); - -#endif - - (void) disk; /* avoid argument-unused warning */ - return 0; -} diff --git a/xcompile/lib/fsusage.h b/xcompile/lib/fsusage.h deleted file mode 100644 index 9630b04e001..00000000000 --- a/xcompile/lib/fsusage.h +++ /dev/null @@ -1,39 +0,0 @@ -/* fsusage.h -- declarations for file system space usage info - - Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2023 Free Software - Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Space usage statistics for a file system. Blocks are 512-byte. */ - -#if !defined FSUSAGE_H_ -# define FSUSAGE_H_ - -# include - -struct fs_usage -{ - uintmax_t fsu_blocksize; /* Size of a block. */ - uintmax_t fsu_blocks; /* Total blocks. */ - uintmax_t fsu_bfree; /* Free blocks available to superuser. */ - uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ - bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ - uintmax_t fsu_files; /* Total file nodes. */ - uintmax_t fsu_ffree; /* Free file nodes. */ -}; - -int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp); - -#endif diff --git a/xcompile/lib/fsync.c b/xcompile/lib/fsync.c deleted file mode 100644 index 51314662872..00000000000 --- a/xcompile/lib/fsync.c +++ /dev/null @@ -1,87 +0,0 @@ -/* Emulate fsync on platforms that lack it, primarily Windows and - cross-compilers like MinGW. - - This is derived from sqlite3 sources. - https://www.sqlite.org/src/finfo?name=src/os_win.c - https://www.sqlite.org/copyright.html - - Written by Richard W.M. Jones - - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include -#include - -#if defined _WIN32 && ! defined __CYGWIN__ - -/* FlushFileBuffers */ -# define WIN32_LEAN_AND_MEAN -# include - -# include - -/* Get _get_osfhandle. */ -# if GNULIB_MSVC_NOTHROW -# include "msvc-nothrow.h" -# else -# include -# endif - -int -fsync (int fd) -{ - HANDLE h = (HANDLE) _get_osfhandle (fd); - DWORD err; - - if (h == INVALID_HANDLE_VALUE) - { - errno = EBADF; - return -1; - } - - if (!FlushFileBuffers (h)) - { - /* Translate some Windows errors into rough approximations of Unix - * errors. MSDN is useless as usual - in this case it doesn't - * document the full range of errors. - */ - err = GetLastError (); - switch (err) - { - case ERROR_ACCESS_DENIED: - /* For a read-only handle, fsync should succeed, even though we have - no way to sync the access-time changes. */ - return 0; - - /* eg. Trying to fsync a tty. */ - case ERROR_INVALID_HANDLE: - errno = EINVAL; - break; - - default: - errno = EIO; - } - return -1; - } - - return 0; -} - -#else /* !Windows */ - -# error "This platform lacks fsync function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib." - -#endif /* !Windows */ diff --git a/xcompile/lib/ftoastr.c b/xcompile/lib/ftoastr.c deleted file mode 100644 index 8740a4d86c8..00000000000 --- a/xcompile/lib/ftoastr.c +++ /dev/null @@ -1,151 +0,0 @@ -/* floating point to accurate string - - Copyright (C) 2010-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -/* This code can misbehave on some buggy or older platforms, when - operating on arguments on floating types other than 'double', or - when given unusual combinations of options. Gnulib's - snprintf-posix module works around many of these problems. - - This code relies on sprintf, strtod, etc. operating accurately; - otherwise, the resulting strings could be inaccurate or too long. */ - -#include - -#include "ftoastr.h" - -#include -#include -#include - -#ifdef C_LOCALE -# include "c-snprintf.h" -# include "c-strtod.h" -# define PREFIX(name) c_ ## name -#else -# define PREFIX(name) name -#endif - -#if LENGTH == 3 -# define FLOAT long double -# define FLOAT_DIG LDBL_DIG -# define FLOAT_MIN LDBL_MIN -# define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND -# define FTOASTR PREFIX (ldtoastr) -# define PROMOTED_FLOAT long double -# define STRTOF PREFIX (strtold) -#elif LENGTH == 2 -# define FLOAT double -# define FLOAT_DIG DBL_DIG -# define FLOAT_MIN DBL_MIN -# define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND -# define FTOASTR PREFIX (dtoastr) -# define PROMOTED_FLOAT double -#else -# define LENGTH 1 -# define FLOAT float -# define FLOAT_DIG FLT_DIG -# define FLOAT_MIN FLT_MIN -# define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND -# define FTOASTR PREFIX (ftoastr) -# define PROMOTED_FLOAT double -# if HAVE_STRTOF -# define STRTOF strtof -# endif -#endif - -/* On pre-C99 hosts, approximate strtof with strtod. This - may generate one or two extra digits, but that's better than not - working at all. */ -#ifndef STRTOF -# define STRTOF PREFIX (strtod) -#endif - -/* On hosts where it's not known that snprintf works, use sprintf to - implement the subset needed here. Typically BUFSIZE is big enough - and there's little or no performance hit. */ -#ifdef C_LOCALE -# undef snprintf -# define snprintf c_snprintf -#elif ! GNULIB_SNPRINTF -# undef snprintf -# define snprintf ftoastr_snprintf -static int -ftoastr_snprintf (char *buf, size_t bufsize, char const *format, - int width, int prec, FLOAT x) -{ - PROMOTED_FLOAT promoted_x = x; - char width_0_buffer[LENGTH == 1 ? FLT_BUFSIZE_BOUND - : LENGTH == 2 ? DBL_BUFSIZE_BOUND - : LDBL_BUFSIZE_BOUND]; - int n = width; - if (bufsize < sizeof width_0_buffer) - { - n = sprintf (width_0_buffer, format, 0, prec, promoted_x); - if (n < 0) - return n; - if (n < width) - n = width; - } - if (n < bufsize) - n = sprintf (buf, format, width, prec, promoted_x); - return n; -} -#endif - -int -FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x) -{ - /* The following method is simple but slow. - For ideas about speeding things up, please see: - - Andrysco M, Jhala R, Lerner S. Printing floating-point numbers: - a faster, always correct method. ACM SIGPLAN notices - POPL '16. - 2016;51(1):555-67 ; draft at - . */ - - PROMOTED_FLOAT promoted_x = x; - char format[sizeof "%-+ 0*.*Lg"]; - FLOAT abs_x = x < 0 ? -x : x; - int prec; - - char *p = format; - *p++ = '%'; - - /* Support flags that generate output parsable by strtof. */ - *p = '-'; p += (flags & FTOASTR_LEFT_JUSTIFY ) != 0; - *p = '+'; p += (flags & FTOASTR_ALWAYS_SIGNED ) != 0; - *p = ' '; p += (flags & FTOASTR_SPACE_POSITIVE) != 0; - *p = '0'; p += (flags & FTOASTR_ZERO_PAD ) != 0; - - *p++ = '*'; - *p++ = '.'; - *p++ = '*'; - *p = 'L'; p += 2 < LENGTH; - *p++ = flags & FTOASTR_UPPER_E ? 'G' : 'g'; - *p = '\0'; - - for (prec = abs_x < FLOAT_MIN ? 1 : FLOAT_DIG; ; prec++) - { - int n = snprintf (buf, bufsize, format, width, prec, promoted_x); - if (n < 0 - || FLOAT_PREC_BOUND <= prec - || (n < bufsize && STRTOF (buf, NULL) == x)) - return n; - } -} diff --git a/xcompile/lib/ftoastr.h b/xcompile/lib/ftoastr.h deleted file mode 100644 index 1ce1b7a4bc6..00000000000 --- a/xcompile/lib/ftoastr.h +++ /dev/null @@ -1,152 +0,0 @@ -/* floating point to accurate string - - Copyright (C) 2010-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -#ifndef _GL_FTOASTR_H -#define _GL_FTOASTR_H - -#include "intprops.h" -#include -#include - -/* Store into BUF (of size BUFSIZE) an accurate minimal-precision - string representation of a floating point number. FLAGS affect the - formatting of the number. Pad the output string with spaces as - necessary to width WIDTH bytes, in the style of printf. WIDTH must - be nonnegative. X is the floating-point number to be converted. - - Return the number of bytes stored into BUF, not counting the - terminating null. However, do not overrun BUF: if BUF is too - small, return a fairly tight (but not necessarily exact) upper - bound on the value that would have been returned if BUF had been - big enough. If SIZE is zero, BUF may be a null pointer. On error - (e.g., returned value would exceed INT_MAX), return -1 and set - errno. - - Example: - - char buf[DBL_BUFSIZE_BOUND]; - int r = dtoastr (buf, sizeof buf, 0, 0, 0.1); - - In the C locale, this sets R to 3 and stores "0.1" into BUF. */ - -int ftoastr (char *buf, size_t bufsize, int flags, int width, float x); -int dtoastr (char *buf, size_t bufsize, int flags, int width, double x); -int ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); - -/* The last two functions except that the formatting takes place in - the C locale. */ -int c_dtoastr (char *buf, size_t bufsize, int flags, int width, double x); -int c_ldtoastr (char *buf, size_t bufsize, int flags, int width, long double x); - - -/* Flag values for ftoastr etc. These can be ORed together. */ -enum - { - /* Left justify within the width; the default is right justification. */ - FTOASTR_LEFT_JUSTIFY = 1, - - /* Output "+" before positive numbers; the default outputs nothing. */ - FTOASTR_ALWAYS_SIGNED = 2, - - /* Output " " before positive numbers; ignored if - FTOASTR_ALWAYS_SIGNED is also given. */ - FTOASTR_SPACE_POSITIVE = 4, - - /* Pad with zeros instead of spaces; ignored if FTOASTR_LEFT_JUSTIFY - is also given. */ - FTOASTR_ZERO_PAD = 8, - - /* Use 'E' instead of 'e' before the exponent. */ - FTOASTR_UPPER_E = 16 - }; - - -/* _GL_FLT_PREC_BOUND is an upper bound on the precision needed to - represent a float value without losing information. Likewise for - _GL_DBL_PREC_BOUND and double, and _GL_LDBL_PREC_BOUND and long double. - These are macros, not enums, to work around a bug in IBM xlc 12.1. */ - -#if FLT_RADIX == 10 /* decimal floating point */ -# define _GL_FLT_PREC_BOUND FLT_MANT_DIG -# define _GL_DBL_PREC_BOUND DBL_MANT_DIG -# define _GL_LDBL_PREC_BOUND LDBL_MANT_DIG -#else - -/* An upper bound on the number of bits needed to represent a single - digit in a floating-point fraction. */ -# if FLT_RADIX == 2 /* IEEE 754 floating point, VAX floating point, etc. */ -# define _GL_FLOAT_DIG_BITS_BOUND 1 -# elif FLT_RADIX <= 16 /* IBM hex floating point has FLT_RADIX == 16. */ -# define _GL_FLOAT_DIG_BITS_BOUND 4 -# else /* no machine is this bad, but let's be complete */ -# define _GL_FLOAT_DIG_BITS_BOUND ((int) TYPE_WIDTH (int) - 1) -# endif - -/* An upper bound on the number of decimal digits needed to represent - a floating point number accurately, assuming a fraction contains - DIG digits. For why the "+ 1" is needed, see "Binary to Decimal - Conversion" in David Goldberg's paper "What Every Computer - Scientist Should Know About Floating-Point Arithmetic" - . */ -# define _GL_FLOAT_PREC_BOUND(dig) \ - (INT_BITS_STRLEN_BOUND ((dig) * _GL_FLOAT_DIG_BITS_BOUND) + 1) - -# define _GL_FLT_PREC_BOUND _GL_FLOAT_PREC_BOUND ( FLT_MANT_DIG) -# define _GL_DBL_PREC_BOUND _GL_FLOAT_PREC_BOUND ( DBL_MANT_DIG) -# define _GL_LDBL_PREC_BOUND _GL_FLOAT_PREC_BOUND (LDBL_MANT_DIG) -#endif - - -/* Bound on the number of bytes printed for an exponent in the range - MIN..MAX, where MIN < 0 < MAX; printf always prints a sign and at - least 2 digits. Although the maximum known exponent is 4932 for - IEEE 754 binary128, support tight bounds for exponents up to a - million, just in case. */ -#define _GL_FLOAT_EXPONENT_STRLEN_BOUND(min, max) \ - ( -100 < (min) && (max) < 100 ? 3 \ - : -1000 < (min) && (max) < 1000 ? 4 \ - : -10000 < (min) && (max) < 10000 ? 5 \ - : -100000 < (min) && (max) < 100000 ? 6 \ - : -1000000 < (min) && (max) < 1000000 ? 7 \ - : INT_STRLEN_BOUND (int) /* not a tight bound */) - -/* A reasonably tight bound on the length of a type-T floating value - formatted with ftoastr etc. Room is needed for sign, fraction - digits, decimal point, "e", and exponent. POINTLEN should be a - reasonably tight bound on the string length of the decimal - point. */ -#define _GL_FLOAT_STRLEN_BOUND_L(t, pointlen) \ - (1 + _GL_##t##_PREC_BOUND + pointlen + 1 \ - + _GL_FLOAT_EXPONENT_STRLEN_BOUND (t##_MIN_10_EXP, t##_MAX_10_EXP)) -#define FLT_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L ( FLT, pointlen) -#define DBL_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L ( DBL, pointlen) -#define LDBL_STRLEN_BOUND_L(pointlen) _GL_FLOAT_STRLEN_BOUND_L (LDBL, pointlen) - -/* Looser bounds that are locale-independent and are integral constant - expressions. */ -#define FLT_STRLEN_BOUND FLT_STRLEN_BOUND_L (MB_LEN_MAX) -#define DBL_STRLEN_BOUND DBL_STRLEN_BOUND_L (MB_LEN_MAX) -#define LDBL_STRLEN_BOUND LDBL_STRLEN_BOUND_L (MB_LEN_MAX) - -/* Looser, locale-independent bounds that include the trailing null byte. */ -#define FLT_BUFSIZE_BOUND ( FLT_STRLEN_BOUND + 1) -#define DBL_BUFSIZE_BOUND ( DBL_STRLEN_BOUND + 1) -#define LDBL_BUFSIZE_BOUND (LDBL_STRLEN_BOUND + 1) - -#endif /* _GL_FTOASTR_H */ diff --git a/xcompile/lib/futimens.c b/xcompile/lib/futimens.c deleted file mode 100644 index 5bb30493c7e..00000000000 --- a/xcompile/lib/futimens.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Set the access and modification time of an open fd. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* written by Eric Blake */ - -#include - -#include - -#include "utimens.h" - -/* Set the access and modification timestamps of FD to be - TIMESPEC[0] and TIMESPEC[1], respectively. - Fail with ENOSYS on systems without futimes (or equivalent). - If TIMESPEC is null, set the timestamps to the current time. - Return 0 on success, -1 (setting errno) on failure. */ -int -futimens (int fd, struct timespec const times[2]) -{ - /* fdutimens also works around bugs in native futimens, when running - with glibc compiled against newer headers but on a Linux kernel - older than 2.6.32. */ - return fdutimens (fd, NULL, times); -} diff --git a/xcompile/lib/get-permissions.c b/xcompile/lib/get-permissions.c deleted file mode 100644 index 545ad23195b..00000000000 --- a/xcompile/lib/get-permissions.c +++ /dev/null @@ -1,291 +0,0 @@ -/* Get permissions of a file. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -#include - -#include -#include "acl.h" - -#include "acl-internal.h" - -/* Read the permissions of a file into CTX. If DESC is a valid file descriptor, - use file descriptor operations, else use filename based operations on NAME. - MODE is the file mode obtained from a previous stat call. - Return 0 if successful. Return -1 and set errno upon failure. */ - -int -get_permissions (const char *name, int desc, mode_t mode, - struct permission_context *ctx) -{ - memset (ctx, 0, sizeof *ctx); - ctx->mode = mode; - -#if USE_ACL && HAVE_ACL_GET_FILE - /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ - /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ -# if !HAVE_ACL_TYPE_EXTENDED - /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ - - if (HAVE_ACL_GET_FD && desc != -1) - ctx->acl = acl_get_fd (desc); - else - ctx->acl = acl_get_file (name, ACL_TYPE_ACCESS); - if (ctx->acl == NULL) - return acl_errno_valid (errno) ? -1 : 0; - - /* With POSIX ACLs, a file cannot have "no" acl; a file without - extended permissions has a "minimal" acl which is equivalent to the - file mode. */ - - if (S_ISDIR (mode)) - { - ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT); - if (ctx->default_acl == NULL) - return -1; - } - -# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */ - - /* TODO (see set_permissions). */ - -# endif - -# else /* HAVE_ACL_TYPE_EXTENDED */ - /* Mac OS X */ - - /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) - always return NULL / EINVAL. You have to use - acl_get_file (name, ACL_TYPE_EXTENDED) - or acl_get_fd (open (name, ...)) - to retrieve an ACL. - On the other hand, - acl_set_file (name, ACL_TYPE_ACCESS, acl) - and acl_set_file (name, ACL_TYPE_DEFAULT, acl) - have the same effect as - acl_set_file (name, ACL_TYPE_EXTENDED, acl): - Each of these calls sets the file's ACL. */ - - if (HAVE_ACL_GET_FD && desc != -1) - ctx->acl = acl_get_fd (desc); - else - ctx->acl = acl_get_file (name, ACL_TYPE_EXTENDED); - if (ctx->acl == NULL) - return acl_errno_valid (errno) ? -1 : 0; - -# endif - -#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ - - /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions - of Unixware. The acl() call returns the access and default ACL both - at once. */ -# ifdef ACE_GETACL - /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 - file systems (whereas the other ones are used in UFS file systems). - There is an API - pathconf (name, _PC_ACL_ENABLED) - fpathconf (desc, _PC_ACL_ENABLED) - that allows us to determine which of the two kinds of ACLs is supported - for the given file. But some file systems may implement this call - incorrectly, so better not use it. - When fetching the source ACL, we simply fetch both ACL types. - When setting the destination ACL, we try either ACL types, assuming - that the kernel will translate the ACL from one form to the other. - (See in - the description of ENOTSUP.) */ - for (;;) - { - int ret; - - if (desc != -1) - ret = facl (desc, ACE_GETACLCNT, 0, NULL); - else - ret = acl (name, ACE_GETACLCNT, 0, NULL); - if (ret < 0) - { - if (errno == ENOSYS || errno == EINVAL) - ret = 0; - else - return -1; - } - ctx->ace_count = ret; - - if (ctx->ace_count == 0) - break; - - ctx->ace_entries = (ace_t *) malloc (ctx->ace_count * sizeof (ace_t)); - if (ctx->ace_entries == NULL) - { - errno = ENOMEM; - return -1; - } - - if (desc != -1) - ret = facl (desc, ACE_GETACL, ctx->ace_count, ctx->ace_entries); - else - ret = acl (name, ACE_GETACL, ctx->ace_count, ctx->ace_entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == EINVAL) - { - free (ctx->ace_entries); - ctx->ace_entries = NULL; - ctx->ace_count = 0; - break; - } - else - return -1; - } - if (ret <= ctx->ace_count) - { - ctx->ace_count = ret; - break; - } - /* Huh? The number of ACL entries has increased since the last call. - Repeat. */ - free (ctx->ace_entries); - ctx->ace_entries = NULL; - } -# endif - - for (;;) - { - int ret; - - if (desc != -1) - ret = facl (desc, GETACLCNT, 0, NULL); - else - ret = acl (name, GETACLCNT, 0, NULL); - if (ret < 0) - { - if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) - ret = 0; - else - return -1; - } - ctx->count = ret; - - if (ctx->count == 0) - break; - - ctx->entries = (aclent_t *) malloc (ctx->count * sizeof (aclent_t)); - if (ctx->entries == NULL) - { - errno = ENOMEM; - return -1; - } - - if (desc != -1) - ret = facl (desc, GETACL, ctx->count, ctx->entries); - else - ret = acl (name, GETACL, ctx->count, ctx->entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) - { - free (ctx->entries); - ctx->entries = NULL; - ctx->count = 0; - break; - } - else - return -1; - } - if (ret <= ctx->count) - { - ctx->count = ret; - break; - } - /* Huh? The number of ACL entries has increased since the last call. - Repeat. */ - free (ctx->entries); - ctx->entries = NULL; - } - -#elif USE_ACL && HAVE_GETACL /* HP-UX */ - - { - int ret; - - if (desc != -1) - ret = fgetacl (desc, NACLENTRIES, ctx->entries); - else - ret = getacl (name, NACLENTRIES, ctx->entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) - ret = 0; - else - return -1; - } - else if (ret > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - ctx->count = ret; - -# if HAVE_ACLV_H - ret = acl ((char *) name, ACL_GET, NACLVENTRIES, ctx->aclv_entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - ret = 0; - else - return -2; - } - else if (ret > NACLVENTRIES) - /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - ctx->aclv_count = ret; -# endif - } - -#elif USE_ACL && HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ - - /* TODO (see set_permissions). */ - -#elif USE_ACL && HAVE_STATACL /* older AIX */ - - { - int ret; - if (desc != -1) - ret = fstatacl (desc, STX_NORMAL, &ctx->u.a, sizeof ctx->u); - else - ret = statacl ((char *) name, STX_NORMAL, &ctx->u.a, sizeof ctx->u); - if (ret == 0) - ctx->have_u = true; - } - -#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ - - { - int ret = acl ((char *) name, ACL_GET, NACLENTRIES, ctx->entries); - if (ret < 0) - return -1; - else if (ret > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - ctx->count = ret; - } - -#endif - - return 0; - -} diff --git a/xcompile/lib/getdelim.c b/xcompile/lib/getdelim.c deleted file mode 100644 index 79ec3dd12a3..00000000000 --- a/xcompile/lib/getdelim.c +++ /dev/null @@ -1,147 +0,0 @@ -/* getdelim.c --- Implementation of replacement getdelim function. - Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Ported from glibc by Simon Josefsson. */ - -/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc - optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ -#define _GL_ARG_NONNULL(params) - -#include - -#include - -#include -#include -#include -#include - -#ifndef SSIZE_MAX -# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -# define getc_maybe_unlocked(fp) getc(fp) -#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED -# undef flockfile -# undef funlockfile -# define flockfile(x) ((void) 0) -# define funlockfile(x) ((void) 0) -# define getc_maybe_unlocked(fp) getc(fp) -#else -# define getc_maybe_unlocked(fp) getc_unlocked(fp) -#endif - -static void -alloc_failed (void) -{ -#if defined _WIN32 && ! defined __CYGWIN__ - /* Avoid errno problem without using the realloc module; see: - https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */ - errno = ENOMEM; -#endif -} - -/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and - NUL-terminate it). *LINEPTR is a pointer returned from malloc (or - NULL), pointing to *N characters of space. It is realloc'ed as - necessary. Returns the number of characters read (not including - the null terminator), or -1 on error or EOF. */ - -ssize_t -getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) -{ - ssize_t result; - size_t cur_len = 0; - - if (lineptr == NULL || n == NULL || fp == NULL) - { - errno = EINVAL; - return -1; - } - - flockfile (fp); - - if (*lineptr == NULL || *n == 0) - { - char *new_lineptr; - *n = 120; - new_lineptr = (char *) realloc (*lineptr, *n); - if (new_lineptr == NULL) - { - alloc_failed (); - result = -1; - goto unlock_return; - } - *lineptr = new_lineptr; - } - - for (;;) - { - int i; - - i = getc_maybe_unlocked (fp); - if (i == EOF) - { - result = -1; - break; - } - - /* Make enough space for len+1 (for final NUL) bytes. */ - if (cur_len + 1 >= *n) - { - size_t needed_max = - SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; - size_t needed = 2 * *n + 1; /* Be generous. */ - char *new_lineptr; - - if (needed_max < needed) - needed = needed_max; - if (cur_len + 1 >= needed) - { - result = -1; - errno = EOVERFLOW; - goto unlock_return; - } - - new_lineptr = (char *) realloc (*lineptr, needed); - if (new_lineptr == NULL) - { - alloc_failed (); - result = -1; - goto unlock_return; - } - - *lineptr = new_lineptr; - *n = needed; - } - - (*lineptr)[cur_len] = i; - cur_len++; - - if (i == delimiter) - break; - } - (*lineptr)[cur_len] = '\0'; - result = cur_len ? cur_len : result; - - unlock_return: - funlockfile (fp); /* doesn't set errno */ - - return result; -} diff --git a/xcompile/lib/getdtablesize.c b/xcompile/lib/getdtablesize.c deleted file mode 100644 index ac2d1753a6b..00000000000 --- a/xcompile/lib/getdtablesize.c +++ /dev/null @@ -1,124 +0,0 @@ -/* getdtablesize() function: Return maximum possible file descriptor value + 1. - Copyright (C) 2008-2023 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#if defined _WIN32 && ! defined __CYGWIN__ - -# include - -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -# include "msvc-inval.h" -# endif - -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -static int -_setmaxstdio_nothrow (int newmax) -{ - int result; - - TRY_MSVC_INVAL - { - result = _setmaxstdio (newmax); - } - CATCH_MSVC_INVAL - { - result = -1; - } - DONE_MSVC_INVAL; - - return result; -} -# else -# define _setmaxstdio_nothrow _setmaxstdio -# endif - -/* Cache for the previous getdtablesize () result. Safe to cache because - Windows also lacks setrlimit. */ -static int dtablesize; - -int -getdtablesize (void) -{ - if (dtablesize == 0) - { - /* We are looking for the number N such that the valid file descriptors - are 0..N-1. It can be obtained through a loop as follows: - { - int fd; - for (fd = 3; fd < 65536; fd++) - if (dup2 (0, fd) == -1) - break; - return fd; - } - On Windows XP, the result is 2048. - The drawback of this loop is that it allocates memory for a libc - internal array that is never freed. - - The number N can also be obtained as the upper bound for - _getmaxstdio (). _getmaxstdio () returns the maximum number of open - FILE objects. The sanity check in _setmaxstdio reveals the maximum - number of file descriptors. This too allocates memory, but it is - freed when we call _setmaxstdio with the original value. */ - int orig_max_stdio = _getmaxstdio (); - unsigned int bound; - for (bound = 0x10000; _setmaxstdio_nothrow (bound) < 0; bound = bound / 2) - ; - _setmaxstdio_nothrow (orig_max_stdio); - dtablesize = bound; - } - return dtablesize; -} - -#else - -# include -# include - -# ifndef RLIM_SAVED_CUR -# define RLIM_SAVED_CUR RLIM_INFINITY -# endif -# ifndef RLIM_SAVED_MAX -# define RLIM_SAVED_MAX RLIM_INFINITY -# endif - -# ifdef __CYGWIN__ - /* Cygwin 1.7.25 auto-increases the RLIMIT_NOFILE soft limit until it - hits the compile-time constant hard limit of 3200. We might as - well just report the hard limit. */ -# define rlim_cur rlim_max -# endif - -int -getdtablesize (void) -{ - struct rlimit lim; - - if (getrlimit (RLIMIT_NOFILE, &lim) == 0 - && 0 <= lim.rlim_cur && lim.rlim_cur <= INT_MAX - && lim.rlim_cur != RLIM_INFINITY - && lim.rlim_cur != RLIM_SAVED_CUR - && lim.rlim_cur != RLIM_SAVED_MAX) - return lim.rlim_cur; - - return INT_MAX; -} - -#endif diff --git a/xcompile/lib/getgroups.c b/xcompile/lib/getgroups.c deleted file mode 100644 index 93829d3b15e..00000000000 --- a/xcompile/lib/getgroups.c +++ /dev/null @@ -1,125 +0,0 @@ -/* provide consistent interface to getgroups for systems that don't allow N==0 - - Copyright (C) 1996, 1999, 2003, 2006-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering */ - -#include - -#include - -#include -#include -#include - -#if !HAVE_GETGROUPS - -/* Provide a stub that fails with ENOSYS, since there is no group - information available on mingw. */ -int -getgroups (_GL_UNUSED int n, _GL_UNUSED GETGROUPS_T *groups) -{ - errno = ENOSYS; - return -1; -} - -#else /* HAVE_GETGROUPS */ - -# undef getgroups -# ifndef GETGROUPS_ZERO_BUG -# define GETGROUPS_ZERO_BUG 0 -# endif - -/* On OS X 10.6 and later, use the usual getgroups, not the one - supplied when _DARWIN_C_SOURCE is defined. _DARWIN_C_SOURCE is - normally defined, since it means "conform to POSIX, but add - non-POSIX extensions even if that violates the POSIX namespace - rules", which is what we normally want. But with getgroups there - is an inconsistency, and _DARWIN_C_SOURCE means "change getgroups() - so that it no longer works right". The BUGS section of compat(5) - says that the behavior is dubious if you compile different sections - of a program with different _DARWIN_C_SOURCE settings, so fix only - the offending symbol. */ -# ifdef __APPLE__ -int posix_getgroups (int, gid_t []) __asm ("_getgroups"); -# define getgroups posix_getgroups -# endif - -/* On at least NeXTstep 3.2, getgroups (0, NULL) always fails. - On other systems, it returns the number of supplemental - groups for the process. This function handles that special case - and lets the system-provided function handle all others. However, - it can fail with ENOMEM if memory is tight. It is unspecified - whether the effective group id is included in the list. */ - -int -rpl_getgroups (int n, gid_t *group) -{ - int n_groups; - GETGROUPS_T *gbuf; - - if (n < 0) - { - errno = EINVAL; - return -1; - } - - if (n != 0 || !GETGROUPS_ZERO_BUG) - { - int result; - if (sizeof *group == sizeof *gbuf) - return getgroups (n, (GETGROUPS_T *) group); - - if (SIZE_MAX / sizeof *gbuf <= n) - { - errno = ENOMEM; - return -1; - } - gbuf = malloc (n * sizeof *gbuf); - if (!gbuf) - return -1; - result = getgroups (n, gbuf); - if (0 <= result) - { - n = result; - while (n--) - group[n] = gbuf[n]; - } - free (gbuf); - return result; - } - - n = 20; - while (1) - { - /* No need to worry about address arithmetic overflow here, - since the ancient systems that we're running on have low - limits on the number of secondary groups. */ - gbuf = malloc (n * sizeof *gbuf); - if (!gbuf) - return -1; - n_groups = getgroups (n, gbuf); - if (n_groups == -1 ? errno != EINVAL : n_groups < n) - break; - free (gbuf); - n *= 2; - } - - free (gbuf); - return n_groups; -} - -#endif /* HAVE_GETGROUPS */ diff --git a/xcompile/lib/getline.c b/xcompile/lib/getline.c deleted file mode 100644 index 85f16ab8bac..00000000000 --- a/xcompile/lib/getline.c +++ /dev/null @@ -1,27 +0,0 @@ -/* getline.c --- Implementation of replacement getline function. - Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Simon Josefsson. */ - -#include - -#include - -ssize_t -getline (char **lineptr, size_t *n, FILE *stream) -{ - return getdelim (lineptr, n, '\n', stream); -} diff --git a/xcompile/lib/getloadavg.c b/xcompile/lib/getloadavg.c deleted file mode 100644 index 59b53e79980..00000000000 --- a/xcompile/lib/getloadavg.c +++ /dev/null @@ -1,943 +0,0 @@ -/* Get the system load averages. - - Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2023 Free Software - Foundation, Inc. - - NOTE: The canonical source of this file is maintained with gnulib. - Bugs can be reported to bug-gnulib@gnu.org. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 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 . */ - -/* Compile-time symbols that this file uses: - - HAVE_PSTAT_GETDYNAMIC Define this if your system has the - pstat_getdynamic function. I think it - is unique to HPUX9. The best way to get the - definition is through the AC_FUNC_GETLOADAVG - macro that comes with autoconf 2.13 or newer. - If that isn't an option, then just put - AC_CHECK_FUNCS(pstat_getdynamic) in your - configure.ac file. - HAVE_LIBPERFSTAT Define this if your system has the - perfstat_cpu_total function in libperfstat (AIX). - FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. - KERNEL_FILE Name of the kernel file to nlist. - LDAV_CVT() Scale the load average from the kernel. - Returns a double. - LDAV_SYMBOL Name of kernel symbol giving load average. - LOAD_AVE_TYPE Type of the load average array in the kernel. - Must be defined unless one of - apollo, DGUX, NeXT, or UMAX is defined; - or we have libkstat; - otherwise, no load average is available. - HAVE_NLIST_H nlist.h is available. NLIST_STRUCT defaults - to this. - NLIST_STRUCT Include nlist.h, not a.out.h. - N_NAME_POINTER The nlist n_name element is a pointer, - not an array. - HAVE_STRUCT_NLIST_N_UN_N_NAME 'n_un.n_name' is member of 'struct nlist'. - LINUX_LDAV_FILE [__linux__, __ANDROID__, __CYGWIN__]: File - containing load averages. - - Specific system predefines this file uses, aside from setting - default values if not emacs: - - apollo - BSD Real BSD, not just BSD-like. - DGUX - eunice UNIX emulator under VMS. - hpux - __MSDOS__ No-op for MSDOS. - NeXT - sgi - UMAX - UMAX4_3 - VMS - _WIN32 Native Windows (possibly also defined on Cygwin) - __linux__, __ANDROID__ Linux: assumes /proc file system mounted. - Support from Michael K. Johnson. - __CYGWIN__ Cygwin emulates linux /proc/loadavg. - __NetBSD__ NetBSD: assumes /kern file system mounted. - - In addition, to avoid nesting many #ifdefs, we internally set - LDAV_DONE to indicate that the load average has been computed. - - We also #define LDAV_PRIVILEGED if a program will require - special installation to be able to call getloadavg. */ - -#include - -/* Specification. */ -#include - -#include -#include - -# include - -# if HAVE_SYS_PARAM_H -# include -# endif - -# include "intprops.h" - -# if defined _WIN32 && ! defined __CYGWIN__ && ! defined WINDOWS32 -# define WINDOWS32 -# endif - -# ifdef NeXT -/* NeXT in the 2.{0,1,2} releases defines BSD in , which - conflicts with the definition understood in this file, that this - really is BSD. */ -# undef BSD - -/* NeXT defines FSCALE in . However, we take FSCALE being - defined to mean that the nlist method should be used, which is not true. */ -# undef FSCALE -# endif - -/* Same issues as for NeXT apply to the HURD-based GNU system. */ -# ifdef __GNU__ -# undef BSD -# undef FSCALE -# endif /* __GNU__ */ - -/* Set values that are different from the defaults, which are - set a little farther down with #ifndef. */ - - -/* Some shorthands. */ - -# if defined (HPUX) && !defined (hpux) -# define hpux -# endif - -# if defined (__hpux) && !defined (hpux) -# define hpux -# endif - -# if defined (__sun) && !defined (sun) -# define sun -# endif - -# if defined (hp300) && !defined (hpux) -# define MORE_BSD -# endif - -# if defined (__SVR4) && !defined (SVR4) -# define SVR4 -# endif - -# if (defined (sun) && defined (SVR4)) || defined (SOLARIS2) -# define SUNOS_5 -# endif - -# if defined (__osf__) && (defined (__alpha) || defined (__alpha__)) -# define OSF_ALPHA -# include -# include -# include -# include -/* Tru64 4.0D's table.h redefines sys */ -# undef sys -# endif - -# if defined (__osf__) && (defined (mips) || defined (__mips__)) -# define OSF_MIPS -# include -# endif - - -/* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */ -# ifndef LOAD_AVE_TYPE - -# ifdef MORE_BSD -# define LOAD_AVE_TYPE long -# endif - -# ifdef sun -# define LOAD_AVE_TYPE long -# endif - -# ifdef sgi -# define LOAD_AVE_TYPE long -# endif - -# ifdef SVR4 -# define LOAD_AVE_TYPE long -# endif - -# ifdef OSF_ALPHA -# define LOAD_AVE_TYPE long -# endif - -# if defined _AIX && ! defined HAVE_LIBPERFSTAT -# define LOAD_AVE_TYPE long -# endif - -# endif /* No LOAD_AVE_TYPE. */ - -# ifdef OSF_ALPHA -/* defines an incorrect value for FSCALE on Alpha OSF/1, - according to ghazi@noc.rutgers.edu. */ -# undef FSCALE -# define FSCALE 1024.0 -# endif - - -# ifndef FSCALE - -/* SunOS and some others define FSCALE in sys/param.h. */ - -# ifdef MORE_BSD -# define FSCALE 2048.0 -# endif - -# if defined (MIPS) || defined (SVR4) -# define FSCALE 256 -# endif - -# if defined (sgi) -/* Sometimes both MIPS and sgi are defined, so FSCALE was just defined - above under #ifdef MIPS. But we want the sgi value. */ -# undef FSCALE -# define FSCALE 1000.0 -# endif - -# if defined _AIX && !defined HAVE_LIBPERFSTAT -# define FSCALE 65536.0 -# endif - -# endif /* Not FSCALE. */ - -# if !defined (LDAV_CVT) && defined (FSCALE) -# define LDAV_CVT(n) (((double) (n)) / FSCALE) -# endif - -# ifndef NLIST_STRUCT -# if HAVE_NLIST_H -# define NLIST_STRUCT -# endif -# endif - -# if defined (sgi) || (defined (mips) && !defined (BSD)) -# define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31)) -# endif - - -# if !defined (KERNEL_FILE) && defined (hpux) -# define KERNEL_FILE "/hp-ux" -# endif - -# if !defined (KERNEL_FILE) && (defined (MIPS) || defined (SVR4) || defined (ISC) || defined (sgi)) -# define KERNEL_FILE "/unix" -# endif - - -# if !defined (LDAV_SYMBOL) && (defined (hpux) || defined (SVR4) || defined (ISC) || defined (sgi) || (defined (_AIX) && !defined(HAVE_LIBPERFSTAT))) -# define LDAV_SYMBOL "avenrun" -# endif - -# ifdef HAVE_UNISTD_H -# include -# endif - -/* LOAD_AVE_TYPE should only get defined if we're going to use the - nlist method. */ -# if !defined (LOAD_AVE_TYPE) && (defined (BSD) || defined (LDAV_CVT) || defined (KERNEL_FILE) || defined (LDAV_SYMBOL)) -# define LOAD_AVE_TYPE double -# endif - -# ifdef LOAD_AVE_TYPE - -# ifndef __VMS -# if !(defined __linux__ || defined __ANDROID__) -# ifndef NLIST_STRUCT -# include -# else /* NLIST_STRUCT */ -# include -# endif /* NLIST_STRUCT */ - -# ifdef SUNOS_5 -# include -# include -# endif - -# if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) -# include -# endif - -# ifndef KERNEL_FILE -# define KERNEL_FILE "/vmunix" -# endif /* KERNEL_FILE */ - -# ifndef LDAV_SYMBOL -# define LDAV_SYMBOL "_avenrun" -# endif /* LDAV_SYMBOL */ -# endif /* __linux__ || __ANDROID__ */ - -# else /* __VMS */ - -# ifndef eunice -# include -# include -# else /* eunice */ -# include -# endif /* eunice */ -# endif /* __VMS */ - -# ifndef LDAV_CVT -# define LDAV_CVT(n) ((double) (n)) -# endif /* !LDAV_CVT */ - -# endif /* LOAD_AVE_TYPE */ - -# if defined HAVE_LIBPERFSTAT -# include -# include -# include -# ifndef SBITS -# define SBITS 16 -# endif -# endif - -# if defined (__GNU__) && !defined (NeXT) -/* Note that NeXT Openstep defines __GNU__ even though it should not. */ -/* GNU system acts much like NeXT, for load average purposes, - but not exactly. */ -# define NeXT -# define host_self mach_host_self -# endif - -# ifdef NeXT -# ifdef HAVE_MACH_MACH_H -# include -# else -# include -# endif -# endif /* NeXT */ - -# ifdef sgi -# include -# endif /* sgi */ - -# ifdef UMAX -# include -# include -# include -# include - -# ifdef UMAX_43 -# include -# include -# include -# include -# include -# else /* Not UMAX_43. */ -# include -# include -# include -# include -# include -# include -# endif /* Not UMAX_43. */ -# endif /* UMAX */ - -# ifdef DGUX -# include -# endif - -# if (defined __linux__ || defined __ANDROID__ \ - || defined __CYGWIN__ || defined SUNOS_5 \ - || (defined LOAD_AVE_TYPE && ! defined __VMS)) -# include -# endif - -/* Avoid static vars inside a function since in HPUX they dump as pure. */ - -# ifdef NeXT -static processor_set_t default_set; -static bool getloadavg_initialized; -# endif /* NeXT */ - -# ifdef UMAX -static unsigned int cpus = 0; -static unsigned int samples; -# endif /* UMAX */ - -# ifdef DGUX -static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ -# endif /* DGUX */ - -# if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE) -/* File descriptor open to /dev/kmem or VMS load ave driver. */ -static int channel; -/* True if channel is valid. */ -static bool getloadavg_initialized; -/* Offset in kmem to seek to read load average, or 0 means invalid. */ -static long offset; - -# if ! defined __VMS && ! defined sgi && ! (defined __linux__ || defined __ANDROID__) -static struct nlist name_list[2]; -# endif - -# ifdef SUNOS_5 -static kvm_t *kd; -# endif /* SUNOS_5 */ - -# endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */ - -/* Put the 1 minute, 5 minute and 15 minute load averages - into the first NELEM elements of LOADAVG. - Return the number written (never more than 3, but may be less than NELEM), - or -1 (setting errno) if an error occurred. */ - -int -getloadavg (double loadavg[], int nelem) -{ - int elem = 0; /* Return value. */ - -# ifdef NO_GET_LOAD_AVG -# define LDAV_DONE - errno = ENOSYS; - elem = -1; -# endif - -# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Solaris <= 2.6 */ -/* Use libkstat because we don't have to be root. */ -# define LDAV_DONE - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_named_t *kn; - int saved_errno; - - kc = kstat_open (); - if (kc == NULL) - return -1; - ksp = kstat_lookup (kc, "unix", 0, "system_misc"); - if (ksp == NULL) - return -1; - if (kstat_read (kc, ksp, 0) == -1) - return -1; - - - kn = kstat_data_lookup (ksp, "avenrun_1min"); - if (kn == NULL) - { - /* Return -1 if no load average information is available. */ - nelem = 0; - elem = -1; - } - - if (nelem >= 1) - loadavg[elem++] = (double) kn->value.ul / FSCALE; - - if (nelem >= 2) - { - kn = kstat_data_lookup (ksp, "avenrun_5min"); - if (kn != NULL) - { - loadavg[elem++] = (double) kn->value.ul / FSCALE; - - if (nelem >= 3) - { - kn = kstat_data_lookup (ksp, "avenrun_15min"); - if (kn != NULL) - loadavg[elem++] = (double) kn->value.ul / FSCALE; - } - } - } - - saved_errno = errno; - kstat_close (kc); - errno = saved_errno; -# endif /* HAVE_LIBKSTAT */ - -# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) - /* HP-UX */ -/* Use pstat_getdynamic() because we don't have to be root. */ -# define LDAV_DONE -# undef LOAD_AVE_TYPE - - struct pst_dynamic dyn_info; - if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0) - return -1; - if (nelem > 0) - loadavg[elem++] = dyn_info.psd_avg_1_min; - if (nelem > 1) - loadavg[elem++] = dyn_info.psd_avg_5_min; - if (nelem > 2) - loadavg[elem++] = dyn_info.psd_avg_15_min; - -# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ - -# if ! defined LDAV_DONE && defined HAVE_LIBPERFSTAT /* AIX */ -# define LDAV_DONE -# undef LOAD_AVE_TYPE -/* Use perfstat_cpu_total because we don't have to be root. */ - { - perfstat_cpu_total_t cpu_stats; - int result = perfstat_cpu_total (NULL, &cpu_stats, sizeof cpu_stats, 1); - if (result == -1) - return result; - loadavg[0] = cpu_stats.loadavg[0] / (double)(1 << SBITS); - loadavg[1] = cpu_stats.loadavg[1] / (double)(1 << SBITS); - loadavg[2] = cpu_stats.loadavg[2] / (double)(1 << SBITS); - elem = 3; - } -# endif - -# if !defined (LDAV_DONE) && (defined __linux__ || defined __ANDROID__ || defined __CYGWIN__) - /* Linux without glibc, Android, Cygwin */ -# define LDAV_DONE -# undef LOAD_AVE_TYPE - -# ifndef LINUX_LDAV_FILE -# define LINUX_LDAV_FILE "/proc/loadavg" -# endif - - char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")]; - char const *ptr = ldavgbuf; - int fd, count, saved_errno; - - fd = open (LINUX_LDAV_FILE, O_RDONLY | O_CLOEXEC); - if (fd == -1) - return -1; - count = read (fd, ldavgbuf, sizeof ldavgbuf - 1); - saved_errno = errno; - (void) close (fd); - errno = saved_errno; - if (count <= 0) - return -1; - ldavgbuf[count] = '\0'; - - for (elem = 0; elem < nelem; elem++) - { - double numerator = 0; - double denominator = 1; - - while (*ptr == ' ') - ptr++; - - /* Finish if this number is missing, and report an error if all - were missing. */ - if (! ('0' <= *ptr && *ptr <= '9')) - { - if (elem == 0) - { - errno = ENOTSUP; - return -1; - } - break; - } - - while ('0' <= *ptr && *ptr <= '9') - numerator = 10 * numerator + (*ptr++ - '0'); - - if (*ptr == '.') - for (ptr++; '0' <= *ptr && *ptr <= '9'; ptr++) - numerator = 10 * numerator + (*ptr - '0'), denominator *= 10; - - loadavg[elem] = numerator / denominator; - } - - return elem; - -# endif /* __linux__ || __ANDROID__ || __CYGWIN__ */ - -# if !defined (LDAV_DONE) && defined (__NetBSD__) /* NetBSD < 0.9 */ -# define LDAV_DONE -# undef LOAD_AVE_TYPE - -# ifndef NETBSD_LDAV_FILE -# define NETBSD_LDAV_FILE "/kern/loadavg" -# endif - - unsigned long int load_ave[3], scale; - int count; - char readbuf[4 * INT_BUFSIZE_BOUND (unsigned long int) + 1]; - int fd = open (NETBSD_LDAV_FILE, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return fd; - int nread = read (fd, readbuf, sizeof readbuf - 1); - int err = errno; - close (fd); - if (nread < 0) - { - errno = err; - return -1; - } - readbuf[nread] = '\0'; - count = sscanf (readbuf, "%lu %lu %lu %lu\n", - &load_ave[0], &load_ave[1], &load_ave[2], - &scale); - if (count != 4) - { - errno = ENOTSUP; - return -1; - } - - for (elem = 0; elem < nelem; elem++) - loadavg[elem] = (double) load_ave[elem] / (double) scale; - - return elem; - -# endif /* __NetBSD__ */ - -# if !defined (LDAV_DONE) && defined (NeXT) /* NeXTStep */ -# define LDAV_DONE - /* The NeXT code was adapted from iscreen 3.2. */ - - host_t host; - struct processor_set_basic_info info; - unsigned int info_count; - - /* We only know how to get the 1-minute average for this system, - so even if the caller asks for more than 1, we only return 1. */ - - if (!getloadavg_initialized) - { - if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) - getloadavg_initialized = true; - } - - if (getloadavg_initialized) - { - info_count = PROCESSOR_SET_BASIC_INFO_COUNT; - if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, - (processor_set_info_t) &info, &info_count) - != KERN_SUCCESS) - getloadavg_initialized = false; - else - { - if (nelem > 0) - loadavg[elem++] = (double) info.load_average / LOAD_SCALE; - } - } - - if (!getloadavg_initialized) - { - errno = ENOTSUP; - return -1; - } -# endif /* NeXT */ - -# if !defined (LDAV_DONE) && defined (UMAX) -# define LDAV_DONE -/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not - have a /dev/kmem. Information about the workings of the running kernel - can be gathered with inq_stats system calls. - We only know how to get the 1-minute average for this system. */ - - struct proc_summary proc_sum_data; - struct stat_descr proc_info; - double load; - register unsigned int i, j; - - if (cpus == 0) - { - register unsigned int c, i; - struct cpu_config conf; - struct stat_descr desc; - - desc.sd_next = 0; - desc.sd_subsys = SUBSYS_CPU; - desc.sd_type = CPUTYPE_CONFIG; - desc.sd_addr = (char *) &conf; - desc.sd_size = sizeof conf; - - if (inq_stats (1, &desc)) - return -1; - - c = 0; - for (i = 0; i < conf.config_maxclass; ++i) - { - struct class_stats stats; - memset (&stats, 0, sizeof stats); - - desc.sd_type = CPUTYPE_CLASS; - desc.sd_objid = i; - desc.sd_addr = (char *) &stats; - desc.sd_size = sizeof stats; - - if (inq_stats (1, &desc)) - return -1; - - c += stats.class_numcpus; - } - cpus = c; - samples = cpus < 2 ? 3 : (2 * cpus / 3); - } - - proc_info.sd_next = 0; - proc_info.sd_subsys = SUBSYS_PROC; - proc_info.sd_type = PROCTYPE_SUMMARY; - proc_info.sd_addr = (char *) &proc_sum_data; - proc_info.sd_size = sizeof (struct proc_summary); - proc_info.sd_sizeused = 0; - - if (inq_stats (1, &proc_info) != 0) - return -1; - - load = proc_sum_data.ps_nrunnable; - j = 0; - for (i = samples - 1; i > 0; --i) - { - load += proc_sum_data.ps_nrun[j]; - if (j++ == PS_NRUNSIZE) - j = 0; - } - - if (nelem > 0) - loadavg[elem++] = load / samples / cpus; -# endif /* UMAX */ - -# if !defined (LDAV_DONE) && defined (DGUX) -# define LDAV_DONE - /* This call can return -1 for an error, but with good args - it's not supposed to fail. The first argument is for no - apparent reason of type 'long int *'. */ - dg_sys_info ((long int *) &load_info, - DG_SYS_INFO_LOAD_INFO_TYPE, - DG_SYS_INFO_LOAD_VERSION_0); - - if (nelem > 0) - loadavg[elem++] = load_info.one_minute; - if (nelem > 1) - loadavg[elem++] = load_info.five_minute; - if (nelem > 2) - loadavg[elem++] = load_info.fifteen_minute; -# endif /* DGUX */ - -# if !defined (LDAV_DONE) && defined (apollo) -# define LDAV_DONE -/* Apollo code from lisch@mentorg.com (Ray Lischner). - - This system call is not documented. The load average is obtained as - three long integers, for the load average over the past minute, - five minutes, and fifteen minutes. Each value is a scaled integer, - with 16 bits of integer part and 16 bits of fraction part. - - I'm not sure which operating system first supported this system call, - but I know that SR10.2 supports it. */ - - extern void proc1_$get_loadav (); - unsigned long load_ave[3]; - - proc1_$get_loadav (load_ave); - - if (nelem > 0) - loadavg[elem++] = load_ave[0] / 65536.0; - if (nelem > 1) - loadavg[elem++] = load_ave[1] / 65536.0; - if (nelem > 2) - loadavg[elem++] = load_ave[2] / 65536.0; -# endif /* apollo */ - -# if !defined (LDAV_DONE) && defined (OSF_MIPS) -# define LDAV_DONE - - struct tbl_loadavg load_ave; - table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); - loadavg[elem++] - = (load_ave.tl_lscale == 0 - ? load_ave.tl_avenrun.d[0] - : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale)); -# endif /* OSF_MIPS */ - -# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32)) - /* DJGPP */ -# define LDAV_DONE - - /* A faithful emulation is going to have to be saved for a rainy day. */ - for ( ; elem < nelem; elem++) - { - loadavg[elem] = 0.0; - } -# endif /* __MSDOS__ || WINDOWS32 */ - -# if !defined (LDAV_DONE) && defined (OSF_ALPHA) /* OSF/1 */ -# define LDAV_DONE - - struct tbl_loadavg load_ave; - table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); - for (elem = 0; elem < nelem; elem++) - loadavg[elem] - = (load_ave.tl_lscale == 0 - ? load_ave.tl_avenrun.d[elem] - : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale)); -# endif /* OSF_ALPHA */ - -# if ! defined LDAV_DONE && defined __VMS /* VMS */ - /* VMS specific code -- read from the Load Ave driver. */ - - LOAD_AVE_TYPE load_ave[3]; - static bool getloadavg_initialized; -# ifdef eunice - struct - { - int dsc$w_length; - char *dsc$a_pointer; - } descriptor; -# endif - - /* Ensure that there is a channel open to the load ave device. */ - if (!getloadavg_initialized) - { - /* Attempt to open the channel. */ -# ifdef eunice - descriptor.dsc$w_length = 18; - descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE"; -# else - $DESCRIPTOR (descriptor, "LAV0:"); -# endif - if (sys$assign (&descriptor, &channel, 0, 0) & 1) - getloadavg_initialized = true; - } - - /* Read the load average vector. */ - if (getloadavg_initialized - && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0, - load_ave, 12, 0, 0, 0, 0) & 1)) - { - sys$dassgn (channel); - getloadavg_initialized = false; - } - - if (!getloadavg_initialized) - { - errno = ENOTSUP; - return -1; - } -# endif /* ! defined LDAV_DONE && defined __VMS */ - -# if ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS - /* IRIX, other old systems */ - - /* UNIX-specific code -- read the average from /dev/kmem. */ - -# define LDAV_PRIVILEGED /* This code requires special installation. */ - - LOAD_AVE_TYPE load_ave[3]; - - /* Get the address of LDAV_SYMBOL. */ - if (offset == 0) - { -# ifndef sgi -# if ! defined NLIST_STRUCT || ! defined N_NAME_POINTER - strcpy (name_list[0].n_name, LDAV_SYMBOL); - strcpy (name_list[1].n_name, ""); -# else /* NLIST_STRUCT */ -# ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME - name_list[0].n_un.n_name = LDAV_SYMBOL; - name_list[1].n_un.n_name = 0; -# else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ - name_list[0].n_name = LDAV_SYMBOL; - name_list[1].n_name = 0; -# endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ -# endif /* NLIST_STRUCT */ - -# ifndef SUNOS_5 - if ( -# if !defined (_AIX) - nlist (KERNEL_FILE, name_list) -# else /* _AIX */ - knlist (name_list, 1, sizeof (name_list[0])) -# endif - >= 0) - /* Omit "&& name_list[0].n_type != 0 " -- it breaks on Sun386i. */ - { -# ifdef FIXUP_KERNEL_SYMBOL_ADDR - FIXUP_KERNEL_SYMBOL_ADDR (name_list); -# endif - offset = name_list[0].n_value; - } -# endif /* !SUNOS_5 */ -# else /* sgi */ - ptrdiff_t ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); - if (ldav_off != -1) - offset = (long int) ldav_off & 0x7fffffff; -# endif /* sgi */ - } - - /* Make sure we have /dev/kmem open. */ - if (!getloadavg_initialized) - { -# ifndef SUNOS_5 - int fd = open ("/dev/kmem", O_RDONLY | O_CLOEXEC); - if (0 <= fd) - { - channel = fd; - getloadavg_initialized = true; - } -# else /* SUNOS_5 */ - /* We pass 0 for the kernel, corefile, and swapfile names - to use the currently running kernel. */ - kd = kvm_open (0, 0, 0, O_RDONLY, 0); - if (kd != NULL) - { - /* nlist the currently running kernel. */ - kvm_nlist (kd, name_list); - offset = name_list[0].n_value; - getloadavg_initialized = true; - } -# endif /* SUNOS_5 */ - } - - /* If we can, get the load average values. */ - if (offset && getloadavg_initialized) - { - /* Try to read the load. */ -# ifndef SUNOS_5 - if (lseek (channel, offset, 0) == -1L - || read (channel, (char *) load_ave, sizeof (load_ave)) - != sizeof (load_ave)) - { - close (channel); - getloadavg_initialized = false; - } -# else /* SUNOS_5 */ - if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) - != sizeof (load_ave)) - { - kvm_close (kd); - getloadavg_initialized = false; - } -# endif /* SUNOS_5 */ - } - - if (offset == 0 || !getloadavg_initialized) - { - errno = ENOTSUP; - return -1; - } -# endif /* ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS */ - -# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */ - if (nelem > 0) - loadavg[elem++] = LDAV_CVT (load_ave[0]); - if (nelem > 1) - loadavg[elem++] = LDAV_CVT (load_ave[1]); - if (nelem > 2) - loadavg[elem++] = LDAV_CVT (load_ave[2]); - -# define LDAV_DONE -# endif /* !LDAV_DONE && LOAD_AVE_TYPE */ - -# if !defined LDAV_DONE - errno = ENOSYS; - elem = -1; -# endif - return elem; -} diff --git a/xcompile/lib/getopt-cdefs.in.h b/xcompile/lib/getopt-cdefs.in.h deleted file mode 100644 index e76c78cb212..00000000000 --- a/xcompile/lib/getopt-cdefs.in.h +++ /dev/null @@ -1,66 +0,0 @@ -/* getopt-on-non-glibc compatibility macros. - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of gnulib. - Unlike most of the getopt implementation, it is NOT shared - with the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GETOPT_CDEFS_H -#define _GETOPT_CDEFS_H 1 - -/* This header should not be used directly; include getopt.h or - unistd.h instead. It does not have a protective #error, because - the guard macro for getopt.h in gnulib is not fixed. */ - -/* getopt-core.h and getopt-ext.h are shared with GNU libc, and expect - a number of the internal macros supplied to GNU libc's headers by - sys/cdefs.h. Provide fallback definitions for all of them. */ -#if @HAVE_SYS_CDEFS_H@ -# include -#endif - -#ifndef __BEGIN_DECLS -# ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# else -# define __BEGIN_DECLS /* nothing */ -# endif -#endif -#ifndef __END_DECLS -# ifdef __cplusplus -# define __END_DECLS } -# else -# define __END_DECLS /* nothing */ -# endif -#endif - -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_VERSION__ -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -# else -# define __GNUC_PREREQ(maj, min) 0 -# endif -#endif - -#ifndef __THROW -# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4) -# define __THROW throw () -# else -# define __THROW -# endif -#endif - -#endif /* _GETOPT_CDEFS_H */ diff --git a/xcompile/lib/getopt-core.h b/xcompile/lib/getopt-core.h deleted file mode 100644 index c5dd49363f0..00000000000 --- a/xcompile/lib/getopt-core.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Declarations for getopt (basic, portable features only). - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library and is also part of gnulib. - Patches to this file should be submitted to both projects. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _GETOPT_CORE_H -#define _GETOPT_CORE_H 1 - -/* This header should not be used directly; include getopt.h or - unistd.h instead. Unlike most bits headers, it does not have - a protective #error, because the guard macro for getopt.h in - gnulib is not fixed. */ - -__BEGIN_DECLS - -/* For communication from 'getopt' to the caller. - When 'getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when 'ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to 'getopt'. - - On entry to 'getopt', zero means this is the first call; initialize. - - When 'getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, 'optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message 'getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, 'optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in 'optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU 'getopt'. - - The argument '--' causes premature termination of argument - scanning, explicitly telling 'getopt' that there are no more - options. - - If OPTS begins with '-', then non-option arguments are treated as - arguments to the option '\1'. This behavior is specific to the GNU - 'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in - the environment, then do not permute arguments. - - For standards compliance, the 'argv' argument has the type - char *const *, but this is inaccurate; if argument permutation is - enabled, the argv array (not the strings it points to) must be - writable. */ - -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) - __THROW _GL_ARG_NONNULL ((2, 3)); - -__END_DECLS - -#endif /* _GETOPT_CORE_H */ diff --git a/xcompile/lib/getopt-ext.h b/xcompile/lib/getopt-ext.h deleted file mode 100644 index d37c29328b2..00000000000 --- a/xcompile/lib/getopt-ext.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Declarations for getopt (GNU extensions). - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library and is also part of gnulib. - Patches to this file should be submitted to both projects. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _GETOPT_EXT_H -#define _GETOPT_EXT_H 1 - -/* This header should not be used directly; include getopt.h instead. - Unlike most bits headers, it does not have a protective #error, - because the guard macro for getopt.h in gnulib is not fixed. */ - -__BEGIN_DECLS - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of 'struct option' terminated by an element containing a name which is - zero. - - The field 'has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field 'flag' is not NULL, it points to a variable that is set - to the value given in the field 'val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an 'int' to - a compiled-in constant, such as set a value from 'optarg', set the - option's 'flag' field to zero and its 'val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero 'flag' field, 'getopt' - returns the contents of the 'val' field. */ - -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the 'has_arg' field of 'struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); -extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); - -__END_DECLS - -#endif /* _GETOPT_EXT_H */ diff --git a/xcompile/lib/getopt-pfx-core.h b/xcompile/lib/getopt-pfx-core.h deleted file mode 100644 index 3a2fde5ad4f..00000000000 --- a/xcompile/lib/getopt-pfx-core.h +++ /dev/null @@ -1,66 +0,0 @@ -/* getopt (basic, portable features) gnulib wrapper header. - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of gnulib. - Unlike most of the getopt implementation, it is NOT shared - with the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GETOPT_PFX_CORE_H -#define _GETOPT_PFX_CORE_H 1 - -/* This header should not be used directly; include getopt.h or - unistd.h instead. It does not have a protective #error, because - the guard macro for getopt.h in gnulib is not fixed. */ - -/* Standalone applications should #define __GETOPT_PREFIX to an - identifier that prefixes the external functions and variables - defined in getopt-core.h and getopt-ext.h. Systematically - rename identifiers so that they do not collide with the system - functions and variables. Renaming avoids problems with some - compilers and linkers. */ -#ifdef __GETOPT_PREFIX -# ifndef __GETOPT_ID -# define __GETOPT_CONCAT(x, y) x ## y -# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) -# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) -# endif -# undef getopt -# undef optarg -# undef opterr -# undef optind -# undef optopt -# define getopt __GETOPT_ID (getopt) -# define optarg __GETOPT_ID (optarg) -# define opterr __GETOPT_ID (opterr) -# define optind __GETOPT_ID (optind) -# define optopt __GETOPT_ID (optopt) - -/* Work around a a problem on macOS, which declares getopt with a - trailing __DARWIN_ALIAS(getopt) that would expand to something like - __asm("_" "rpl_getopt" "$UNIX2003") were it not for the following - hack to suppress the macOS declaration . */ -# ifdef __APPLE__ -# define _GETOPT -# endif - -/* The system's getopt.h may have already included getopt-core.h to - declare the unprefixed identifiers. Undef _GETOPT_CORE_H so that - getopt-core.h declares them with prefixes. */ -# undef _GETOPT_CORE_H -#endif - -#include - -#endif /* _GETOPT_PFX_CORE_H */ diff --git a/xcompile/lib/getopt-pfx-ext.h b/xcompile/lib/getopt-pfx-ext.h deleted file mode 100644 index 8578d72530a..00000000000 --- a/xcompile/lib/getopt-pfx-ext.h +++ /dev/null @@ -1,70 +0,0 @@ -/* getopt (GNU extensions) gnulib wrapper header. - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of gnulib. - Unlike most of the getopt implementation, it is NOT shared - with the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GETOPT_PFX_EXT_H -#define _GETOPT_PFX_EXT_H 1 - -/* This header should not be used directly; include getopt.h instead. - It does not have a protective #error, because the guard macro for - getopt.h in gnulib is not fixed. */ - -/* Standalone applications should #define __GETOPT_PREFIX to an - identifier that prefixes the external functions and variables - defined in getopt-core.h and getopt-ext.h. Systematically - rename identifiers so that they do not collide with the system - functions and variables. Renaming avoids problems with some - compilers and linkers. */ -#ifdef __GETOPT_PREFIX -# ifndef __GETOPT_ID -# define __GETOPT_CONCAT(x, y) x ## y -# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) -# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) -# endif -# undef getopt_long -# undef getopt_long_only -# undef option -# undef _getopt_internal -# define getopt_long __GETOPT_ID (getopt_long) -# define getopt_long_only __GETOPT_ID (getopt_long_only) -# define option __GETOPT_ID (option) -# define _getopt_internal __GETOPT_ID (getopt_internal) - -/* The system's getopt.h may have already included getopt-ext.h to - declare the unprefixed identifiers. Undef _GETOPT_EXT_H so that - getopt-ext.h declares them with prefixes. */ -# undef _GETOPT_EXT_H -#endif - -/* Standalone applications get correct prototypes for getopt_long and - getopt_long_only; they declare "char **argv". For backward - compatibility with old applications, if __GETOPT_PREFIX is not - defined, we supply GNU-libc-compatible, but incorrect, prototypes - using "char *const *argv". (GNU libc is stuck with the incorrect - prototypes, as they are baked into older versions of LSB.) */ -#ifndef __getopt_argv_const -# if defined __GETOPT_PREFIX -# define __getopt_argv_const /* empty */ -# else -# define __getopt_argv_const const -# endif -#endif - -#include - -#endif /* _GETOPT_PFX_EXT_H */ diff --git a/xcompile/lib/getopt.c b/xcompile/lib/getopt.c deleted file mode 100644 index 1e2441c4afe..00000000000 --- a/xcompile/lib/getopt.c +++ /dev/null @@ -1,811 +0,0 @@ -/* Getopt for GNU. - Copyright (C) 1987-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library and is also part of gnulib. - Patches to this file should be submitted to both projects. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include "getopt.h" - -#include -#include -#include -#include - -#ifdef _LIBC -/* When used as part of glibc, error printing must be done differently - for standards compliance. getopt is not a cancellation point, so - it must not call functions that are, and it is specified by an - older standard than stdio locking, so it must not refer to - functions in the "user namespace" related to stdio locking. - Finally, it must use glibc's internal message translation so that - the messages are looked up in the proper text domain. */ -# include -# define fprintf __fxprintf_nocancel -# define flockfile(fp) _IO_flockfile (fp) -# define funlockfile(fp) _IO_funlockfile (fp) -#else -# include "gettext.h" -# define _(msgid) gettext (msgid) -/* When used standalone, flockfile and funlockfile might not be - available. */ -# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \ - || (defined _WIN32 && ! defined __CYGWIN__)) -# define flockfile(fp) /* nop */ -# define funlockfile(fp) /* nop */ -# endif -/* When used standalone, do not attempt to use alloca. */ -# define __libc_use_alloca(size) 0 -# undef alloca -# define alloca(size) (abort (), (void *)0) -#endif - -/* This implementation of 'getopt' has three modes for handling - options interspersed with non-option arguments. It can stop - scanning for options at the first non-option argument encountered, - as POSIX specifies. It can continue scanning for options after the - first non-option argument, but permute 'argv' as it goes so that, - after 'getopt' is done, all the options precede all the non-option - arguments and 'optind' points to the first non-option argument. - Or, it can report non-option arguments as if they were arguments to - the option character '\x01'. - - The default behavior of 'getopt_long' is to permute the argument list. - When this implementation is used standalone, the default behavior of - 'getopt' is to stop at the first non-option argument, but when it is - used as part of GNU libc it also permutes the argument list. In both - cases, setting the environment variable POSIXLY_CORRECT to any value - disables permutation. - - If the first character of the OPTSTRING argument to 'getopt' or - 'getopt_long' is '+', both functions will stop at the first - non-option argument. If it is '-', both functions will report - non-option arguments as arguments to the option character '\x01'. */ - -#include "getopt_int.h" - -/* For communication from 'getopt' to the caller. - When 'getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when 'ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to 'getopt'. - - On entry to 'getopt', zero means this is the first call; initialize. - - When 'getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, 'optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Keep a global copy of all internal members of getopt_data. */ - -static struct _getopt_data getopt_data; - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - 'first_nonopt' and 'last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (char **argv, struct _getopt_data *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} - -/* Process the argument starting with d->__nextchar as a long option. - d->optind should *not* have been advanced over this argument. - - If the value returned is -1, it was not actually a long option, the - state is unchanged, and the argument should be processed as a set - of short options (this can only happen when long_only is true). - Otherwise, the option (and its argument, if any) have been consumed - and the return value is the value to return from _getopt_internal_r. */ -static int -process_long_option (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, struct _getopt_data *d, - int print_errors, const char *prefix) -{ - char *nameend; - size_t namelen; - const struct option *p; - const struct option *pfound = NULL; - int n_options; - int option_index; - - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - namelen = nameend - d->__nextchar; - - /* First look for an exact match, counting the options as a side - effect. */ - for (p = longopts, n_options = 0; p->name; p++, n_options++) - if (!strncmp (p->name, d->__nextchar, namelen) - && namelen == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - option_index = n_options; - break; - } - - if (pfound == NULL) - { - /* Didn't find an exact match, so look for abbreviations. */ - unsigned char *ambig_set = NULL; - int ambig_malloced = 0; - int ambig_fallback = 0; - int indfound = -1; - - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, namelen)) - { - if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - { - /* Second or later nonexact match found. */ - if (!ambig_fallback) - { - if (!print_errors) - /* Don't waste effort tracking the ambig set if - we're not going to print it anyway. */ - ambig_fallback = 1; - else if (!ambig_set) - { - if (__libc_use_alloca (n_options)) - ambig_set = alloca (n_options); - else if ((ambig_set = malloc (n_options)) == NULL) - /* Fall back to simpler error message. */ - ambig_fallback = 1; - else - ambig_malloced = 1; - - if (ambig_set) - { - memset (ambig_set, 0, n_options); - ambig_set[indfound] = 1; - } - } - if (ambig_set) - ambig_set[option_index] = 1; - } - } - } - - if (ambig_set || ambig_fallback) - { - if (print_errors) - { - if (ambig_fallback) - fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"), - argv[0], prefix, d->__nextchar); - else - { - flockfile (stderr); - fprintf (stderr, - _("%s: option '%s%s' is ambiguous; possibilities:"), - argv[0], prefix, d->__nextchar); - - for (option_index = 0; option_index < n_options; option_index++) - if (ambig_set[option_index]) - fprintf (stderr, " '%s%s'", - prefix, longopts[option_index].name); - - /* This must use 'fprintf' even though it's only - printing a single character, so that it goes through - __fxprintf_nocancel when compiled as part of glibc. */ - fprintf (stderr, "\n"); - funlockfile (stderr); - } - } - if (ambig_malloced) - free (ambig_set); - d->__nextchar += strlen (d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - - option_index = indfound; - } - - if (pfound == NULL) - { - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short option, - then it's an error. */ - if (!long_only || argv[d->optind][1] == '-' - || strchr (optstring, *d->__nextchar) == NULL) - { - if (print_errors) - fprintf (stderr, _("%s: unrecognized option '%s%s'\n"), - argv[0], prefix, d->__nextchar); - - d->__nextchar = NULL; - d->optind++; - d->optopt = 0; - return '?'; - } - - /* Otherwise interpret it as a short option. */ - return -1; - } - - /* We have found a matching long option. Consume it. */ - d->optind++; - d->__nextchar = NULL; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - fprintf (stderr, - _("%s: option '%s%s' doesn't allow an argument\n"), - argv[0], prefix, pfound->name); - - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - fprintf (stderr, - _("%s: option '%s%s' requires an argument\n"), - argv[0], prefix, pfound->name); - - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; -} - -/* Initialize internal data upon the first call to getopt. */ - -static const char * -_getopt_initialize (_GL_UNUSED int argc, - _GL_UNUSED char **argv, const char *optstring, - struct _getopt_data *d, int posixly_correct) -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - if (d->optind == 0) - d->optind = 1; - - d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - - /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct || !!getenv ("POSIXLY_CORRECT")) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - - d->__initialized = 1; - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If 'getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If 'getopt' finds another option character, it returns that character, - updating 'optind' and 'nextchar' so that the next call to 'getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, 'getopt' returns -1. - Then 'optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set 'opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in 'optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in 'optarg', otherwise 'optarg' is set to zero. - - If OPTSTRING starts with '-' or '+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with '--' instead of '-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a '=', or else the in next ARGV-element. - When 'getopt' finds a long-named option, it returns 0 if that option's - 'flag' field is nonzero, the value of the option's 'val' field - if the 'flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of 'struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal_r (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, struct _getopt_data *d, int posixly_correct) -{ - int print_errors = d->opterr; - - if (argc < 1) - return -1; - - d->optarg = NULL; - - if (d->optind == 0 || !d->__initialized) - optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct); - else if (optstring[0] == '-' || optstring[0] == '+') - optstring++; - - if (optstring[0] == ':') - print_errors = 0; - - /* Test whether ARGV[optind] points to a non-option argument. */ -#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') - - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - - if (d->__ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange (argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (d->optind < argc && NONOPTION_P) - d->optind++; - d->__last_nonopt = d->optind; - } - - /* The special ARGV-element '--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (d->optind != argc && !strcmp (argv[d->optind], "--")) - { - d->optind++; - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange (argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - - d->optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (d->optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Check whether it might be a long option. */ - if (longopts) - { - if (argv[d->optind][1] == '-') - { - /* "--foo" is always a long option. The special option - "--" was handled above. */ - d->__nextchar = argv[d->optind] + 2; - return process_long_option (argc, argv, optstring, longopts, - longind, long_only, d, - print_errors, "--"); - } - - /* If long_only and the ARGV-element has the form "-f", - where f is a valid short option, don't consider it an - abbreviated form of a long option that starts with f. - Otherwise there would be no way to give the -f short - option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an - abbreviation of the long option, just like "--fu", and - not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - if (long_only && (argv[d->optind][2] - || !strchr (optstring, argv[d->optind][1]))) - { - int code; - d->__nextchar = argv[d->optind] + 1; - code = process_long_option (argc, argv, optstring, longopts, - longind, long_only, d, - print_errors, "-"); - if (code != -1) - return code; - } - } - - /* It is not a long option. Skip the initial punctuation. */ - d->__nextchar = argv[d->optind] + 1; - } - - /* Look at and handle the next short option-character. */ - - { - char c = *d->__nextchar++; - const char *temp = strchr (optstring, c); - - /* Increment 'optind' when we start to process its last character. */ - if (*d->__nextchar == '\0') - ++d->optind; - - if (temp == NULL || c == ':' || c == ';') - { - if (print_errors) - fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); - d->optopt = c; - return '?'; - } - - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL) - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - d->optarg = d->__nextchar; - else if (d->optind == argc) - { - if (print_errors) - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); - - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - d->optarg = argv[d->optind]; - - d->__nextchar = d->optarg; - d->optarg = NULL; - return process_long_option (argc, argv, optstring, longopts, longind, - 0 /* long_only */, d, print_errors, "-W "); - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); - - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented 'optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} - -int -_getopt_internal (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, int long_only, - int posixly_correct) -{ - int result; - - getopt_data.optind = optind; - getopt_data.opterr = opterr; - - result = _getopt_internal_r (argc, argv, optstring, longopts, - longind, long_only, &getopt_data, - posixly_correct); - - optind = getopt_data.optind; - optarg = getopt_data.optarg; - optopt = getopt_data.optopt; - - return result; -} - -/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt. - Standalone applications just get a POSIX-compliant getopt. - POSIX and LSB both require these functions to take 'char *const *argv' - even though this is incorrect (because of the permutation). */ -#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \ - int \ - NAME (int argc, char *const *argv, const char *optstring) \ - { \ - return _getopt_internal (argc, (char **)argv, optstring, \ - 0, 0, 0, POSIXLY_CORRECT); \ - } - -#ifdef _LIBC -GETOPT_ENTRY(getopt, 0) -GETOPT_ENTRY(__posix_getopt, 1) -#else -GETOPT_ENTRY(getopt, 1) -#endif - - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of 'getopt'. */ - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value '%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/xcompile/lib/getopt.in.h b/xcompile/lib/getopt.in.h deleted file mode 100644 index 0867d365f47..00000000000 --- a/xcompile/lib/getopt.in.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of gnulib. - Unlike most of the getopt implementation, it is NOT shared - with the GNU C Library, which supplies a different version of - this file. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _@GUARD_PREFIX@_GETOPT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* The include_next requires a split double-inclusion guard. We must - also inform the replacement unistd.h to not recursively use - ; our definitions will be present soon enough. */ -#if @HAVE_GETOPT_H@ -# define _GL_SYSTEM_GETOPT -# @INCLUDE_NEXT@ @NEXT_GETOPT_H@ -# undef _GL_SYSTEM_GETOPT -#endif - -#define _@GUARD_PREFIX@_GETOPT_H 1 - -/* Standalone applications should #define __GETOPT_PREFIX to an - identifier that prefixes the external functions and variables - defined in getopt-core.h and getopt-ext.h. When this happens, - include the headers that might declare getopt so that they will not - cause confusion if included after this file (if the system had - , we have already included it). */ -#if defined __GETOPT_PREFIX -# if !@HAVE_GETOPT_H@ -# define __need_system_stdlib_h -# include -# undef __need_system_stdlib_h -# include -# include -# endif -#endif - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -#include -#include -#include - -#endif /* _@GUARD_PREFIX@_GETOPT_H */ diff --git a/xcompile/lib/getopt1.c b/xcompile/lib/getopt1.c deleted file mode 100644 index 49323aa8ed1..00000000000 --- a/xcompile/lib/getopt1.c +++ /dev/null @@ -1,159 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library and is also part of gnulib. - Patches to this file should be submitted to both projects. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include "getopt.h" -#include "getopt_int.h" - -int -getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 0, 0); -} - -int -_getopt_long_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 0, d, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (int argc, char *__getopt_argv_const *argv, - const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 1, 0); -} - -int -_getopt_long_only_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 1, d, 0); -} - - -#ifdef TEST - -#include -#include - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static const struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value '%s'\n", optarg); - break; - - case 'd': - printf ("option d with value '%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/xcompile/lib/getopt_int.h b/xcompile/lib/getopt_int.h deleted file mode 100644 index 4d9e24beebc..00000000000 --- a/xcompile/lib/getopt_int.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Internal declarations for getopt. - Copyright (C) 1989-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library and is also part of gnulib. - Patches to this file should be submitted to both projects. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _GETOPT_INT_H -#define _GETOPT_INT_H 1 - -#include - -extern int _getopt_internal (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct); - - -/* Reentrant versions which can handle parsing multiple argument - vectors at the same time. */ - -/* Describe how to deal with options that follow non-option ARGV-elements. - - REQUIRE_ORDER means don't recognize them as options; stop option - processing when the first non-option is seen. This is what POSIX - specifies should happen. - - PERMUTE means permute the contents of ARGV as we scan, so that - eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written - to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. - - The special argument '--' forces an end of option-scanning regardless - of the value of 'ordering'. In the case of RETURN_IN_ORDER, only - '--' can cause 'getopt' to return -1 with 'optind' != ARGC. */ - -enum __ord - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - }; - -/* Data type for reentrant functions. */ -struct _getopt_data -{ - /* These have exactly the same meaning as the corresponding global - variables, except that they are used for the reentrant - versions of getopt. */ - int optind; - int opterr; - int optopt; - char *optarg; - - /* Internal members. */ - - /* True if the internal members have been initialized. */ - int __initialized; - - /* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - char *__nextchar; - - /* See __ord above. */ - enum __ord __ordering; - - /* Handle permutation of arguments. */ - - /* Describe the part of ARGV that contains non-options that have - been skipped. 'first_nonopt' is the index in ARGV of the first - of them; 'last_nonopt' is the index after the last of them. */ - - int __first_nonopt; - int __last_nonopt; -}; - -/* The initializer is necessary to set OPTIND and OPTERR to their - default values and to clear the initialization flag. */ -#define _GETOPT_DATA_INITIALIZER { 1, 1 } - -extern int _getopt_internal_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, struct _getopt_data *__data, - int __posixly_correct); - -extern int _getopt_long_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - struct _getopt_data *__data); - -extern int _getopt_long_only_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, - int *__longind, - struct _getopt_data *__data); - -#endif /* getopt_int.h */ diff --git a/xcompile/lib/getrandom.c b/xcompile/lib/getrandom.c deleted file mode 100644 index 19bb3429baf..00000000000 --- a/xcompile/lib/getrandom.c +++ /dev/null @@ -1,190 +0,0 @@ -/* Obtain a series of random bytes. - - Copyright 2020-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include - -#include - -#include -#include -#include - -#if defined _WIN32 && ! defined __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -# if HAVE_BCRYPT_H -# include -# else -# define NTSTATUS LONG -typedef void * BCRYPT_ALG_HANDLE; -# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 -# if HAVE_LIB_BCRYPT -extern NTSTATUS WINAPI BCryptGenRandom (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG); -# endif -# endif -# if !HAVE_LIB_BCRYPT -# include -# ifndef CRYPT_VERIFY_CONTEXT -# define CRYPT_VERIFY_CONTEXT 0xF0000000 -# endif -# endif -#endif - -#include "minmax.h" - -#if defined _WIN32 && ! defined __CYGWIN__ - -/* Don't assume that UNICODE is not defined. */ -# undef LoadLibrary -# define LoadLibrary LoadLibraryA -# undef CryptAcquireContext -# define CryptAcquireContext CryptAcquireContextA - -# if !HAVE_LIB_BCRYPT - -/* Avoid warnings from gcc -Wcast-function-type. */ -# define GetProcAddress \ - (void *) GetProcAddress - -/* BCryptGenRandom with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag works only - starting with Windows 7. */ -typedef NTSTATUS (WINAPI * BCryptGenRandomFuncType) (BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG); -static BCryptGenRandomFuncType BCryptGenRandomFunc = NULL; -static BOOL initialized = FALSE; - -static void -initialize (void) -{ - HMODULE bcrypt = LoadLibrary ("bcrypt.dll"); - if (bcrypt != NULL) - { - BCryptGenRandomFunc = - (BCryptGenRandomFuncType) GetProcAddress (bcrypt, "BCryptGenRandom"); - } - initialized = TRUE; -} - -# else - -# define BCryptGenRandomFunc BCryptGenRandom - -# endif - -#else -/* These devices exist on all platforms except native Windows. */ - -/* Name of a device through which the kernel returns high quality random - numbers, from an entropy pool. When the pool is empty, the call blocks - until entropy sources have added enough bits of entropy. */ -# ifndef NAME_OF_RANDOM_DEVICE -# define NAME_OF_RANDOM_DEVICE "/dev/random" -# endif - -/* Name of a device through which the kernel returns random or pseudo-random - numbers. It uses an entropy pool, but, in order to avoid blocking, adds - bits generated by a pseudo-random number generator, as needed. */ -# ifndef NAME_OF_NONCE_DEVICE -# define NAME_OF_NONCE_DEVICE "/dev/urandom" -# endif - -#endif - -/* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS. - Return the number of bytes written (> 0). - Upon error, return -1 and set errno. */ -ssize_t -getrandom (void *buffer, size_t length, unsigned int flags) -#undef getrandom -{ -#if defined _WIN32 && ! defined __CYGWIN__ - /* BCryptGenRandom, defined in - - with the BCRYPT_USE_SYSTEM_PREFERRED_RNG flag - works in Windows 7 and newer. */ - static int bcrypt_not_working /* = 0 */; - if (!bcrypt_not_working) - { -# if !HAVE_LIB_BCRYPT - if (!initialized) - initialize (); -# endif - if (BCryptGenRandomFunc != NULL - && BCryptGenRandomFunc (NULL, buffer, length, - BCRYPT_USE_SYSTEM_PREFERRED_RNG) - == 0 /*STATUS_SUCCESS*/) - return length; - bcrypt_not_working = 1; - } -# if !HAVE_LIB_BCRYPT - /* CryptGenRandom, defined in - - works in older releases as well, but is now deprecated. - CryptAcquireContext, defined in - */ - { - static int crypt_initialized /* = 0 */; - static HCRYPTPROV provider; - if (!crypt_initialized) - { - if (CryptAcquireContext (&provider, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFY_CONTEXT)) - crypt_initialized = 1; - else - crypt_initialized = -1; - } - if (crypt_initialized >= 0) - { - if (!CryptGenRandom (provider, length, buffer)) - { - errno = EIO; - return -1; - } - return length; - } - } -# endif - errno = ENOSYS; - return -1; -#elif HAVE_GETRANDOM - return getrandom (buffer, length, flags); -#else - static int randfd[2] = { -1, -1 }; - bool devrandom = (flags & GRND_RANDOM) != 0; - int fd = randfd[devrandom]; - - if (fd < 0) - { - static char const randdevice[][MAX (sizeof NAME_OF_NONCE_DEVICE, - sizeof NAME_OF_RANDOM_DEVICE)] - = { NAME_OF_NONCE_DEVICE, NAME_OF_RANDOM_DEVICE }; - int oflags = (O_RDONLY + O_CLOEXEC - + (flags & GRND_NONBLOCK ? O_NONBLOCK : 0)); - fd = open (randdevice[devrandom], oflags); - if (fd < 0) - { - if (errno == ENOENT || errno == ENOTDIR) - errno = ENOSYS; - return -1; - } - randfd[devrandom] = fd; - } - - return read (fd, buffer, length); -#endif -} diff --git a/xcompile/lib/gettext.h b/xcompile/lib/gettext.h deleted file mode 100644 index d0462c47e17..00000000000 --- a/xcompile/lib/gettext.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option - or through "#define ENABLE NLS 0" before including this file. */ -#if defined ENABLE_NLS && ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by - the gettext() and ngettext() macros. This is an alternative to calling - textdomain(), and is useful for libraries. */ -# ifdef DEFAULT_TEXT_DOMAIN -# undef gettext -# define gettext(Msgid) \ - dgettext (DEFAULT_TEXT_DOMAIN, Msgid) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) -# endif - -#else - -/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which - chokes if dcgettext is defined as a macro. So include it now, to make - later inclusions of a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ -#if defined(__sun) -# include -#endif - -/* Many header files from the libstdc++ coming with g++ 3.3 or newer include - , which chokes if dcgettext is defined as a macro. So include - it now, to make later inclusions of a NOP. */ -#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) -# include -# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H -# include -# endif -#endif - -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# undef gettext -# define gettext(Msgid) ((const char *) (Msgid)) -# undef dgettext -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) -# undef dcgettext -# define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) -# undef textdomain -# define textdomain(Domainname) ((const char *) (Domainname)) -# undef bindtextdomain -# define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) -# undef bind_textdomain_codeset -# define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) - -#endif - -/* Prefer gnulib's setlocale override over libintl's setlocale override. */ -#ifdef GNULIB_defined_setlocale -# undef setlocale -# define setlocale rpl_setlocale -#endif - -/* A pseudo function call that serves as a marker for the automated - extraction of messages, but does not call gettext(). The run-time - translation is done at a different place in the code. - The argument, String, should be a literal string. Concatenated strings - and other string expressions won't work. - The macro's expansion is not parenthesized, so that it is suitable as - initializer for static 'char[]' or 'const char[]' variables. */ -#define gettext_noop(String) String - -/* The separator between msgctxt and msgid in a .mo file. */ -#define GETTEXT_CONTEXT_GLUE "\004" - -/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a - MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be - short and rarely need to change. - The letter 'p' stands for 'particular' or 'special'. */ -#ifdef DEFAULT_TEXT_DOMAIN -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#else -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#endif -#define dpgettext(Domainname, Msgctxt, Msgid) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) -#ifdef DEFAULT_TEXT_DOMAIN -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#else -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#endif -#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) - -#if defined __GNUC__ || defined __clang__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -pgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - int category) -{ - const char *translation = dcgettext (domain, msg_ctxt_id, category); - if (translation == msg_ctxt_id) - return msgid; - else - return translation; -} - -#if defined __GNUC__ || defined __clang__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -npgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - const char *translation = - dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); - if (translation == msg_ctxt_id || translation == msgid_plural) - return (n == 1 ? msgid : msgid_plural); - else - return translation; -} - -/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID - can be arbitrary expressions. But for string literals these macros are - less efficient than those above. */ - -#include - -/* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported. - This relates to the -Wvla and -Wvla-larger-than warnings, enabled in - the default GCC many warnings set. This allows programs to disable use - of VLAs, which may be unintended, or may be awkward to support portably, - or may have security implications due to non-deterministic stack usage. */ - -#if (!defined GNULIB_NO_VLA \ - && defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ - && !defined __STDC_NO_VLA__) -# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 -#else -# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 -#endif - -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS -#include -#endif - -#define pgettext_expr(Msgctxt, Msgid) \ - dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) -#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ - dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) - -#if defined __GNUC__ || defined __clang__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - int found_translation; - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcgettext (domain, msg_ctxt_id, category); - found_translation = (translation != msg_ctxt_id); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (found_translation) - return translation; - } - return msgid; -} - -#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) - -#if defined __GNUC__ || defined __clang__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcnpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - int found_translation; - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); - found_translation = !(translation == msg_ctxt_id || translation == msgid_plural); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (found_translation) - return translation; - } - return (n == 1 ? msgid : msgid_plural); -} - -#endif /* _LIBGETTEXT_H */ diff --git a/xcompile/lib/gettime.c b/xcompile/lib/gettime.c deleted file mode 100644 index f86cc4efbff..00000000000 --- a/xcompile/lib/gettime.c +++ /dev/null @@ -1,51 +0,0 @@ -/* gettime -- get the system clock - - Copyright (C) 2002, 2004-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include - -#include "timespec.h" - -#include - -/* Get the system time into *TS. */ - -void -gettime (struct timespec *ts) -{ -#if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME - clock_gettime (CLOCK_REALTIME, ts); -#elif defined HAVE_TIMESPEC_GET - timespec_get (ts, TIME_UTC); -#else - struct timeval tv; - gettimeofday (&tv, NULL); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; -#endif -} - -/* Return the current system time as a struct timespec. */ - -struct timespec -current_timespec (void) -{ - struct timespec ts; - gettime (&ts); - return ts; -} diff --git a/xcompile/lib/gettimeofday.c b/xcompile/lib/gettimeofday.c deleted file mode 100644 index d896ec132b9..00000000000 --- a/xcompile/lib/gettimeofday.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Provide gettimeofday for systems that don't have it or for which it's broken. - - Copyright (C) 2001-2003, 2005-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering */ - -#include - -/* Specification. */ -#include - -#include - -#if defined _WIN32 && ! defined __CYGWIN__ -# define WINDOWS_NATIVE -# include -#endif - -#ifdef WINDOWS_NATIVE - -/* Don't assume that UNICODE is not defined. */ -# undef LoadLibrary -# define LoadLibrary LoadLibraryA - -# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8) - -/* Avoid warnings from gcc -Wcast-function-type. */ -# define GetProcAddress \ - (void *) GetProcAddress - -/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8. */ -typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME *lpTime); -static GetSystemTimePreciseAsFileTimeFuncType GetSystemTimePreciseAsFileTimeFunc = NULL; -static BOOL initialized = FALSE; - -static void -initialize (void) -{ - HMODULE kernel32 = LoadLibrary ("kernel32.dll"); - if (kernel32 != NULL) - { - GetSystemTimePreciseAsFileTimeFunc = - (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, "GetSystemTimePreciseAsFileTime"); - } - initialized = TRUE; -} - -# else - -# define GetSystemTimePreciseAsFileTimeFunc GetSystemTimePreciseAsFileTime - -# endif - -#endif - -/* This is a wrapper for gettimeofday. It is used only on systems - that lack this function, or whose implementation of this function - causes problems. - Work around the bug in some systems whereby gettimeofday clobbers - the static buffer that localtime uses for its return value. The - gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has - this problem. */ - -int -gettimeofday (struct timeval *restrict tv, void *restrict tz) -{ -#undef gettimeofday -#ifdef WINDOWS_NATIVE - - /* On native Windows, there are two ways to get the current time: - GetSystemTimeAsFileTime - - or - GetSystemTimePreciseAsFileTime - . - GetSystemTimeAsFileTime produces values that jump by increments of - 15.627 milliseconds (!) on average. - Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2 - microseconds. - More discussion on this topic: - . */ - FILETIME current_time; - -# if !(_WIN32_WINNT >= _WIN32_WINNT_WIN8) - if (!initialized) - initialize (); -# endif - if (GetSystemTimePreciseAsFileTimeFunc != NULL) - GetSystemTimePreciseAsFileTimeFunc (¤t_time); - else - GetSystemTimeAsFileTime (¤t_time); - - /* Convert from FILETIME to 'struct timeval'. */ - /* FILETIME: */ - ULONGLONG since_1601 = - ((ULONGLONG) current_time.dwHighDateTime << 32) - | (ULONGLONG) current_time.dwLowDateTime; - /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap - years, in total 134774 days. */ - ULONGLONG since_1970 = - since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000; - ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10; - tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000; - tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000; - - return 0; - -#else - -# if HAVE_GETTIMEOFDAY - -# if defined timeval /* 'struct timeval' overridden by gnulib? */ -# undef timeval - struct timeval otv; - int result = gettimeofday (&otv, (struct timezone *) tz); - if (result == 0) - { - tv->tv_sec = otv.tv_sec; - tv->tv_usec = otv.tv_usec; - } -# else - int result = gettimeofday (tv, (struct timezone *) tz); -# endif - - return result; - -# else - -# if !defined OK_TO_USE_1S_CLOCK -# error "Only 1-second nominal clock resolution found. Is that intended?" \ - "If so, compile with the -DOK_TO_USE_1S_CLOCK option." -# endif - tv->tv_sec = time (NULL); - tv->tv_usec = 0; - - return 0; - -# endif -#endif -} diff --git a/xcompile/lib/group-member.c b/xcompile/lib/group-member.c deleted file mode 100644 index 96a09f94a8f..00000000000 --- a/xcompile/lib/group-member.c +++ /dev/null @@ -1,114 +0,0 @@ -/* group-member.c -- determine whether group id is in calling user's group list - - Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include - -/* Most processes have no more than this many groups, and for these - processes we can avoid using malloc. */ -enum { GROUPBUF_SIZE = 100 }; - -struct group_info - { - gid_t *group; - gid_t groupbuf[GROUPBUF_SIZE]; - }; - -static void -free_group_info (struct group_info const *g) -{ - if (g->group != g->groupbuf) - free (g->group); -} - -static int -get_group_info (struct group_info *gi) -{ - int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf); - gi->group = gi->groupbuf; - - if (n_groups < 0) - { - int n_group_slots = getgroups (0, NULL); - size_t nbytes; - if (! ckd_mul (&nbytes, n_group_slots, sizeof *gi->group)) - { - gi->group = malloc (nbytes); - if (gi->group) - n_groups = getgroups (n_group_slots, gi->group); - } - } - - /* In case of error, the user loses. */ - return n_groups; -} - -/* Return non-zero if GID is one that we have in our groups list. - Note that the groups list is not guaranteed to contain the current - or effective group ID, so they should generally be checked - separately. */ - -int -group_member (gid_t gid) -{ - int i; - int found; - struct group_info gi; - int n_groups = get_group_info (&gi); - - /* Search through the list looking for GID. */ - found = 0; - for (i = 0; i < n_groups; i++) - { - if (gid == gi.group[i]) - { - found = 1; - break; - } - } - - free_group_info (&gi); - - return found; -} - -#ifdef TEST - -int -main (int argc, char **argv) -{ - int i; - - for (i = 1; i < argc; i++) - { - gid_t gid; - - gid = atoi (argv[i]); - printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no"); - } - exit (0); -} - -#endif /* TEST */ diff --git a/xcompile/lib/idx.h b/xcompile/lib/idx.h deleted file mode 100644 index 23020b7ec0c..00000000000 --- a/xcompile/lib/idx.h +++ /dev/null @@ -1,134 +0,0 @@ -/* A type for indices and sizes. - Copyright (C) 2020-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _IDX_H -#define _IDX_H - -/* Get ptrdiff_t. */ -#include - -/* Get PTRDIFF_MAX. */ -#include - -/* The type 'idx_t' holds an (array) index or an (object) size. - Its implementation promotes to a signed integer type, - which can hold the values - 0..2^63-1 (on 64-bit platforms) or - 0..2^31-1 (on 32-bit platforms). - - Why a signed integer type? - - * Security: Signed types can be checked for overflow via - '-fsanitize=undefined', but unsigned types cannot. - - * Comparisons without surprises: ISO C99 § 6.3.1.8 specifies a few - surprising results for comparisons, such as - - (int) -3 < (unsigned long) 7 => false - (int) -3 < (unsigned int) 7 => false - and on 32-bit machines: - (long) -3 < (unsigned int) 7 => false - - This is surprising because the natural comparison order is by - value in the realm of infinite-precision signed integers (ℤ). - - The best way to get rid of such surprises is to use signed types - for numerical integer values, and use unsigned types only for - bit masks and enums. - - Why not use 'size_t' directly? - - * Because 'size_t' is an unsigned type, and a signed type is better. - See above. - - Why not use 'ssize_t'? - - * 'ptrdiff_t' is more portable; it is standardized by ISO C - whereas 'ssize_t' is standardized only by POSIX. - - * 'ssize_t' is not required to be as wide as 'size_t', and some - now-obsolete POSIX platforms had 'size_t' wider than 'ssize_t'. - - * Conversely, some now-obsolete platforms had 'ptrdiff_t' wider - than 'size_t', which can be a win and conforms to POSIX. - - Won't this cause a problem with objects larger than PTRDIFF_MAX? - - * Typical modern or large platforms do not allocate such objects, - so this is not much of a problem in practice; for example, you - can safely write 'idx_t len = strlen (s);'. To port to older - small platforms where allocations larger than PTRDIFF_MAX could - in theory be a problem, you can use Gnulib's ialloc module, or - functions like ximalloc in Gnulib's xalloc module. - - Why not use 'ptrdiff_t' directly? - - * Maintainability: When reading and modifying code, it helps to know that - a certain variable cannot have negative values. For example, when you - have a loop - - int n = ...; - for (int i = 0; i < n; i++) ... - - or - - ptrdiff_t n = ...; - for (ptrdiff_t i = 0; i < n; i++) ... - - you have to ask yourself "what if n < 0?". Whereas in - - idx_t n = ...; - for (idx_t i = 0; i < n; i++) ... - - you know that this case cannot happen. - - Similarly, when a programmer writes - - idx_t = ptr2 - ptr1; - - there is an implied assertion that ptr1 and ptr2 point into the same - object and that ptr1 <= ptr2. - - * Being future-proof: In the future, range types (integers which are - constrained to a certain range of values) may be added to C compilers - or to the C standard. Several programming languages (Ada, Haskell, - Common Lisp, Pascal) already have range types. Such range types may - help producing good code and good warnings. The type 'idx_t' could - then be typedef'ed to a range type that is signed after promotion. */ - -/* In the future, idx_t could be typedef'ed to a signed range type. - The clang "extended integer types", supported in Clang 11 or newer - , - are a special case of range types. However, these types don't support binary - operators with plain integer types (e.g. expressions such as x > 1). - Therefore, they don't behave like signed types (and not like unsigned types - either). So, we cannot use them here. */ - -/* Use the signed type 'ptrdiff_t'. */ -/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same - size, but it is so on all platforms we have seen since 1990. */ -typedef ptrdiff_t idx_t; - -/* IDX_MAX is the maximum value of an idx_t. */ -#define IDX_MAX PTRDIFF_MAX - -/* So far no need has been found for an IDX_WIDTH macro. - Perhaps there should be another macro IDX_VALUE_BITS that does not - count the sign bit and is therefore one less than PTRDIFF_WIDTH. */ - -#endif /* _IDX_H */ diff --git a/xcompile/lib/ieee754.in.h b/xcompile/lib/ieee754.in.h deleted file mode 100644 index 8de4c32be5e..00000000000 --- a/xcompile/lib/ieee754.in.h +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (C) 1992-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _IEEE754_H - -#define _IEEE754_H 1 - -#ifndef _GL_GNULIB_HEADER -/* Ordinary glibc usage. */ -# include -# include -#else -/* Gnulib usage. */ -# ifndef __BEGIN_DECLS -# ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# define __END_DECLS } -# else -# define __BEGIN_DECLS -# define __END_DECLS -# endif -# endif -# ifndef __FLOAT_WORD_ORDER -# define __LITTLE_ENDIAN 1234 -# define __BIG_ENDIAN 4321 -# ifdef WORDS_BIGENDIAN -# define __BYTE_ORDER __BIG_ENDIAN -# else -# define __BYTE_ORDER __LITTLE_ENDIAN -# endif -# define __FLOAT_WORD_ORDER __BYTE_ORDER -# endif -#endif - -__BEGIN_DECLS - -union ieee754_float - { - float f; - - /* This is the IEEE 754 single-precision format. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; -#endif /* Big endian. */ -#if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; -#endif /* Little endian. */ - } ieee; - - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:8; - unsigned int quiet_nan:1; - unsigned int mantissa:22; -#endif /* Big endian. */ -#if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int mantissa:22; - unsigned int quiet_nan:1; - unsigned int exponent:8; - unsigned int negative:1; -#endif /* Little endian. */ - } ieee_nan; - }; - -#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ - - -union ieee754_double - { - double d; - - /* This is the IEEE 754 double-precision format. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; -#endif /* Big endian. */ -#if __BYTE_ORDER == __LITTLE_ENDIAN -# if __FLOAT_WORD_ORDER == __BIG_ENDIAN - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; -# else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; -# endif -#endif /* Little endian. */ - } ieee; - - /* This format makes it easier to see if a NaN is a signalling NaN. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:11; - unsigned int quiet_nan:1; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:19; - unsigned int mantissa1:32; -#else -# if __FLOAT_WORD_ORDER == __BIG_ENDIAN - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; - unsigned int mantissa1:32; -# else - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:19; - unsigned int quiet_nan:1; - unsigned int exponent:11; - unsigned int negative:1; -# endif -#endif - } ieee_nan; - }; - -#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ - - -union ieee854_long_double - { - long double d; - - /* This is the IEEE 854 double-extended-precision format. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; -#endif -#if __BYTE_ORDER == __LITTLE_ENDIAN -# if __FLOAT_WORD_ORDER == __BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:32; - unsigned int mantissa1:32; -# else - unsigned int mantissa1:32; - unsigned int mantissa0:32; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; -# endif -#endif - } ieee; - - /* This is for NaNs in the IEEE 854 double-extended-precision format. */ - struct - { -#if __BYTE_ORDER == __BIG_ENDIAN - unsigned int negative:1; - unsigned int exponent:15; - unsigned int empty:16; - unsigned int one:1; - unsigned int quiet_nan:1; - unsigned int mantissa0:30; - unsigned int mantissa1:32; -#endif -#if __BYTE_ORDER == __LITTLE_ENDIAN -# if __FLOAT_WORD_ORDER == __BIG_ENDIAN - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int mantissa1:32; -# else - unsigned int mantissa1:32; - unsigned int mantissa0:30; - unsigned int quiet_nan:1; - unsigned int one:1; - unsigned int exponent:15; - unsigned int negative:1; - unsigned int empty:16; -# endif -#endif - } ieee_nan; - }; - -#define IEEE854_LONG_DOUBLE_BIAS 0x3fff - -__END_DECLS - -#endif /* ieee754.h */ diff --git a/xcompile/lib/ignore-value.h b/xcompile/lib/ignore-value.h deleted file mode 100644 index f0b569af4a7..00000000000 --- a/xcompile/lib/ignore-value.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ignore a function return without a compiler warning. -*- coding: utf-8 -*- - - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Jim Meyering, Eric Blake and Pádraig Brady. */ - -/* Use "ignore_value" to avoid a warning when using a function declared with - gcc's warn_unused_result attribute, but for which you really do want to - ignore the result. Traditionally, people have used a "(void)" cast to - indicate that a function's return value is deliberately unused. However, - if the function is declared with __attribute__((warn_unused_result)), - gcc issues a warning even with the cast. - - Caution: most of the time, you really should heed gcc's warning, and - check the return value. However, in those exceptional cases in which - you're sure you know what you're doing, use this function. - - For the record, here's one of the ignorable warnings: - "copy.c:233: warning: ignoring return value of 'fchown', - declared with attribute warn_unused_result". */ - -#ifndef _GL_IGNORE_VALUE_H -#define _GL_IGNORE_VALUE_H - -/* Normally casting an expression to void discards its value, but GCC - versions 3.4 and newer have __attribute__ ((__warn_unused_result__)) - which may cause unwanted diagnostics in that case. Use __typeof__ - and __extension__ to work around the problem, if the workaround is - known to be needed. - The workaround is not needed with clang. */ -#if (3 < __GNUC__ + (4 <= __GNUC_MINOR__)) && !defined __clang__ -# define ignore_value(x) \ - (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) -#else -# define ignore_value(x) ((void) (x)) -#endif - -#endif diff --git a/xcompile/lib/intprops-internal.h b/xcompile/lib/intprops-internal.h deleted file mode 100644 index 0467a9ca8f2..00000000000 --- a/xcompile/lib/intprops-internal.h +++ /dev/null @@ -1,392 +0,0 @@ -/* intprops-internal.h -- properties of integer types not visible to users - - Copyright (C) 2001-2023 Free Software Foundation, Inc. - - This program 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 program is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GL_INTPROPS_INTERNAL_H -#define _GL_INTPROPS_INTERNAL_H - -#include - -/* Return a value with the common real type of E and V and the value of V. - Do not evaluate E. */ -#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) - -/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see - . */ -#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v)) - -/* The extra casts in the following macros work around compiler bugs, - e.g., in Cray C 5.0.3.0. */ - -/* True if the real type T is signed. */ -#define _GL_TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) - -/* Return 1 if the real expression E, after promotion, has a - signed or floating type. Do not evaluate E. */ -#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) - - -/* Minimum and maximum values for integer types and expressions. */ - -/* The width in bits of the integer type or expression T. - Do not evaluate T. T must not be a bit-field expression. - Padding bits are not supported; this is checked at compile-time below. */ -#define _GL_TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) - -/* The maximum and minimum values for the type of the expression E, - after integer promotion. E is not evaluated. */ -#define _GL_INT_MINIMUM(e) \ - (_GL_EXPR_SIGNED (e) \ - ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ - : _GL_INT_CONVERT (e, 0)) -#define _GL_INT_MAXIMUM(e) \ - (_GL_EXPR_SIGNED (e) \ - ? _GL_SIGNED_INT_MAXIMUM (e) \ - : _GL_INT_NEGATE_CONVERT (e, 1)) -#define _GL_SIGNED_INT_MAXIMUM(e) \ - (((_GL_INT_CONVERT (e, 1) << (_GL_TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1) - -/* Work around OpenVMS incompatibility with C99. */ -#if !defined LLONG_MAX && defined __INT64_MAX -# define LLONG_MAX __INT64_MAX -# define LLONG_MIN __INT64_MIN -#endif - -/* This include file assumes that signed types are two's complement without - padding bits; the above macros have undefined behavior otherwise. - If this is a problem for you, please let us know how to fix it for your host. - This assumption is tested by the intprops-tests module. */ - -/* Does the __typeof__ keyword work? This could be done by - 'configure', but for now it's easier to do it by hand. */ -#if (2 <= __GNUC__ \ - || (4 <= __clang_major__) \ - || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ - || (0x5110 <= __SUNPRO_C && !__STDC__)) -# define _GL_HAVE___TYPEOF__ 1 -#else -# define _GL_HAVE___TYPEOF__ 0 -#endif - -/* Return 1 if the integer type or expression T might be signed. Return 0 - if it is definitely unsigned. T must not be a bit-field expression. - This macro does not evaluate its argument, and expands to an - integer constant expression. */ -#if _GL_HAVE___TYPEOF__ -# define _GL_SIGNED_TYPE_OR_EXPR(t) _GL_TYPE_SIGNED (__typeof__ (t)) -#else -# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 -#endif - -/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. - A should not have side effects, and A's type should be an - integer with minimum value MIN and maximum MAX. */ -#define _GL_INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ - ((min) < 0 ? (a) < - (max) : 0 < (a)) - -/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow - (A, B, P) work when P is non-null. */ -#ifdef __EDG__ -/* EDG-based compilers like nvc 22.1 cannot add 64-bit signed to unsigned - . */ -# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 -#elif defined __has_builtin -# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow) -/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x, - see . */ -#elif 7 <= __GNUC__ -# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1 -#else -# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 -#endif - -/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */ -#if defined __clang_major__ && __clang_major__ < 14 -/* Work around Clang bug . */ -# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0 -#else -# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW -#endif - -/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for - __builtin_sub_overflow_p and __builtin_mul_overflow_p. */ -#ifdef __EDG__ -/* In EDG-based compilers like ICC 2021.3 and earlier, - __builtin_add_overflow_p etc. are not treated as integral constant - expressions even when all arguments are. */ -# define _GL_HAS_BUILTIN_OVERFLOW_P 0 -#elif defined __has_builtin -# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p) -#else -# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) -#endif - -#if (!defined _GL_STDCKDINT_H && 202311 <= __STDC_VERSION__ \ - && ! (_GL_HAS_BUILTIN_ADD_OVERFLOW && _GL_HAS_BUILTIN_MUL_OVERFLOW)) -# include -#endif - -/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. - Return 1 if the result overflows. Arguments should not have side - effects and A, B and *R can be of any integer type other than char, - bool, a bit-precise integer type, or an enumeration type. */ -#if _GL_HAS_BUILTIN_ADD_OVERFLOW -# define _GL_INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r) -# define _GL_INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r) -#elif defined ckd_add && defined ckd_sub && !defined _GL_STDCKDINT_H -# define _GL_INT_ADD_WRAPV(a, b, r) ckd_add (r, + (a), + (b)) -# define _GL_INT_SUBTRACT_WRAPV(a, b, r) ckd_sub (r, + (a), + (b)) -#else -# define _GL_INT_ADD_WRAPV(a, b, r) \ - _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW) -# define _GL_INT_SUBTRACT_WRAPV(a, b, r) \ - _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW) -#endif -#if _GL_HAS_BUILTIN_MUL_OVERFLOW -# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \ - || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \ - && !defined __EDG__) -# define _GL_INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r) -# else - /* Work around GCC bug 91450. */ -# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \ - ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && _GL_EXPR_SIGNED (a) && _GL_EXPR_SIGNED (b) \ - && _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \ - ? ((void) __builtin_mul_overflow (a, b, r), 1) \ - : __builtin_mul_overflow (a, b, r)) -# endif -#elif defined ckd_mul && !defined _GL_STDCKDINT_H -# define _GL_INT_MULTIPLY_WRAPV(a, b, r) ckd_mul (r, + (a), + (b)) -#else -# define _GL_INT_MULTIPLY_WRAPV(a, b, r) \ - _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW) -#endif - -/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 - https://llvm.org/bugs/show_bug.cgi?id=25390 - For now, assume all versions of GCC-like compilers generate bogus - warnings for _Generic. This matters only for compilers that - lack relevant builtins. */ -#if __GNUC__ || defined __clang__ -# define _GL__GENERIC_BOGUS 1 -#else -# define _GL__GENERIC_BOGUS 0 -#endif - -/* Store the low-order bits of A B into *R, where OP specifies - the operation and OVERFLOW the overflow predicate. Return 1 if the - result overflows. Arguments should not have side effects, - and A, B and *R can be of any integer type other than char, bool, a - bit-precise integer type, or an enumeration type. */ -#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS -# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ - (_Generic \ - (*(r), \ - signed char: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - signed char, SCHAR_MIN, SCHAR_MAX), \ - unsigned char: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - unsigned char, 0, UCHAR_MAX), \ - short int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - short int, SHRT_MIN, SHRT_MAX), \ - unsigned short int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - unsigned short int, 0, USHRT_MAX), \ - int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - int, INT_MIN, INT_MAX), \ - unsigned int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - unsigned int, 0, UINT_MAX), \ - long int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - long int, LONG_MIN, LONG_MAX), \ - unsigned long int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - unsigned long int, 0, ULONG_MAX), \ - long long int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ - long long int, LLONG_MIN, LLONG_MAX), \ - unsigned long long int: \ - _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ - unsigned long long int, 0, ULLONG_MAX))) -#else -/* Store the low-order bits of A B into *R, where OP specifies - the operation and OVERFLOW the overflow predicate. If *R is - signed, its type is ST with bounds SMIN..SMAX; otherwise its type - is UT with bounds U..UMAX. ST and UT are narrower than int. - Return 1 if the result overflows. Arguments should not have side - effects, and A, B and *R can be of any integer type other than - char, bool, a bit-precise integer type, or an enumeration type. */ -# if _GL_HAVE___TYPEOF__ -# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \ - (_GL_TYPE_SIGNED (__typeof__ (*(r))) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \ - : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax)) -# else -# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \ - (overflow (a, b, smin, smax) \ - ? (overflow (a, b, 0, umax) \ - ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \ - : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \ - : (overflow (a, b, 0, umax) \ - ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \ - : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0))) -# endif - -# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \ - (sizeof *(r) == sizeof (signed char) \ - ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \ - signed char, SCHAR_MIN, SCHAR_MAX, \ - unsigned char, UCHAR_MAX) \ - : sizeof *(r) == sizeof (short int) \ - ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \ - short int, SHRT_MIN, SHRT_MAX, \ - unsigned short int, USHRT_MAX) \ - : sizeof *(r) == sizeof (int) \ - ? (_GL_EXPR_SIGNED (*(r)) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - int, INT_MIN, INT_MAX) \ - : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ - unsigned int, 0, UINT_MAX)) \ - : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) -# ifdef LLONG_MAX -# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ - (sizeof *(r) == sizeof (long int) \ - ? (_GL_EXPR_SIGNED (*(r)) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - long int, LONG_MIN, LONG_MAX) \ - : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - unsigned long int, 0, ULONG_MAX)) \ - : (_GL_EXPR_SIGNED (*(r)) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ - long long int, LLONG_MIN, LLONG_MAX) \ - : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ - unsigned long long int, 0, ULLONG_MAX))) -# else -# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ - (_GL_EXPR_SIGNED (*(r)) \ - ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - long int, LONG_MIN, LONG_MAX) \ - : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ - unsigned long int, 0, ULONG_MAX)) -# endif -#endif - -/* Store the low-order bits of A B into *R, where the operation - is given by OP. Use the unsigned type UT for calculation to avoid - overflow problems. *R's type is T, with extrema TMIN and TMAX. - T can be any signed integer type other than char, bool, a - bit-precise integer type, or an enumeration type. - Return 1 if the result overflows. */ -#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ - (overflow (a, b, tmin, tmax) \ - ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ - : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) - -/* Return 1 if the integer expressions A - B and -A would overflow, - respectively. Arguments should not have side effects, - and can be any signed integer type other than char, bool, a - bit-precise integer type, or an enumeration type. - These macros are tuned for their last input argument being a constant. */ - -#if _GL_HAS_BUILTIN_OVERFLOW_P -# define _GL_INT_NEGATE_OVERFLOW(a) \ - __builtin_sub_overflow_p (0, a, (__typeof__ (- (a))) 0) -#else -# define _GL_INT_NEGATE_OVERFLOW(a) \ - _GL_INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) -#endif - -/* Return the low-order bits of A B, where the operation is given - by OP. Use the unsigned type UT for calculation to avoid undefined - behavior on signed integer overflow, and convert the result to type T. - UT is at least as wide as T and is no narrower than unsigned int, - T is two's complement, and there is no padding or trap representations. - Assume that converting UT to T yields the low-order bits, as is - done in all known two's-complement C compilers. E.g., see: - https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html - - According to the C standard, converting UT to T yields an - implementation-defined result or signal for values outside T's - range. However, code that works around this theoretical problem - runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: - https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html - As the compiler bug is real, don't try to work around the - theoretical problem. */ - -#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ - ((t) ((ut) (a) op (ut) (b))) - -/* Return true if the numeric values A + B, A - B, A * B fall outside - the range TMIN..TMAX. Arguments should not have side effects - and can be any integer type other than char, bool, - a bit-precise integer type, or an enumeration type. - TMIN should be signed and nonpositive. - TMAX should be positive, and should be signed unless TMIN is zero. */ -#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \ - ((b) < 0 \ - ? (((tmin) \ - ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \ - && (a) < (tmin) - (b)) \ - : (a) <= -1 - (b)) \ - || ((_GL_EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \ - : (a) < 0 \ - ? (((tmin) \ - ? ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \ - && (b) < (tmin) - (a)) \ - : (b) <= -1 - (a)) \ - || ((_GL_EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \ - && (tmax) < (a) + (b))) \ - : (tmax) < (b) || (tmax) - (b) < (a)) -#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \ - (((a) < 0) == ((b) < 0) \ - ? ((a) < (b) \ - ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \ - : (tmax) < (a) - (b)) \ - : (a) < 0 \ - ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \ - || (a) - (tmin) < (b)) \ - : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ - && _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \ - && (tmax) <= -1 - (b)) \ - || (tmax) + (b) < (a))) -#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \ - ((b) < 0 \ - ? ((a) < 0 \ - ? (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ - ? (a) < (tmax) / (b) \ - : ((_GL_INT_NEGATE_OVERFLOW (b) \ - ? _GL_INT_CONVERT (b, tmax) >> (_GL_TYPE_WIDTH (+ (b)) - 1) \ - : (tmax) / -(b)) \ - <= -1 - (a))) \ - : _GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \ - ? (_GL_EXPR_SIGNED (a) \ - ? 0 < (a) + (tmin) \ - : 0 < (a) && -1 - (tmin) < (a) - 1) \ - : (tmin) / (b) < (a)) \ - : (b) == 0 \ - ? 0 \ - : ((a) < 0 \ - ? (_GL_INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \ - ? (_GL_EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \ - : (tmin) / (a) < (b)) \ - : (tmax) / (b) < (a))) - -#endif /* _GL_INTPROPS_INTERNAL_H */ diff --git a/xcompile/lib/intprops.h b/xcompile/lib/intprops.h deleted file mode 100644 index 44b5e60fb9a..00000000000 --- a/xcompile/lib/intprops.h +++ /dev/null @@ -1,335 +0,0 @@ -/* intprops.h -- properties of integer types - - Copyright (C) 2001-2023 Free Software Foundation, Inc. - - This program 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 program is distributed in the hope that 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 program. If not, see . */ - -#ifndef _GL_INTPROPS_H -#define _GL_INTPROPS_H - -#include "intprops-internal.h" - -/* The extra casts in the following macros work around compiler bugs, - e.g., in Cray C 5.0.3.0. */ - -/* True if the arithmetic type T is an integer type. bool counts as - an integer. */ -#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) - -/* True if the real type T is signed. */ -#define TYPE_SIGNED(t) _GL_TYPE_SIGNED (t) - -/* Return 1 if the real expression E, after promotion, has a - signed or floating type. Do not evaluate E. */ -#define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e) - - -/* Minimum and maximum values for integer types and expressions. */ - -/* The width in bits of the integer type or expression T. - Do not evaluate T. T must not be a bit-field expression. - Padding bits are not supported; this is checked at compile-time below. */ -#define TYPE_WIDTH(t) _GL_TYPE_WIDTH (t) - -/* The maximum and minimum values for the integer type T. */ -#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) -#define TYPE_MAXIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) -1 \ - : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) - -/* Bound on length of the string representing an unsigned integer - value representable in B bits. log10 (2.0) < 146/485. The - smallest value of B where this bound is not tight is 2621. */ -#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) - -/* Bound on length of the string representing an integer type or expression T. - T must not be a bit-field expression. - - Subtract 1 for the sign bit if T is signed, and then add 1 more for - a minus sign if needed. - - Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is - unsigned, this macro may overestimate the true bound by one byte when - applied to unsigned types of size 2, 4, 16, ... bytes. */ -#define INT_STRLEN_BOUND(t) \ - (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \ - + _GL_SIGNED_TYPE_OR_EXPR (t)) - -/* Bound on buffer size needed to represent an integer type or expression T, - including the terminating null. T must not be a bit-field expression. */ -#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) - - -/* Range overflow checks. - - The INT__RANGE_OVERFLOW macros return 1 if the corresponding C - operators overflow arithmetically when given the same arguments. - These macros do not rely on undefined or implementation-defined behavior. - Although their implementations are simple and straightforward, - they are harder to use and may be less efficient than the - INT__WRAPV, INT__OK, and INT__OVERFLOW macros described below. - - Example usage: - - long int i = ...; - long int j = ...; - if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) - printf ("multiply would overflow"); - else - printf ("product is %ld", i * j); - - Restrictions on *_RANGE_OVERFLOW macros: - - These macros do not check for all possible numerical problems or - undefined or unspecified behavior: they do not check for division - by zero, for bad shift counts, or for shifting negative numbers. - - These macros may evaluate their arguments zero or multiple times, - so the arguments should not have side effects. The arithmetic - arguments (including the MIN and MAX arguments) must be of the same - integer type after the usual arithmetic conversions, and the type - must have minimum value MIN and maximum MAX. Unsigned types should - use a zero MIN of the proper type. - - Because all arguments are subject to integer promotions, these - macros typically do not work on types narrower than 'int'. - - These macros are tuned for constant MIN and MAX. For commutative - operations such as A + B, they are also tuned for constant B. */ - -/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. */ -#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ - ((b) < 0 \ - ? (a) < (min) - (b) \ - : (max) - (b) < (a)) - -/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. */ -#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ - ((b) < 0 \ - ? (max) + (b) < (a) \ - : (a) < (min) + (b)) - -/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. - See above for restrictions. */ -#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ - _GL_INT_NEGATE_RANGE_OVERFLOW (a, min, max) - -/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. Avoid && and || as they tickle - bugs in Sun C 5.11 2010/08/13 and other compilers; see - . */ -#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ - ((b) < 0 \ - ? ((a) < 0 \ - ? (a) < (max) / (b) \ - : (b) == -1 \ - ? 0 \ - : (min) / (b) < (a)) \ - : (b) == 0 \ - ? 0 \ - : ((a) < 0 \ - ? (a) < (min) / (b) \ - : (max) / (b) < (a))) - -/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. Do not check for division by zero. */ -#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ - ((min) < 0 && (b) == -1 && (a) < - (max)) - -/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. Do not check for division by zero. - Mathematically, % should never overflow, but on x86-like hosts - INT_MIN % -1 traps, and the C standard permits this, so treat this - as an overflow too. */ -#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ - INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) - -/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. - See above for restrictions. Here, MIN and MAX are for A only, and B need - not be of the same type as the other arguments. The C standard says that - behavior is undefined for shifts unless 0 <= B < wordwidth, and that when - A is negative then A << B has undefined behavior and A >> B has - implementation-defined behavior, but do not check these other - restrictions. */ -#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ - ((a) < 0 \ - ? (a) < (min) >> (b) \ - : (max) >> (b) < (a)) - -/* The _GL*_OVERFLOW macros have the same restrictions as the - *_RANGE_OVERFLOW macros, except that they do not assume that operands - (e.g., A and B) have the same type as MIN and MAX. Instead, they assume - that the result (e.g., A + B) has that type. */ -#if _GL_HAS_BUILTIN_OVERFLOW_P -# define _GL_ADD_OVERFLOW(a, b, min, max) \ - __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) -# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ - __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) -# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ - __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) -#else -# define _GL_ADD_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ - : (a) < 0 ? (b) <= (a) + (b) \ - : (b) < 0 ? (a) <= (a) + (b) \ - : (a) + (b) < (b)) -# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ - : (a) < 0 ? 1 \ - : (b) < 0 ? (a) - (b) <= (a) \ - : (a) < (b)) -# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ - (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ - || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) -#endif -#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ - : (a) < 0 ? (b) <= (a) + (b) - 1 \ - : (b) < 0 && (a) + (b) <= (a)) -#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ - ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ - : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ - : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) - -/* Return a nonzero value if A is a mathematical multiple of B, where - A is unsigned, B is negative, and MAX is the maximum value of A's - type. A's type must be the same as (A % B)'s type. Normally (A % - -B == 0) suffices, but things get tricky if -B would overflow. */ -#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ - (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ - ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ - ? (a) \ - : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ - : (a) % - (b)) \ - == 0) - -/* Check for integer overflow, and report low order bits of answer. - - The INT__OVERFLOW macros return 1 if the corresponding C operators - might not yield numerically correct answers due to arithmetic overflow. - The INT__WRAPV macros compute the low-order bits of the sum, - difference, and product of two C integers, and return 1 if these - low-order bits are not numerically correct. - These macros work correctly on all known practical hosts, and do not rely - on undefined behavior due to signed arithmetic overflow. - - Example usage, assuming A and B are long int: - - if (INT_MULTIPLY_OVERFLOW (a, b)) - printf ("result would overflow\n"); - else - printf ("result is %ld (no overflow)\n", a * b); - - Example usage with WRAPV flavor: - - long int result; - bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); - printf ("result is %ld (%s)\n", result, - overflow ? "after overflow" : "no overflow"); - - Restrictions on these macros: - - These macros do not check for all possible numerical problems or - undefined or unspecified behavior: they do not check for division - by zero, for bad shift counts, or for shifting negative numbers. - - These macros may evaluate their arguments zero or multiple times, so the - arguments should not have side effects. - - The WRAPV macros are not constant expressions. They support only - +, binary -, and *. - - Because the WRAPV macros convert the result, they report overflow - in different circumstances than the OVERFLOW macros do. For - example, in the typical case with 16-bit 'short' and 32-bit 'int', - if A, B and *R are all of type 'short' then INT_ADD_OVERFLOW (A, B) - returns false because the addition cannot overflow after A and B - are converted to 'int', whereas INT_ADD_WRAPV (A, B, R) returns - true or false depending on whether the sum fits into 'short'. - - These macros are tuned for their last input argument being a constant. - - A, B, and *R should be integers; they need not be the same type, - and they need not be all signed or all unsigned. - However, none of the integer types should be bit-precise, - and *R's type should not be char, bool, or an enumeration type. - - Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, - A % B, and A << B would overflow, respectively. */ - -#define INT_ADD_OVERFLOW(a, b) \ - _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) -#define INT_SUBTRACT_OVERFLOW(a, b) \ - _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) -#define INT_NEGATE_OVERFLOW(a) _GL_INT_NEGATE_OVERFLOW (a) -#define INT_MULTIPLY_OVERFLOW(a, b) \ - _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) -#define INT_DIVIDE_OVERFLOW(a, b) \ - _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) -#define INT_REMAINDER_OVERFLOW(a, b) \ - _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) -#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ - INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ - _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) - -/* Return 1 if the expression A B would overflow, - where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, - assuming MIN and MAX are the minimum and maximum for the result type. - Arguments should be free of side effects. */ -#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ - op_result_overflow (a, b, \ - _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \ - _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b))) - -/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. - Return 1 if the result overflows. See above for restrictions. */ -#define INT_ADD_WRAPV(a, b, r) _GL_INT_ADD_WRAPV (a, b, r) -#define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r) -#define INT_MULTIPLY_WRAPV(a, b, r) _GL_INT_MULTIPLY_WRAPV (a, b, r) - -/* The following macros compute A + B, A - B, and A * B, respectively. - If no overflow occurs, they set *R to the result and return 1; - otherwise, they return 0 and may modify *R. - - Example usage: - - long int result; - if (INT_ADD_OK (a, b, &result)) - printf ("result is %ld\n", result); - else - printf ("overflow\n"); - - A, B, and *R should be integers; they need not be the same type, - and they need not be all signed or all unsigned. - However, none of the integer types should be bit-precise, - and *R's type should not be char, bool, or an enumeration type. - - These macros work correctly on all known practical hosts, and do not rely - on undefined behavior due to signed arithmetic overflow. - - These macros are not constant expressions. - - These macros may evaluate their arguments zero or multiple times, so the - arguments should not have side effects. - - These macros are tuned for B being a constant. */ - -#define INT_ADD_OK(a, b, r) (! INT_ADD_WRAPV (a, b, r)) -#define INT_SUBTRACT_OK(a, b, r) (! INT_SUBTRACT_WRAPV (a, b, r)) -#define INT_MULTIPLY_OK(a, b, r) (! INT_MULTIPLY_WRAPV (a, b, r)) - -#endif /* _GL_INTPROPS_H */ diff --git a/xcompile/lib/inttypes.in.h b/xcompile/lib/inttypes.in.h deleted file mode 100644 index 50a2bbfcda2..00000000000 --- a/xcompile/lib/inttypes.in.h +++ /dev/null @@ -1,1002 +0,0 @@ -/* Copyright (C) 2006-2023 Free Software Foundation, Inc. - Written by Paul Eggert, Bruno Haible, Derek Price. - This file is part of gnulib. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* - * ISO C 99 for platforms that lack it. - * - */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* Include the original if it exists, and if this file - has not been included yet or if this file includes gnulib stdint.h - which in turn includes this file. - The include_next requires a split double-inclusion guard. */ -#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H -# if @HAVE_INTTYPES_H@ - - /* Some pre-C++11 implementations need this. */ -# if defined __cplusplus && ! defined __STDC_FORMAT_MACROS -# define __STDC_FORMAT_MACROS 1 -# endif - -# @INCLUDE_NEXT@ @NEXT_INTTYPES_H@ - -# define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H -# endif -#endif - -#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H -#define INTTYPES_H - -/* Include or the gnulib replacement. - But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ -# include -#endif -/* Get CHAR_BIT, INT_MAX, LONG_MAX, etc. */ -#include -/* On mingw, __USE_MINGW_ANSI_STDIO only works if is also included */ -#if defined _WIN32 && ! defined __CYGWIN__ -# include -#endif - -#if !(INT_MAX == 0x7fffffff && INT_MIN + INT_MAX == -1) -# error "This file assumes that 'int' is 32-bit two's complement. Please report your platform and compiler to ." -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* 7.8.1 Macros for format specifiers */ - -#if defined _TNS_R_TARGET - /* Tandem NonStop R series and compatible platforms released before - July 2005 support %Ld but not %lld. */ -# define _LONG_LONG_FORMAT_PREFIX "L" -#else -# define _LONG_LONG_FORMAT_PREFIX "ll" -#endif - -#if !defined PRId8 -# ifdef INT8_MAX -# define PRId8 "d" -# endif -#endif -#if !defined PRIi8 -# ifdef INT8_MAX -# define PRIi8 "i" -# endif -#endif -#if !defined PRIo8 -# ifdef UINT8_MAX -# define PRIo8 "o" -# endif -#endif -#if !defined PRIu8 -# ifdef UINT8_MAX -# define PRIu8 "u" -# endif -#endif -#if !defined PRIx8 -# ifdef UINT8_MAX -# define PRIx8 "x" -# endif -#endif -#if !defined PRIX8 -# ifdef UINT8_MAX -# define PRIX8 "X" -# endif -#endif -#if !defined PRId16 -# ifdef INT16_MAX -# define PRId16 "d" -# endif -#endif -#if !defined PRIi16 -# ifdef INT16_MAX -# define PRIi16 "i" -# endif -#endif -#if !defined PRIo16 -# ifdef UINT16_MAX -# define PRIo16 "o" -# endif -#endif -#if !defined PRIu16 -# ifdef UINT16_MAX -# define PRIu16 "u" -# endif -#endif -#if !defined PRIx16 -# ifdef UINT16_MAX -# define PRIx16 "x" -# endif -#endif -#if !defined PRIX16 -# ifdef UINT16_MAX -# define PRIX16 "X" -# endif -#endif -#if !defined PRId32 -# ifdef INT32_MAX -# define PRId32 "d" -# endif -#endif -#if !defined PRIi32 -# ifdef INT32_MAX -# define PRIi32 "i" -# endif -#endif -#if !defined PRIo32 -# ifdef UINT32_MAX -# define PRIo32 "o" -# endif -#endif -#if !defined PRIu32 -# ifdef UINT32_MAX -# define PRIu32 "u" -# endif -#endif -#if !defined PRIx32 -# ifdef UINT32_MAX -# define PRIx32 "x" -# endif -#endif -#if !defined PRIX32 -# ifdef UINT32_MAX -# define PRIX32 "X" -# endif -#endif -#ifdef INT64_MAX -# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@) -# define _PRI64_PREFIX "l" -# elif defined _MSC_VER || defined __MINGW32__ -# define _PRI64_PREFIX "I64" -# elif LONG_MAX >> 30 == 1 -# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX -# endif -# if !defined PRId64 -# define PRId64 _PRI64_PREFIX "d" -# endif -# if !defined PRIi64 -# define PRIi64 _PRI64_PREFIX "i" -# endif -#endif -#ifdef UINT64_MAX -# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@) -# define _PRIu64_PREFIX "l" -# elif defined _MSC_VER || defined __MINGW32__ -# define _PRIu64_PREFIX "I64" -# elif ULONG_MAX >> 31 == 1 -# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX -# endif -# if !defined PRIo64 -# define PRIo64 _PRIu64_PREFIX "o" -# endif -# if !defined PRIu64 -# define PRIu64 _PRIu64_PREFIX "u" -# endif -# if !defined PRIx64 -# define PRIx64 _PRIu64_PREFIX "x" -# endif -# if !defined PRIX64 -# define PRIX64 _PRIu64_PREFIX "X" -# endif -#endif - -#if !defined PRIdLEAST8 -# define PRIdLEAST8 "d" -#endif -#if !defined PRIiLEAST8 -# define PRIiLEAST8 "i" -#endif -#if !defined PRIoLEAST8 -# define PRIoLEAST8 "o" -#endif -#if !defined PRIuLEAST8 -# define PRIuLEAST8 "u" -#endif -#if !defined PRIxLEAST8 -# define PRIxLEAST8 "x" -#endif -#if !defined PRIXLEAST8 -# define PRIXLEAST8 "X" -#endif -#if !defined PRIdLEAST16 -# define PRIdLEAST16 "d" -#endif -#if !defined PRIiLEAST16 -# define PRIiLEAST16 "i" -#endif -#if !defined PRIoLEAST16 -# define PRIoLEAST16 "o" -#endif -#if !defined PRIuLEAST16 -# define PRIuLEAST16 "u" -#endif -#if !defined PRIxLEAST16 -# define PRIxLEAST16 "x" -#endif -#if !defined PRIXLEAST16 -# define PRIXLEAST16 "X" -#endif -#if !defined PRIdLEAST32 -# define PRIdLEAST32 "d" -#endif -#if !defined PRIiLEAST32 -# define PRIiLEAST32 "i" -#endif -#if !defined PRIoLEAST32 -# define PRIoLEAST32 "o" -#endif -#if !defined PRIuLEAST32 -# define PRIuLEAST32 "u" -#endif -#if !defined PRIxLEAST32 -# define PRIxLEAST32 "x" -#endif -#if !defined PRIXLEAST32 -# define PRIXLEAST32 "X" -#endif -#ifdef INT64_MAX -# if !defined PRIdLEAST64 -# define PRIdLEAST64 PRId64 -# endif -# if !defined PRIiLEAST64 -# define PRIiLEAST64 PRIi64 -# endif -#endif -#ifdef UINT64_MAX -# if !defined PRIoLEAST64 -# define PRIoLEAST64 PRIo64 -# endif -# if !defined PRIuLEAST64 -# define PRIuLEAST64 PRIu64 -# endif -# if !defined PRIxLEAST64 -# define PRIxLEAST64 PRIx64 -# endif -# if !defined PRIXLEAST64 -# define PRIXLEAST64 PRIX64 -# endif -#endif - -#if !defined PRIdFAST8 -# if INT_FAST8_MAX > INT32_MAX -# define PRIdFAST8 PRId64 -# else -# define PRIdFAST8 "d" -# endif -#endif -#if !defined PRIiFAST8 -# if INT_FAST8_MAX > INT32_MAX -# define PRIiFAST8 PRIi64 -# else -# define PRIiFAST8 "i" -# endif -#endif -#if !defined PRIoFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define PRIoFAST8 PRIo64 -# else -# define PRIoFAST8 "o" -# endif -#endif -#if !defined PRIuFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define PRIuFAST8 PRIu64 -# else -# define PRIuFAST8 "u" -# endif -#endif -#if !defined PRIxFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define PRIxFAST8 PRIx64 -# else -# define PRIxFAST8 "x" -# endif -#endif -#if !defined PRIXFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define PRIXFAST8 PRIX64 -# else -# define PRIXFAST8 "X" -# endif -#endif -#if !defined PRIdFAST16 -# if INT_FAST16_MAX > INT32_MAX -# define PRIdFAST16 PRId64 -# else -# define PRIdFAST16 "d" -# endif -#endif -#if !defined PRIiFAST16 -# if INT_FAST16_MAX > INT32_MAX -# define PRIiFAST16 PRIi64 -# else -# define PRIiFAST16 "i" -# endif -#endif -#if !defined PRIoFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define PRIoFAST16 PRIo64 -# else -# define PRIoFAST16 "o" -# endif -#endif -#if !defined PRIuFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define PRIuFAST16 PRIu64 -# else -# define PRIuFAST16 "u" -# endif -#endif -#if !defined PRIxFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define PRIxFAST16 PRIx64 -# else -# define PRIxFAST16 "x" -# endif -#endif -#if !defined PRIXFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define PRIXFAST16 PRIX64 -# else -# define PRIXFAST16 "X" -# endif -#endif -#if !defined PRIdFAST32 -# if INT_FAST32_MAX > INT32_MAX -# define PRIdFAST32 PRId64 -# else -# define PRIdFAST32 "d" -# endif -#endif -#if !defined PRIiFAST32 -# if INT_FAST32_MAX > INT32_MAX -# define PRIiFAST32 PRIi64 -# else -# define PRIiFAST32 "i" -# endif -#endif -#if !defined PRIoFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define PRIoFAST32 PRIo64 -# else -# define PRIoFAST32 "o" -# endif -#endif -#if !defined PRIuFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define PRIuFAST32 PRIu64 -# else -# define PRIuFAST32 "u" -# endif -#endif -#if !defined PRIxFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define PRIxFAST32 PRIx64 -# else -# define PRIxFAST32 "x" -# endif -#endif -#if !defined PRIXFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define PRIXFAST32 PRIX64 -# else -# define PRIXFAST32 "X" -# endif -#endif -#ifdef INT64_MAX -# if !defined PRIdFAST64 -# define PRIdFAST64 PRId64 -# endif -# if !defined PRIiFAST64 -# define PRIiFAST64 PRIi64 -# endif -#endif -#ifdef UINT64_MAX -# if !defined PRIoFAST64 -# define PRIoFAST64 PRIo64 -# endif -# if !defined PRIuFAST64 -# define PRIuFAST64 PRIu64 -# endif -# if !defined PRIxFAST64 -# define PRIxFAST64 PRIx64 -# endif -# if !defined PRIXFAST64 -# define PRIXFAST64 PRIX64 -# endif -#endif - -#if !defined PRIdMAX -# if @INT32_MAX_LT_INTMAX_MAX@ -# define PRIdMAX PRId64 -# else -# define PRIdMAX "ld" -# endif -#endif -#if !defined PRIiMAX -# if @INT32_MAX_LT_INTMAX_MAX@ -# define PRIiMAX PRIi64 -# else -# define PRIiMAX "li" -# endif -#endif -#if !defined PRIoMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define PRIoMAX PRIo64 -# else -# define PRIoMAX "lo" -# endif -#endif -#if !defined PRIuMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define PRIuMAX PRIu64 -# else -# define PRIuMAX "lu" -# endif -#endif -#if !defined PRIxMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define PRIxMAX PRIx64 -# else -# define PRIxMAX "lx" -# endif -#endif -#if !defined PRIXMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define PRIXMAX PRIX64 -# else -# define PRIXMAX "lX" -# endif -#endif - -#if !defined PRIdPTR -# ifdef INTPTR_MAX -# define PRIdPTR @PRIPTR_PREFIX@ "d" -# endif -#endif -#if !defined PRIiPTR -# ifdef INTPTR_MAX -# define PRIiPTR @PRIPTR_PREFIX@ "i" -# endif -#endif -#if !defined PRIoPTR -# ifdef UINTPTR_MAX -# define PRIoPTR @PRIPTR_PREFIX@ "o" -# endif -#endif -#if !defined PRIuPTR -# ifdef UINTPTR_MAX -# define PRIuPTR @PRIPTR_PREFIX@ "u" -# endif -#endif -#if !defined PRIxPTR -# ifdef UINTPTR_MAX -# define PRIxPTR @PRIPTR_PREFIX@ "x" -# endif -#endif -#if !defined PRIXPTR -# ifdef UINTPTR_MAX -# define PRIXPTR @PRIPTR_PREFIX@ "X" -# endif -#endif - -#if !defined SCNd8 -# ifdef INT8_MAX -# define SCNd8 "hhd" -# endif -#endif -#if !defined SCNi8 -# ifdef INT8_MAX -# define SCNi8 "hhi" -# endif -#endif -#if !defined SCNo8 -# ifdef UINT8_MAX -# define SCNo8 "hho" -# endif -#endif -#if !defined SCNu8 -# ifdef UINT8_MAX -# define SCNu8 "hhu" -# endif -#endif -#if !defined SCNx8 -# ifdef UINT8_MAX -# define SCNx8 "hhx" -# endif -#endif -#if !defined SCNd16 -# ifdef INT16_MAX -# define SCNd16 "hd" -# endif -#endif -#if !defined SCNi16 -# ifdef INT16_MAX -# define SCNi16 "hi" -# endif -#endif -#if !defined SCNo16 -# ifdef UINT16_MAX -# define SCNo16 "ho" -# endif -#endif -#if !defined SCNu16 -# ifdef UINT16_MAX -# define SCNu16 "hu" -# endif -#endif -#if !defined SCNx16 -# ifdef UINT16_MAX -# define SCNx16 "hx" -# endif -#endif -#if !defined SCNd32 -# ifdef INT32_MAX -# define SCNd32 "d" -# endif -#endif -#if !defined SCNi32 -# ifdef INT32_MAX -# define SCNi32 "i" -# endif -#endif -#if !defined SCNo32 -# ifdef UINT32_MAX -# define SCNo32 "o" -# endif -#endif -#if !defined SCNu32 -# ifdef UINT32_MAX -# define SCNu32 "u" -# endif -#endif -#if !defined SCNx32 -# ifdef UINT32_MAX -# define SCNx32 "x" -# endif -#endif -#ifdef INT64_MAX -# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@) -# define _SCN64_PREFIX "l" -# elif defined _MSC_VER || defined __MINGW32__ -# define _SCN64_PREFIX "I64" -# elif LONG_MAX >> 30 == 1 -# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX -# endif -# if !defined SCNd64 -# define SCNd64 _SCN64_PREFIX "d" -# endif -# if !defined SCNi64 -# define SCNi64 _SCN64_PREFIX "i" -# endif -#endif -#ifdef UINT64_MAX -# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@) -# define _SCNu64_PREFIX "l" -# elif defined _MSC_VER || defined __MINGW32__ -# define _SCNu64_PREFIX "I64" -# elif ULONG_MAX >> 31 == 1 -# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX -# endif -# if !defined SCNo64 -# define SCNo64 _SCNu64_PREFIX "o" -# endif -# if !defined SCNu64 -# define SCNu64 _SCNu64_PREFIX "u" -# endif -# if !defined SCNx64 -# define SCNx64 _SCNu64_PREFIX "x" -# endif -#endif - -#if !defined SCNdLEAST8 -# define SCNdLEAST8 "hhd" -#endif -#if !defined SCNiLEAST8 -# define SCNiLEAST8 "hhi" -#endif -#if !defined SCNoLEAST8 -# define SCNoLEAST8 "hho" -#endif -#if !defined SCNuLEAST8 -# define SCNuLEAST8 "hhu" -#endif -#if !defined SCNxLEAST8 -# define SCNxLEAST8 "hhx" -#endif -#if !defined SCNdLEAST16 -# define SCNdLEAST16 "hd" -#endif -#if !defined SCNiLEAST16 -# define SCNiLEAST16 "hi" -#endif -#if !defined SCNoLEAST16 -# define SCNoLEAST16 "ho" -#endif -#if !defined SCNuLEAST16 -# define SCNuLEAST16 "hu" -#endif -#if !defined SCNxLEAST16 -# define SCNxLEAST16 "hx" -#endif -#if !defined SCNdLEAST32 -# define SCNdLEAST32 "d" -#endif -#if !defined SCNiLEAST32 -# define SCNiLEAST32 "i" -#endif -#if !defined SCNoLEAST32 -# define SCNoLEAST32 "o" -#endif -#if !defined SCNuLEAST32 -# define SCNuLEAST32 "u" -#endif -#if !defined SCNxLEAST32 -# define SCNxLEAST32 "x" -#endif -#ifdef INT64_MAX -# if !defined SCNdLEAST64 -# define SCNdLEAST64 SCNd64 -# endif -# if !defined SCNiLEAST64 -# define SCNiLEAST64 SCNi64 -# endif -#endif -#ifdef UINT64_MAX -# if !defined SCNoLEAST64 -# define SCNoLEAST64 SCNo64 -# endif -# if !defined SCNuLEAST64 -# define SCNuLEAST64 SCNu64 -# endif -# if !defined SCNxLEAST64 -# define SCNxLEAST64 SCNx64 -# endif -#endif - -#if !defined SCNdFAST8 -# if INT_FAST8_MAX > INT32_MAX -# define SCNdFAST8 SCNd64 -# elif INT_FAST8_MAX == 0x7fff -# define SCNdFAST8 "hd" -# elif INT_FAST8_MAX == 0x7f -# define SCNdFAST8 "hhd" -# else -# define SCNdFAST8 "d" -# endif -#endif -#if !defined SCNiFAST8 -# if INT_FAST8_MAX > INT32_MAX -# define SCNiFAST8 SCNi64 -# elif INT_FAST8_MAX == 0x7fff -# define SCNiFAST8 "hi" -# elif INT_FAST8_MAX == 0x7f -# define SCNiFAST8 "hhi" -# else -# define SCNiFAST8 "i" -# endif -#endif -#if !defined SCNoFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define SCNoFAST8 SCNo64 -# elif UINT_FAST8_MAX == 0xffff -# define SCNoFAST8 "ho" -# elif UINT_FAST8_MAX == 0xff -# define SCNoFAST8 "hho" -# else -# define SCNoFAST8 "o" -# endif -#endif -#if !defined SCNuFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define SCNuFAST8 SCNu64 -# elif UINT_FAST8_MAX == 0xffff -# define SCNuFAST8 "hu" -# elif UINT_FAST8_MAX == 0xff -# define SCNuFAST8 "hhu" -# else -# define SCNuFAST8 "u" -# endif -#endif -#if !defined SCNxFAST8 -# if UINT_FAST8_MAX > UINT32_MAX -# define SCNxFAST8 SCNx64 -# elif UINT_FAST8_MAX == 0xffff -# define SCNxFAST8 "hx" -# elif UINT_FAST8_MAX == 0xff -# define SCNxFAST8 "hhx" -# else -# define SCNxFAST8 "x" -# endif -#endif -#if !defined SCNdFAST16 -# if INT_FAST16_MAX > INT32_MAX -# define SCNdFAST16 SCNd64 -# elif INT_FAST16_MAX == 0x7fff -# define SCNdFAST16 "hd" -# else -# define SCNdFAST16 "d" -# endif -#endif -#if !defined SCNiFAST16 -# if INT_FAST16_MAX > INT32_MAX -# define SCNiFAST16 SCNi64 -# elif INT_FAST16_MAX == 0x7fff -# define SCNiFAST16 "hi" -# else -# define SCNiFAST16 "i" -# endif -#endif -#if !defined SCNoFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define SCNoFAST16 SCNo64 -# elif UINT_FAST16_MAX == 0xffff -# define SCNoFAST16 "ho" -# else -# define SCNoFAST16 "o" -# endif -#endif -#if !defined SCNuFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define SCNuFAST16 SCNu64 -# elif UINT_FAST16_MAX == 0xffff -# define SCNuFAST16 "hu" -# else -# define SCNuFAST16 "u" -# endif -#endif -#if !defined SCNxFAST16 -# if UINT_FAST16_MAX > UINT32_MAX -# define SCNxFAST16 SCNx64 -# elif UINT_FAST16_MAX == 0xffff -# define SCNxFAST16 "hx" -# else -# define SCNxFAST16 "x" -# endif -#endif -#if !defined SCNdFAST32 -# if INT_FAST32_MAX > INT32_MAX -# define SCNdFAST32 SCNd64 -# else -# define SCNdFAST32 "d" -# endif -#endif -#if !defined SCNiFAST32 -# if INT_FAST32_MAX > INT32_MAX -# define SCNiFAST32 SCNi64 -# else -# define SCNiFAST32 "i" -# endif -#endif -#if !defined SCNoFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define SCNoFAST32 SCNo64 -# else -# define SCNoFAST32 "o" -# endif -#endif -#if !defined SCNuFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define SCNuFAST32 SCNu64 -# else -# define SCNuFAST32 "u" -# endif -#endif -#if !defined SCNxFAST32 -# if UINT_FAST32_MAX > UINT32_MAX -# define SCNxFAST32 SCNx64 -# else -# define SCNxFAST32 "x" -# endif -#endif -#ifdef INT64_MAX -# if !defined SCNdFAST64 -# define SCNdFAST64 SCNd64 -# endif -# if !defined SCNiFAST64 -# define SCNiFAST64 SCNi64 -# endif -#endif -#ifdef UINT64_MAX -# if !defined SCNoFAST64 -# define SCNoFAST64 SCNo64 -# endif -# if !defined SCNuFAST64 -# define SCNuFAST64 SCNu64 -# endif -# if !defined SCNxFAST64 -# define SCNxFAST64 SCNx64 -# endif -#endif - -#if !defined SCNdMAX -# if @INT32_MAX_LT_INTMAX_MAX@ -# define SCNdMAX SCNd64 -# else -# define SCNdMAX "ld" -# endif -#endif -#if !defined SCNiMAX -# if @INT32_MAX_LT_INTMAX_MAX@ -# define SCNiMAX SCNi64 -# else -# define SCNiMAX "li" -# endif -#endif -#if !defined SCNoMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define SCNoMAX SCNo64 -# else -# define SCNoMAX "lo" -# endif -#endif -#if !defined SCNuMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define SCNuMAX SCNu64 -# else -# define SCNuMAX "lu" -# endif -#endif -#if !defined SCNxMAX -# if @UINT32_MAX_LT_UINTMAX_MAX@ -# define SCNxMAX SCNx64 -# else -# define SCNxMAX "lx" -# endif -#endif - -#if !defined SCNdPTR -# ifdef INTPTR_MAX -# define SCNdPTR @PRIPTR_PREFIX@ "d" -# endif -#endif -#if !defined SCNiPTR -# ifdef INTPTR_MAX -# define SCNiPTR @PRIPTR_PREFIX@ "i" -# endif -#endif -#if !defined SCNoPTR -# ifdef UINTPTR_MAX -# define SCNoPTR @PRIPTR_PREFIX@ "o" -# endif -#endif -#if !defined SCNuPTR -# ifdef UINTPTR_MAX -# define SCNuPTR @PRIPTR_PREFIX@ "u" -# endif -#endif -#if !defined SCNxPTR -# ifdef UINTPTR_MAX -# define SCNxPTR @PRIPTR_PREFIX@ "x" -# endif -#endif - -/* 7.8.2 Functions for greatest-width integer types */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if @GNULIB_IMAXABS@ -# if !@HAVE_DECL_IMAXABS@ -extern intmax_t imaxabs (intmax_t); -# endif -#elif defined GNULIB_POSIXCHECK -# undef imaxabs -# if HAVE_RAW_DECL_IMAXABS -_GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - " - "use gnulib module imaxabs for portability"); -# endif -#endif - -#if @GNULIB_IMAXDIV@ -# if !@HAVE_IMAXDIV_T@ -# if !GNULIB_defined_imaxdiv_t -typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t; -# define GNULIB_defined_imaxdiv_t 1 -# endif -# endif -# if !@HAVE_DECL_IMAXDIV@ -extern imaxdiv_t imaxdiv (intmax_t, intmax_t); -# endif -#elif defined GNULIB_POSIXCHECK -# undef imaxdiv -# if HAVE_RAW_DECL_IMAXDIV -_GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - " - "use gnulib module imaxdiv for portability"); -# endif -#endif - -#if @GNULIB_STRTOIMAX@ -# if @REPLACE_STRTOIMAX@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strtoimax -# define strtoimax rpl_strtoimax -# endif -_GL_FUNCDECL_RPL (strtoimax, intmax_t, - (const char *restrict, char **restrict, int) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strtoimax, intmax_t, - (const char *restrict, char **restrict, int)); -# else -# if !@HAVE_DECL_STRTOIMAX@ -# undef strtoimax -_GL_FUNCDECL_SYS (strtoimax, intmax_t, - (const char *restrict, char **restrict, int) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strtoimax, intmax_t, - (const char *restrict, char **restrict, int)); -# endif -_GL_CXXALIASWARN (strtoimax); -#elif defined GNULIB_POSIXCHECK -# undef strtoimax -# if HAVE_RAW_DECL_STRTOIMAX -_GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - " - "use gnulib module strtoimax for portability"); -# endif -#endif - -#if @GNULIB_STRTOUMAX@ -# if @REPLACE_STRTOUMAX@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strtoumax -# define strtoumax rpl_strtoumax -# endif -_GL_FUNCDECL_RPL (strtoumax, uintmax_t, - (const char *restrict, char **restrict, int) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strtoumax, uintmax_t, - (const char *restrict, char **restrict, int)); -# else -# if !@HAVE_DECL_STRTOUMAX@ -# undef strtoumax -_GL_FUNCDECL_SYS (strtoumax, uintmax_t, - (const char *restrict, char **restrict, int) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strtoumax, uintmax_t, - (const char *restrict, char **restrict, int)); -# endif -_GL_CXXALIASWARN (strtoumax); -#elif defined GNULIB_POSIXCHECK -# undef strtoumax -# if HAVE_RAW_DECL_STRTOUMAX -_GL_WARN_ON_USE (strtoumax, "strtoumax is unportable - " - "use gnulib module strtoumax for portability"); -# endif -#endif - -/* Don't bother defining or declaring wcstoimax and wcstoumax, since - wide-character functions like this are hardly ever useful. */ - -#ifdef __cplusplus -} -#endif - -#endif /* !defined INTTYPES_H && !defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H */ diff --git a/xcompile/lib/lchmod.c b/xcompile/lib/lchmod.c deleted file mode 100644 index b2d1b8bfde1..00000000000 --- a/xcompile/lib/lchmod.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Implement lchmod on platforms where it does not work correctly. - - Copyright 2020-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Paul Eggert */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include -#include - -#include - -/* Work like chmod, except when FILE is a symbolic link. - In that case, on systems where permissions on symbolic links are unsupported - (such as Linux), set errno to EOPNOTSUPP and return -1. */ - -int -lchmod (char const *file, mode_t mode) -{ - char readlink_buf[1]; - -#ifdef O_PATH - /* Open a file descriptor with O_NOFOLLOW, to make sure we don't - follow symbolic links, if /proc is mounted. O_PATH is used to - avoid a failure if the file is not readable. - Cf. */ - int fd = open (file, O_PATH | O_NOFOLLOW | O_CLOEXEC); - if (fd < 0) - return fd; - - int err; - if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) - err = EOPNOTSUPP; - else if (errno == EINVAL) - { - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; - } - else - err = errno == ENOENT ? -1 : errno; - - close (fd); - - errno = err; - if (0 <= err) - return err == 0 ? 0 : -1; -#endif - - size_t len = strlen (file); - if (len && file[len - 1] == '/') - { - struct stat st; - if (lstat (file, &st) < 0) - return -1; - if (!S_ISDIR (st.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } - - /* O_PATH + /proc is not supported. */ - - if (0 <= readlink (file, readlink_buf, sizeof readlink_buf)) - { - errno = EOPNOTSUPP; - return -1; - } - - /* Fall back on chmod, despite a possible race. */ - return chmod (file, mode); -} diff --git a/xcompile/lib/libc-config.h b/xcompile/lib/libc-config.h deleted file mode 100644 index 1d28e58c971..00000000000 --- a/xcompile/lib/libc-config.h +++ /dev/null @@ -1,202 +0,0 @@ -/* System definitions for code taken from the GNU C Library - - Copyright 2017-2023 Free Software Foundation, Inc. - - This program 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 program is distributed in the hope that 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 program; if not, see - . */ - -/* Written by Paul Eggert. */ - -/* This is intended to be a good-enough substitute for glibc system - macros like those defined in , so that Gnulib code - shared with glibc can do this as the first #include: - - #ifndef _LIBC - # include - #endif - - When compiled as part of glibc this is a no-op; when compiled as - part of Gnulib this includes Gnulib's and defines macros - that glibc library code would normally assume. - - Note: This header file MUST NOT be included by public header files - of Gnulib. */ - -#include - -/* On glibc this includes and and #defines - _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 and - DragonFlyBSD 5.9 it includes which defines __nonnull. - Elsewhere it is harmless. */ -#include - -/* From glibc . */ -#ifndef __set_errno -# define __set_errno(val) (errno = (val)) -#endif - -/* From glibc . */ - -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__)) -# else -# define __GNUC_PREREQ(maj, min) 0 -# endif -#endif - -#ifndef __glibc_clang_prereq -# if defined __clang_major__ && defined __clang_minor__ -# ifdef __apple_build_version__ -/* Apple for some reason renumbers __clang_major__ and __clang_minor__. - Gnulib code uses only __glibc_clang_prereq (3, 5); map it to - 6000000 <= __apple_build_version__. Support for other calls to - __glibc_clang_prereq can be added here as needed. */ -# define __glibc_clang_prereq(maj, min) \ - ((maj) == 3 && (min) == 5 ? 6000000 <= __apple_build_version__ : 0) -# else -# define __glibc_clang_prereq(maj, min) \ - ((maj) < __clang_major__ + ((min) <= __clang_minor__)) -# endif -# else -# define __glibc_clang_prereq(maj, min) 0 -# endif -#endif - -#ifndef __attribute_nonnull__ -/* either does not exist, or is too old for Gnulib. - Prepare to include , which is Gnulib's version of a - more-recent glibc . */ - -/* Define _FEATURES_H so that does not include . */ -# ifndef _FEATURES_H -# define _FEATURES_H 1 -# endif -/* Define __GNULIB_CDEFS so that does not attempt to include - nonexistent files. */ -# define __GNULIB_CDEFS -/* Undef the macros unconditionally defined by our copy of glibc - , so that they do not clash with any system-defined - versions. */ -# undef _SYS_CDEFS_H -# undef __ASMNAME -# undef __ASMNAME2 -# undef __BEGIN_DECLS -# undef __CONCAT -# undef __END_DECLS -# undef __HAVE_GENERIC_SELECTION -# undef __LDBL_COMPAT -# undef __LDBL_REDIR -# undef __LDBL_REDIR1 -# undef __LDBL_REDIR1_DECL -# undef __LDBL_REDIR1_NTH -# undef __LDBL_REDIR2_DECL -# undef __LDBL_REDIR_DECL -# undef __LDBL_REDIR_NTH -# undef __LEAF -# undef __LEAF_ATTR -# undef __NTH -# undef __NTHNL -# undef __REDIRECT -# undef __REDIRECT_LDBL -# undef __REDIRECT_NTH -# undef __REDIRECT_NTHNL -# undef __REDIRECT_NTH_LDBL -# undef __STRING -# undef __THROW -# undef __THROWNL -# undef __attr_access -# undef __attr_access_none -# undef __attr_dealloc -# undef __attr_dealloc_free -# undef __attribute__ -# undef __attribute_alloc_align__ -# undef __attribute_alloc_size__ -# undef __attribute_artificial__ -# undef __attribute_const__ -# undef __attribute_deprecated__ -# undef __attribute_deprecated_msg__ -# undef __attribute_format_arg__ -# undef __attribute_format_strfmon__ -# undef __attribute_malloc__ -# undef __attribute_maybe_unused__ -# undef __attribute_noinline__ -# undef __attribute_nonstring__ -# undef __attribute_pure__ -# undef __attribute_returns_twice__ -# undef __attribute_used__ -# undef __attribute_warn_unused_result__ -# undef __bos -# undef __bos0 -# undef __errordecl -# undef __extension__ -# undef __extern_always_inline -# undef __extern_inline -# undef __flexarr -# undef __fortified_attr_access -# undef __fortify_function -# undef __glibc_c99_flexarr_available -# undef __glibc_fortify -# undef __glibc_fortify_n -# undef __glibc_has_attribute -# undef __glibc_has_builtin -# undef __glibc_has_extension -# undef __glibc_likely -# undef __glibc_macro_warning -# undef __glibc_macro_warning1 -# undef __glibc_objsize -# undef __glibc_objsize0 -# undef __glibc_safe_len_cond -# undef __glibc_safe_or_unknown_len -# undef __glibc_unlikely -# undef __glibc_unsafe_len -# undef __glibc_unsigned_or_positive -# undef __inline -# undef __ptr_t -# undef __restrict -# undef __restrict_arr -# undef __va_arg_pack -# undef __va_arg_pack_len -# undef __warnattr -# undef __wur - -/* Include our copy of glibc . */ -# include - -/* __inline is too pessimistic for non-GCC. */ -# undef __inline -# ifndef HAVE___INLINE -# if 199901 <= __STDC_VERSION__ || defined inline -# define __inline inline -# else -# define __inline -# endif -# endif - -#endif /* defined __glibc_likely */ - - -/* A substitute for glibc , good enough for Gnulib. */ -#define attribute_hidden -#define libc_hidden_proto(name) -#define libc_hidden_def(name) -#define libc_hidden_weak(name) -#define libc_hidden_ver(local, name) -#define strong_alias(name, aliasname) -#define weak_alias(name, aliasname) - -/* A substitute for glibc , good enough for Gnulib. */ -#define SHLIB_COMPAT(lib, introduced, obsoleted) 0 -#define compat_symbol(lib, local, symbol, version) extern int dummy -#define versioned_symbol(lib, local, symbol, version) extern int dummy diff --git a/xcompile/lib/limits.in.h b/xcompile/lib/limits.in.h deleted file mode 100644 index eaeac472299..00000000000 --- a/xcompile/lib/limits.in.h +++ /dev/null @@ -1,131 +0,0 @@ -/* A GNU-like . - - Copyright 2016-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined _GL_ALREADY_INCLUDING_LIMITS_H -/* Special invocation convention: - On Haiku/x86_64, we have a sequence of nested includes - -> -> . - In this situation, LONG_MAX and INT_MAX are not yet defined, - therefore we should not attempt to define LONG_BIT. */ - -#@INCLUDE_NEXT@ @NEXT_LIMITS_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_LIMITS_H - -# define _GL_ALREADY_INCLUDING_LIMITS_H - -/* The include_next requires a split double-inclusion guard. */ -# @INCLUDE_NEXT@ @NEXT_LIMITS_H@ - -# undef _GL_ALREADY_INCLUDING_LIMITS_H - -#ifndef _@GUARD_PREFIX@_LIMITS_H -#define _@GUARD_PREFIX@_LIMITS_H - -#ifndef LLONG_MIN -# if defined LONG_LONG_MIN /* HP-UX 11.31 */ -# define LLONG_MIN LONG_LONG_MIN -# elif defined LONGLONG_MIN /* IRIX 6.5 */ -# define LLONG_MIN LONGLONG_MIN -# elif defined __GNUC__ -# define LLONG_MIN (- __LONG_LONG_MAX__ - 1LL) -# endif -#endif -#ifndef LLONG_MAX -# if defined LONG_LONG_MAX /* HP-UX 11.31 */ -# define LLONG_MAX LONG_LONG_MAX -# elif defined LONGLONG_MAX /* IRIX 6.5 */ -# define LLONG_MAX LONGLONG_MAX -# elif defined __GNUC__ -# define LLONG_MAX __LONG_LONG_MAX__ -# endif -#endif -#ifndef ULLONG_MAX -# if defined ULONG_LONG_MAX /* HP-UX 11.31 */ -# define ULLONG_MAX ULONG_LONG_MAX -# elif defined ULONGLONG_MAX /* IRIX 6.5 */ -# define ULLONG_MAX ULONGLONG_MAX -# elif defined __GNUC__ -# define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1ULL) -# endif -#endif - -/* The number of usable bits in an unsigned or signed integer type - with minimum value MIN and maximum value MAX, as an int expression - suitable in #if. Cover all known practical hosts. This - implementation exploits the fact that MAX is 1 less than a power of - 2, and merely counts the number of 1 bits in MAX; "COBn" means - "count the number of 1 bits in the low-order n bits"). */ -#define _GL_INTEGER_WIDTH(min, max) (((min) < 0) + _GL_COB128 (max)) -#define _GL_COB128(n) (_GL_COB64 ((n) >> 31 >> 31 >> 2) + _GL_COB64 (n)) -#define _GL_COB64(n) (_GL_COB32 ((n) >> 31 >> 1) + _GL_COB32 (n)) -#define _GL_COB32(n) (_GL_COB16 ((n) >> 16) + _GL_COB16 (n)) -#define _GL_COB16(n) (_GL_COB8 ((n) >> 8) + _GL_COB8 (n)) -#define _GL_COB8(n) (_GL_COB4 ((n) >> 4) + _GL_COB4 (n)) -#define _GL_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + !!((n) & 1)) - -#ifndef WORD_BIT -/* Assume 'int' is 32 bits wide. */ -# define WORD_BIT 32 -#endif -#ifndef LONG_BIT -/* Assume 'long' is 32 or 64 bits wide. */ -# if LONG_MAX == INT_MAX -# define LONG_BIT 32 -# else -# define LONG_BIT 64 -# endif -#endif - -/* Macros specified by C23 and by ISO/IEC TS 18661-1:2014. */ - -#if (! defined ULLONG_WIDTH \ - && (defined _GNU_SOURCE || defined __STDC_WANT_IEC_60559_BFP_EXT__ \ - || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__))) -# define CHAR_WIDTH _GL_INTEGER_WIDTH (CHAR_MIN, CHAR_MAX) -# define SCHAR_WIDTH _GL_INTEGER_WIDTH (SCHAR_MIN, SCHAR_MAX) -# define UCHAR_WIDTH _GL_INTEGER_WIDTH (0, UCHAR_MAX) -# define SHRT_WIDTH _GL_INTEGER_WIDTH (SHRT_MIN, SHRT_MAX) -# define USHRT_WIDTH _GL_INTEGER_WIDTH (0, USHRT_MAX) -# define INT_WIDTH _GL_INTEGER_WIDTH (INT_MIN, INT_MAX) -# define UINT_WIDTH _GL_INTEGER_WIDTH (0, UINT_MAX) -# define LONG_WIDTH _GL_INTEGER_WIDTH (LONG_MIN, LONG_MAX) -# define ULONG_WIDTH _GL_INTEGER_WIDTH (0, ULONG_MAX) -# define LLONG_WIDTH _GL_INTEGER_WIDTH (LLONG_MIN, LLONG_MAX) -# define ULLONG_WIDTH _GL_INTEGER_WIDTH (0, ULLONG_MAX) -#endif - -/* Macros specified by C23. */ - -#if (! defined BOOL_WIDTH \ - && (defined _GNU_SOURCE \ - || (defined __STDC_VERSION__ && 201710 < __STDC_VERSION__))) -# define BOOL_MAX 1 -# define BOOL_WIDTH 1 -#endif - -#endif /* _@GUARD_PREFIX@_LIMITS_H */ -#endif /* _@GUARD_PREFIX@_LIMITS_H */ -#endif diff --git a/xcompile/lib/lstat.c b/xcompile/lib/lstat.c deleted file mode 100644 index 00a4ce2ab87..00000000000 --- a/xcompile/lib/lstat.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Work around a bug of lstat on some systems - - Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering */ - -/* If the user's config.h happens to include , let it include only - the system's here, so that orig_lstat doesn't recurse to - rpl_lstat. */ -#define __need_system_sys_stat_h -#include - -#if !HAVE_LSTAT -/* On systems that lack symlinks, our replacement already - defined lstat as stat, so there is nothing further to do other than - avoid an empty file. */ -typedef int dummy; -#else /* HAVE_LSTAT */ - -/* Get the original definition of lstat. It might be defined as a macro. */ -# include -# include -# undef __need_system_sys_stat_h - -static int -orig_lstat (const char *filename, struct stat *buf) -{ - return lstat (filename, buf); -} - -/* Specification. */ -# ifdef __osf__ -/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include - above. */ -# include "sys/stat.h" -# else -# include -# endif - -# include "stat-time.h" - -# include -# include - -/* lstat works differently on Linux and Solaris systems. POSIX (see - "pathname resolution" in the glossary) requires that programs like - 'ls' take into consideration the fact that FILE has a trailing slash - when FILE is a symbolic link. On Linux and Solaris 10 systems, the - lstat function already has the desired semantics (in treating - 'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)', - but on Solaris 9 and earlier it does not. - - If FILE has a trailing slash and specifies a symbolic link, - then use stat() to get more info on the referent of FILE. - If the referent is a non-directory, then set errno to ENOTDIR - and return -1. Otherwise, return stat's result. */ - -int -rpl_lstat (const char *file, struct stat *sbuf) -{ - int result = orig_lstat (file, sbuf); - - /* This replacement file can blindly check against '/' rather than - using the ISSLASH macro, because all platforms with '\\' either - lack symlinks (mingw) or have working lstat (cygwin) and thus do - not compile this file. 0 len should have already been filtered - out above, with a failure return of ENOENT. */ - if (result == 0) - { - if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/') - result = stat_time_normalize (result, sbuf); - else - { - /* At this point, a trailing slash is permitted only on - symlink-to-dir; but it should have found information on the - directory, not the symlink. Call 'stat' to get info about the - link's referent. Our replacement stat guarantees valid results, - even if the symlink is not pointing to a directory. */ - if (!S_ISLNK (sbuf->st_mode)) - { - errno = ENOTDIR; - return -1; - } - result = stat (file, sbuf); - } - } - return result; -} - -#endif /* HAVE_LSTAT */ diff --git a/xcompile/lib/malloc.c b/xcompile/lib/malloc.c deleted file mode 100644 index 3ade35cb63f..00000000000 --- a/xcompile/lib/malloc.c +++ /dev/null @@ -1,51 +0,0 @@ -/* malloc() function that is glibc compatible. - - Copyright (C) 1997-1998, 2006-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering and Bruno Haible */ - -#define _GL_USE_STDLIB_ALLOC 1 -#include - -#include - -#include - -#include "xalloc-oversized.h" - -/* Allocate an N-byte block of memory from the heap, even if N is 0. */ - -void * -rpl_malloc (size_t n) -{ - if (n == 0) - n = 1; - - if (xalloc_oversized (n, 1)) - { - errno = ENOMEM; - return NULL; - } - - void *result = malloc (n); - -#if !HAVE_MALLOC_POSIX - if (result == NULL) - errno = ENOMEM; -#endif - - return result; -} diff --git a/xcompile/lib/malloc/dynarray-skeleton.c b/xcompile/lib/malloc/dynarray-skeleton.c deleted file mode 100644 index 580c278b7c5..00000000000 --- a/xcompile/lib/malloc/dynarray-skeleton.c +++ /dev/null @@ -1,528 +0,0 @@ -/* Type-safe arrays which grow dynamically. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* Pre-processor macros which act as parameters: - - DYNARRAY_STRUCT - The struct tag of dynamic array to be defined. - DYNARRAY_ELEMENT - The type name of the element type. Elements are copied - as if by memcpy, and can change address as the dynamic - array grows. - DYNARRAY_PREFIX - The prefix of the functions which are defined. - - The following parameters are optional: - - DYNARRAY_ELEMENT_FREE - DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the - contents of elements. E is of type DYNARRAY_ELEMENT *. - DYNARRAY_ELEMENT_INIT - DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new - element. E is of type DYNARRAY_ELEMENT *. - If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is - defined, new elements are automatically zero-initialized. - Otherwise, new elements have undefined contents. - DYNARRAY_INITIAL_SIZE - The size of the statically allocated array (default: - at least 2, more elements if they fit into 128 bytes). - Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, - there is no statically allocated array at, and all non-empty - arrays are heap-allocated. - DYNARRAY_FINAL_TYPE - The name of the type which holds the final array. If not - defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE - must be a struct type, with members of type DYNARRAY_ELEMENT and - size_t at the start (in this order). - - These macros are undefined after this header file has been - included. - - The following types are provided (their members are private to the - dynarray implementation): - - struct DYNARRAY_STRUCT - - The following functions are provided: - - void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *); - bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *); - size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t); - void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *); - bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t); - void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *); - - The following functions are provided are provided if the - prerequisites are met: - - bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, - DYNARRAY_FINAL_TYPE *); - (if DYNARRAY_FINAL_TYPE is defined) - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, - size_t *); - (if DYNARRAY_FINAL_TYPE is not defined) -*/ - -#include - -#include -#include -#include - -#ifndef DYNARRAY_STRUCT -# error "DYNARRAY_STRUCT must be defined" -#endif - -#ifndef DYNARRAY_ELEMENT -# error "DYNARRAY_ELEMENT must be defined" -#endif - -#ifndef DYNARRAY_PREFIX -# error "DYNARRAY_PREFIX must be defined" -#endif - -#ifdef DYNARRAY_INITIAL_SIZE -# if DYNARRAY_INITIAL_SIZE < 0 -# error "DYNARRAY_INITIAL_SIZE must be non-negative" -# endif -# if DYNARRAY_INITIAL_SIZE > 0 -# define DYNARRAY_HAVE_SCRATCH 1 -# else -# define DYNARRAY_HAVE_SCRATCH 0 -# endif -#else -/* Provide a reasonable default which limits the size of - DYNARRAY_STRUCT. */ -# define DYNARRAY_INITIAL_SIZE \ - (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT)) -# define DYNARRAY_HAVE_SCRATCH 1 -#endif - -/* Public type definitions. */ - -/* All fields of this struct are private to the implementation. */ -struct DYNARRAY_STRUCT -{ - union - { - struct dynarray_header dynarray_abstract; - struct - { - /* These fields must match struct dynarray_header. */ - size_t used; - size_t allocated; - DYNARRAY_ELEMENT *array; - } dynarray_header; - } u; - -#if DYNARRAY_HAVE_SCRATCH - /* Initial inline allocation. */ - DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE]; -#endif -}; - -/* Internal use only: Helper macros. */ - -/* Ensure macro-expansion of DYNARRAY_PREFIX. */ -#define DYNARRAY_CONCAT0(prefix, name) prefix##name -#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name) -#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name) - -/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free), - so that Gnulib does not change 'free' to 'rpl_free'. */ -#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree) - -/* Address of the scratch buffer if any. */ -#if DYNARRAY_HAVE_SCRATCH -# define DYNARRAY_SCRATCH(list) (list)->scratch -#else -# define DYNARRAY_SCRATCH(list) NULL -#endif - -/* Internal use only: Helper functions. */ - -/* Internal function. Call DYNARRAY_ELEMENT_FREE with the array - elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE - macro expansion. */ -static inline void -DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array, - size_t __dynarray_used) -{ -#ifdef DYNARRAY_ELEMENT_FREE - for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i) - DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]); -#endif /* DYNARRAY_ELEMENT_FREE */ -} - -/* Internal function. Free the non-scratch array allocation. */ -static inline void -DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list) -{ -#if DYNARRAY_HAVE_SCRATCH - if (list->u.dynarray_header.array != list->scratch) - free (list->u.dynarray_header.array); -#else - free (list->u.dynarray_header.array); -#endif -} - -/* Public functions. */ - -/* Initialize a dynamic array object. This must be called before any - use of the object. */ -__attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list) -{ - list->u.dynarray_header.used = 0; - list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE; - list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); -} - -/* Deallocate the dynamic array and its elements. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_FREE (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - DYNARRAY_NAME (free__array__) (list); - DYNARRAY_NAME (init) (list); -} - -/* Return true if the dynamic array is in an error state. */ -__attribute_nonnull__ ((1)) -static inline bool -DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.allocated == __dynarray_error_marker (); -} - -/* Mark the dynamic array as failed. All elements are deallocated as - a side effect. */ -__attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - DYNARRAY_NAME (free__array__) (list); - list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); - list->u.dynarray_header.used = 0; - list->u.dynarray_header.allocated = __dynarray_error_marker (); -} - -/* Return the number of elements which have been added to the dynamic - array. */ -__attribute_nonnull__ ((1)) -static inline size_t -DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.used; -} - -/* Return a pointer to the array element at INDEX. Terminate the - process if INDEX is out of bounds. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index) -{ - if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list))) - __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index); - return list->u.dynarray_header.array + index; -} - -/* Return a pointer to the first array element, if any. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.array; -} - -/* Return a pointer one element past the last array element. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.array + list->u.dynarray_header.used; -} - -/* Internal function. Slow path for the add function below. */ -static void -DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) -{ - if (__glibc_unlikely - (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)))) - { - DYNARRAY_NAME (mark_failed) (list); - return; - } - - /* Copy the new element and increase the array length. */ - list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; -} - -/* Add ITEM at the end of the array, enlarging it by one element. - Mark *LIST as failed if the dynamic array allocation size cannot be - increased. */ -__attribute_nonnull__ ((1)) -static inline void -DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) -{ - /* Do nothing in case of previous error. */ - if (DYNARRAY_NAME (has_failed) (list)) - return; - - /* Enlarge the array if necessary. */ - if (__glibc_unlikely (list->u.dynarray_header.used - == list->u.dynarray_header.allocated)) - { - DYNARRAY_NAME (add__) (list, item); - return; - } - - /* Copy the new element and increase the array length. */ - list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; -} - -/* Internal function. Building block for the emplace functions below. - Assumes space for one more element in *LIST. */ -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_ELEMENT *result - = &list->u.dynarray_header.array[list->u.dynarray_header.used]; - ++list->u.dynarray_header.used; -#if defined (DYNARRAY_ELEMENT_INIT) - DYNARRAY_ELEMENT_INIT (result); -#elif defined (DYNARRAY_ELEMENT_FREE) - memset (result, 0, sizeof (*result)); -#endif - return result; -} - -/* Internal function. Slow path for the emplace function below. */ -static DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list) -{ - if (__glibc_unlikely - (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)))) - { - DYNARRAY_NAME (mark_failed) (list); - return NULL; - } - return DYNARRAY_NAME (emplace__tail__) (list); -} - -/* Allocate a place for a new element in *LIST and return a pointer to - it. The pointer can be NULL if the dynamic array cannot be - enlarged due to a memory allocation failure. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1)) -static -/* Avoid inlining with the larger initialization code. */ -#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE)) -inline -#endif -DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list) -{ - /* Do nothing in case of previous error. */ - if (DYNARRAY_NAME (has_failed) (list)) - return NULL; - - /* Enlarge the array if necessary. */ - if (__glibc_unlikely (list->u.dynarray_header.used - == list->u.dynarray_header.allocated)) - return (DYNARRAY_NAME (emplace__) (list)); - return DYNARRAY_NAME (emplace__tail__) (list); -} - -/* Change the size of *LIST to SIZE. If SIZE is larger than the - existing size, new elements are added (which can be initialized). - Otherwise, the list is truncated, and elements are freed. Return - false on memory allocation failure (and mark *LIST as failed). */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static bool -DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size) -{ - if (size > list->u.dynarray_header.used) - { - bool ok; -#if defined (DYNARRAY_ELEMENT_INIT) - /* The new elements have to be initialized. */ - size_t old_size = list->u.dynarray_header.used; - ok = __libc_dynarray_resize (&list->u.dynarray_abstract, - size, DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)); - if (ok) - for (size_t i = old_size; i < size; ++i) - { - DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]); - } -#elif defined (DYNARRAY_ELEMENT_FREE) - /* Zero initialization is needed so that the elements can be - safely freed. */ - ok = __libc_dynarray_resize_clear - (&list->u.dynarray_abstract, size, - DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT)); -#else - ok = __libc_dynarray_resize (&list->u.dynarray_abstract, - size, DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)); -#endif - if (__glibc_unlikely (!ok)) - DYNARRAY_NAME (mark_failed) (list); - return ok; - } - else - { - /* The list has shrunk in size. Free the removed elements. */ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array + size, - list->u.dynarray_header.used - size); - list->u.dynarray_header.used = size; - return true; - } -} - -/* Remove the last element of LIST if it is present. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list) -{ - /* used > 0 implies that the array is the non-failed state. */ - if (list->u.dynarray_header.used > 0) - { - size_t new_length = list->u.dynarray_header.used - 1; -#ifdef DYNARRAY_ELEMENT_FREE - DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]); -#endif - list->u.dynarray_header.used = new_length; - } -} - -/* Remove all elements from the list. The elements are freed, but the - list itself is not. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list) -{ - /* free__elements__ does nothing if the list is in the failed - state. */ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - list->u.dynarray_header.used = 0; -} - -#ifdef DYNARRAY_FINAL_TYPE -/* Transfer the dynamic array to a permanent location at *RESULT. - Returns true on success on false on allocation failure. In either - case, *LIST is re-initialized and can be reused. A NULL pointer is - stored in *RESULT if LIST refers to an empty list. On success, the - pointer in *RESULT is heap-allocated and must be deallocated using - free. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1, 2)) -static bool -DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, - DYNARRAY_FINAL_TYPE *result) -{ - struct dynarray_finalize_result res; - if (__libc_dynarray_finalize (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT), &res)) - { - /* On success, the result owns all the data. */ - DYNARRAY_NAME (init) (list); - *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length }; - return true; - } - else - { - /* On error, we need to free all data. */ - DYNARRAY_FREE (list); - errno = ENOMEM; - return false; - } -} -#else /* !DYNARRAY_FINAL_TYPE */ -/* Transfer the dynamic array to a heap-allocated array and return a - pointer to it. The pointer is NULL if memory allocation fails, or - if the array is empty, so this function should be used only for - arrays which are known not be empty (usually because they always - have a sentinel at the end). If LENGTHP is not NULL, the array - length is written to *LENGTHP. *LIST is re-initialized and can be - reused. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1)) -static DYNARRAY_ELEMENT * -DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp) -{ - struct dynarray_finalize_result res; - if (__libc_dynarray_finalize (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT), &res)) - { - /* On success, the result owns all the data. */ - DYNARRAY_NAME (init) (list); - if (lengthp != NULL) - *lengthp = res.length; - return res.array; - } - else - { - /* On error, we need to free all data. */ - DYNARRAY_FREE (list); - errno = ENOMEM; - return NULL; - } -} -#endif /* !DYNARRAY_FINAL_TYPE */ - -/* Undo macro definitions. */ - -#undef DYNARRAY_CONCAT0 -#undef DYNARRAY_CONCAT1 -#undef DYNARRAY_NAME -#undef DYNARRAY_SCRATCH -#undef DYNARRAY_HAVE_SCRATCH - -#undef DYNARRAY_STRUCT -#undef DYNARRAY_ELEMENT -#undef DYNARRAY_PREFIX -#undef DYNARRAY_ELEMENT_FREE -#undef DYNARRAY_ELEMENT_INIT -#undef DYNARRAY_INITIAL_SIZE -#undef DYNARRAY_FINAL_TYPE diff --git a/xcompile/lib/malloc/dynarray.h b/xcompile/lib/malloc/dynarray.h deleted file mode 100644 index a9a3b0859c1..00000000000 --- a/xcompile/lib/malloc/dynarray.h +++ /dev/null @@ -1,177 +0,0 @@ -/* Type-safe arrays which grow dynamically. Shared definitions. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* To use the dynarray facility, you need to include - and define the parameter macros - documented in that file. - - A minimal example which provides a growing list of integers can be - defined like this: - - struct int_array - { - // Pointer to result array followed by its length, - // as required by DYNARRAY_FINAL_TYPE. - int *array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_int - #define DYNARRAY_ELEMENT int - #define DYNARRAY_PREFIX dynarray_int_ - #define DYNARRAY_FINAL_TYPE struct int_array - #include - - To create a three-element array with elements 1, 2, 3, use this - code: - - struct dynarray_int dyn; - dynarray_int_init (&dyn); - for (int i = 1; i <= 3; ++i) - { - int *place = dynarray_int_emplace (&dyn); - assert (place != NULL); - *place = i; - } - struct int_array result; - bool ok = dynarray_int_finalize (&dyn, &result); - assert (ok); - assert (result.length == 3); - assert (result.array[0] == 1); - assert (result.array[1] == 2); - assert (result.array[2] == 3); - free (result.array); - - If the elements contain resources which must be freed, define - DYNARRAY_ELEMENT_FREE appropriately, like this: - - struct str_array - { - char **array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_str - #define DYNARRAY_ELEMENT char * - #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) - #define DYNARRAY_PREFIX dynarray_str_ - #define DYNARRAY_FINAL_TYPE struct str_array - #include - - Compared to scratch buffers, dynamic arrays have the following - features: - - - They have an element type, and are not just an untyped buffer of - bytes. - - - When growing, previously stored elements are preserved. (It is - expected that scratch_buffer_grow_preserve and - scratch_buffer_set_array_size eventually go away because all - current users are moved to dynamic arrays.) - - - Scratch buffers have a more aggressive growth policy because - growing them typically means a retry of an operation (across an - NSS service module boundary), which is expensive. - - - For the same reason, scratch buffers have a much larger initial - stack allocation. */ - -#ifndef _DYNARRAY_H -#define _DYNARRAY_H - -#include -#include - -struct dynarray_header -{ - size_t used; - size_t allocated; - void *array; -}; - -/* Marker used in the allocated member to indicate that an error was - encountered. */ -static inline size_t -__dynarray_error_marker (void) -{ - return -1; -} - -/* Internal function. See the has_failed function in - dynarray-skeleton.c. */ -static inline bool -__dynarray_error (struct dynarray_header *list) -{ - return list->allocated == __dynarray_error_marker (); -} - -/* Internal function. Enlarge the dynamically allocated area of the - array to make room for one more element. SCRATCH is a pointer to - the scratch area (which is not heap-allocated and must not be - freed). ELEMENT_SIZE is the size, in bytes, of one element. - Return false on failure, true on success. */ -bool __libc_dynarray_emplace_enlarge (struct dynarray_header *, - void *scratch, size_t element_size); - -/* Internal function. Enlarge the dynamically allocated area of the - array to make room for at least SIZE elements (which must be larger - than the existing used part of the dynamic array). SCRATCH is a - pointer to the scratch area (which is not heap-allocated and must - not be freed). ELEMENT_SIZE is the size, in bytes, of one element. - Return false on failure, true on success. */ -bool __libc_dynarray_resize (struct dynarray_header *, size_t size, - void *scratch, size_t element_size); - -/* Internal function. Like __libc_dynarray_resize, but clear the new - part of the dynamic array. */ -bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size, - void *scratch, size_t element_size); - -/* Internal type. */ -struct dynarray_finalize_result -{ - void *array; - size_t length; -}; - -/* Internal function. Copy the dynamically-allocated area to an - explicitly-sized heap allocation. SCRATCH is a pointer to the - embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the - element type. On success, true is returned, and pointer and length - are written to *RESULT. On failure, false is returned. The caller - has to take care of some of the memory management; this function is - expected to be called from dynarray-skeleton.c. */ -bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch, - size_t element_size, - struct dynarray_finalize_result *result); - - -/* Internal function. Terminate the process after an index error. - SIZE is the number of elements of the dynamic array. INDEX is the - lookup index which triggered the failure. */ -_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index); - -#ifndef _ISOMAC -libc_hidden_proto (__libc_dynarray_emplace_enlarge) -libc_hidden_proto (__libc_dynarray_resize) -libc_hidden_proto (__libc_dynarray_resize_clear) -libc_hidden_proto (__libc_dynarray_finalize) -libc_hidden_proto (__libc_dynarray_at_failure) -#endif - -#endif /* _DYNARRAY_H */ diff --git a/xcompile/lib/malloc/dynarray_at_failure.c b/xcompile/lib/malloc/dynarray_at_failure.c deleted file mode 100644 index ebc9310982c..00000000000 --- a/xcompile/lib/malloc/dynarray_at_failure.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Report an dynamic array index out of bounds condition. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -# include -#endif - -#include -#include - -void -__libc_dynarray_at_failure (size_t size, size_t index) -{ -#ifdef _LIBC - char buf[200]; - __snprintf (buf, sizeof (buf), "Fatal glibc error: " - "array index %zu not less than array length %zu\n", - index, size); - __libc_fatal (buf); -#else - abort (); -#endif -} -libc_hidden_def (__libc_dynarray_at_failure) diff --git a/xcompile/lib/malloc/dynarray_emplace_enlarge.c b/xcompile/lib/malloc/dynarray_emplace_enlarge.c deleted file mode 100644 index 7da539316c1..00000000000 --- a/xcompile/lib/malloc/dynarray_emplace_enlarge.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Increase the size of a dynamic array in preparation of an emplace operation. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include -#include -#include - -bool -__libc_dynarray_emplace_enlarge (struct dynarray_header *list, - void *scratch, size_t element_size) -{ - size_t new_allocated; - if (list->allocated == 0) - { - /* No scratch buffer provided. Choose a reasonable default - size. */ - if (element_size < 4) - new_allocated = 16; - else if (element_size < 8) - new_allocated = 8; - else - new_allocated = 4; - } - else - /* Increase the allocated size, using an exponential growth - policy. */ - { - new_allocated = list->allocated + list->allocated / 2 + 1; - if (new_allocated <= list->allocated) - { - /* Overflow. */ - __set_errno (ENOMEM); - return false; - } - } - - size_t new_size; - if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size)) - return false; - void *new_array; - if (list->array == scratch) - { - /* The previous array was not heap-allocated. */ - new_array = malloc (new_size); - if (new_array != NULL && list->array != NULL) - memcpy (new_array, list->array, list->used * element_size); - } - else - new_array = realloc (list->array, new_size); - if (new_array == NULL) - return false; - list->array = new_array; - list->allocated = new_allocated; - return true; -} -libc_hidden_def (__libc_dynarray_emplace_enlarge) diff --git a/xcompile/lib/malloc/dynarray_finalize.c b/xcompile/lib/malloc/dynarray_finalize.c deleted file mode 100644 index 673595a5fad..00000000000 --- a/xcompile/lib/malloc/dynarray_finalize.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copy the dynamically-allocated area to an explicitly-sized heap allocation. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_dynarray_finalize (struct dynarray_header *list, - void *scratch, size_t element_size, - struct dynarray_finalize_result *result) -{ - if (__dynarray_error (list)) - /* The caller will reported the deferred error. */ - return false; - - size_t used = list->used; - - /* Empty list. */ - if (used == 0) - { - /* An empty list could still be backed by a heap-allocated - array. Free it if necessary. */ - if (list->array != scratch) - free (list->array); - *result = (struct dynarray_finalize_result) { NULL, 0 }; - return true; - } - - size_t allocation_size = used * element_size; - void *heap_array = malloc (allocation_size); - if (heap_array != NULL) - { - /* The new array takes ownership of the strings. */ - if (list->array != NULL) - memcpy (heap_array, list->array, allocation_size); - if (list->array != scratch) - free (list->array); - *result = (struct dynarray_finalize_result) - { .array = heap_array, .length = used }; - return true; - } - else - /* The caller will perform the freeing operation. */ - return false; -} -libc_hidden_def (__libc_dynarray_finalize) diff --git a/xcompile/lib/malloc/dynarray_resize.c b/xcompile/lib/malloc/dynarray_resize.c deleted file mode 100644 index 7ecd4de63b9..00000000000 --- a/xcompile/lib/malloc/dynarray_resize.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Increase the size of a dynamic array. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include -#include -#include - -bool -__libc_dynarray_resize (struct dynarray_header *list, size_t size, - void *scratch, size_t element_size) -{ - /* The existing allocation provides sufficient room. */ - if (size <= list->allocated) - { - list->used = size; - return true; - } - - /* Otherwise, use size as the new allocation size. The caller is - expected to provide the final size of the array, so there is no - over-allocation here. */ - - size_t new_size_bytes; - if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes)) - { - /* Overflow. */ - __set_errno (ENOMEM); - return false; - } - void *new_array; - if (list->array == scratch) - { - /* The previous array was not heap-allocated. */ - new_array = malloc (new_size_bytes); - if (new_array != NULL && list->array != NULL) - memcpy (new_array, list->array, list->used * element_size); - } - else - new_array = realloc (list->array, new_size_bytes); - if (new_array == NULL) - return false; - list->array = new_array; - list->allocated = size; - list->used = size; - return true; -} -libc_hidden_def (__libc_dynarray_resize) diff --git a/xcompile/lib/malloc/dynarray_resize_clear.c b/xcompile/lib/malloc/dynarray_resize_clear.c deleted file mode 100644 index bb23c522a14..00000000000 --- a/xcompile/lib/malloc/dynarray_resize_clear.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Increase the size of a dynamic array and clear the new part. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -bool -__libc_dynarray_resize_clear (struct dynarray_header *list, size_t size, - void *scratch, size_t element_size) -{ - size_t old_size = list->used; - if (!__libc_dynarray_resize (list, size, scratch, element_size)) - return false; - /* __libc_dynarray_resize already checked for overflow. */ - char *array = list->array; - memset (array + (old_size * element_size), 0, - (size - old_size) * element_size); - return true; -} -libc_hidden_def (__libc_dynarray_resize_clear) diff --git a/xcompile/lib/malloc/scratch_buffer.h b/xcompile/lib/malloc/scratch_buffer.h deleted file mode 100644 index 33fd2b29cd5..00000000000 --- a/xcompile/lib/malloc/scratch_buffer.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _SCRATCH_BUFFER_H -#define _SCRATCH_BUFFER_H - -/* Scratch buffers with a default stack allocation and fallback to - heap allocation. It is expected that this function is used in this - way: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - return -1; - - scratch_buffer_free (&tmpbuf); - return 0; - - The allocation functions (scratch_buffer_grow, - scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make - sure that the heap allocation, if any, is freed, so that the code - above does not have a memory leak. The buffer still remains in a - state that can be deallocated using scratch_buffer_free, so a loop - like this is valid as well: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - break; - - scratch_buffer_free (&tmpbuf); - - scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed - to grow the buffer by at least 512 bytes. This means that when - using the scratch buffer as a backing store for a non-character - array whose element size, in bytes, is 512 or smaller, the scratch - buffer only has to grow once to make room for at least one more - element. -*/ - -#include -#include -#include - -/* Scratch buffer. Must be initialized with scratch_buffer_init - before its use. */ -struct scratch_buffer { - void *data; /* Pointer to the beginning of the scratch area. */ - size_t length; /* Allocated space at the data pointer, in bytes. */ - union { max_align_t __align; char __c[1024]; } __space; -}; - -/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space - and BUFFER->length reflects the available space. */ -static inline void -scratch_buffer_init (struct scratch_buffer *buffer) -{ - buffer->data = buffer->__space.__c; - buffer->length = sizeof (buffer->__space); -} - -/* Deallocates *BUFFER (if it was heap-allocated). */ -static inline void -scratch_buffer_free (struct scratch_buffer *buffer) -{ - if (buffer->data != buffer->__space.__c) - free (buffer->data); -} - -/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT - preserved. Return true on success, false on allocation failure (in - which case the old buffer is freed). On success, the new buffer is - larger than the previous size. On failure, *BUFFER is deallocated, - but remains in a free-able state, and errno is set. */ -bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer); -libc_hidden_proto (__libc_scratch_buffer_grow) - -/* Alias for __libc_scratch_buffer_grow. */ -static __always_inline bool -scratch_buffer_grow (struct scratch_buffer *buffer) -{ - return __glibc_likely (__libc_scratch_buffer_grow (buffer)); -} - -/* Like __libc_scratch_buffer_grow, but preserve the old buffer - contents on success, as a prefix of the new buffer. */ -bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer); -libc_hidden_proto (__libc_scratch_buffer_grow_preserve) - -/* Alias for __libc_scratch_buffer_grow_preserve. */ -static __always_inline bool -scratch_buffer_grow_preserve (struct scratch_buffer *buffer) -{ - return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer)); -} - -/* Grow *BUFFER so that it can store at least NELEM elements of SIZE - bytes. The buffer contents are NOT preserved. Both NELEM and SIZE - can be zero. Return true on success, false on allocation failure - (in which case the old buffer is freed, but *BUFFER remains in a - free-able state, and errno is set). It is unspecified whether this - function can reduce the array size. */ -bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size); -libc_hidden_proto (__libc_scratch_buffer_set_array_size) - -/* Alias for __libc_scratch_set_array_size. */ -static __always_inline bool -scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size) -{ - return __glibc_likely (__libc_scratch_buffer_set_array_size - (buffer, nelem, size)); -} - -#endif /* _SCRATCH_BUFFER_H */ diff --git a/xcompile/lib/malloc/scratch_buffer_dupfree.c b/xcompile/lib/malloc/scratch_buffer_dupfree.c deleted file mode 100644 index 2f60fbb54e8..00000000000 --- a/xcompile/lib/malloc/scratch_buffer_dupfree.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2020-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -void * -__libc_scratch_buffer_dupfree (struct scratch_buffer *buffer, size_t size) -{ - void *data = buffer->data; - if (data == buffer->__space.__c) - { - void *copy = malloc (size); - return copy != NULL ? memcpy (copy, data, size) : NULL; - } - else - { - void *copy = realloc (data, size); - return copy != NULL ? copy : data; - } -} -libc_hidden_def (__libc_scratch_buffer_dupfree) diff --git a/xcompile/lib/malloc/scratch_buffer_grow.c b/xcompile/lib/malloc/scratch_buffer_grow.c deleted file mode 100644 index a5e8f2f7230..00000000000 --- a/xcompile/lib/malloc/scratch_buffer_grow.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -bool -__libc_scratch_buffer_grow (struct scratch_buffer *buffer) -{ - void *new_ptr; - size_t new_length = buffer->length * 2; - - /* Discard old buffer. */ - scratch_buffer_free (buffer); - - /* Check for overflow. */ - if (__glibc_likely (new_length >= buffer->length)) - new_ptr = malloc (new_length); - else - { - __set_errno (ENOMEM); - new_ptr = NULL; - } - - if (__glibc_unlikely (new_ptr == NULL)) - { - /* Buffer must remain valid to free. */ - scratch_buffer_init (buffer); - return false; - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_grow) diff --git a/xcompile/lib/malloc/scratch_buffer_grow_preserve.c b/xcompile/lib/malloc/scratch_buffer_grow_preserve.c deleted file mode 100644 index c0b5d87b7e4..00000000000 --- a/xcompile/lib/malloc/scratch_buffer_grow_preserve.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer) -{ - size_t new_length = 2 * buffer->length; - void *new_ptr; - - if (buffer->data == buffer->__space.__c) - { - /* Move buffer to the heap. No overflow is possible because - buffer->length describes a small buffer on the stack. */ - new_ptr = malloc (new_length); - if (new_ptr == NULL) - return false; - memcpy (new_ptr, buffer->__space.__c, buffer->length); - } - else - { - /* Buffer was already on the heap. Check for overflow. */ - if (__glibc_likely (new_length >= buffer->length)) - new_ptr = realloc (buffer->data, new_length); - else - { - __set_errno (ENOMEM); - new_ptr = NULL; - } - - if (__glibc_unlikely (new_ptr == NULL)) - { - /* Deallocate, but buffer must remain valid to free. */ - free (buffer->data); - scratch_buffer_init (buffer); - return false; - } - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_grow_preserve) diff --git a/xcompile/lib/malloc/scratch_buffer_set_array_size.c b/xcompile/lib/malloc/scratch_buffer_set_array_size.c deleted file mode 100644 index 24c39350ade..00000000000 --- a/xcompile/lib/malloc/scratch_buffer_set_array_size.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size) -{ - size_t new_length = nelem * size; - - /* Avoid overflow check if both values are small. */ - if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0 - && nelem != 0 && size != new_length / nelem) - { - /* Overflow. Discard the old buffer, but it must remain valid - to free. */ - scratch_buffer_free (buffer); - scratch_buffer_init (buffer); - __set_errno (ENOMEM); - return false; - } - - if (new_length <= buffer->length) - return true; - - /* Discard old buffer. */ - scratch_buffer_free (buffer); - - char *new_ptr = malloc (new_length); - if (new_ptr == NULL) - { - /* Buffer must remain valid to free. */ - scratch_buffer_init (buffer); - return false; - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_set_array_size) diff --git a/xcompile/lib/md5-stream.c b/xcompile/lib/md5-stream.c deleted file mode 100644 index ba76792cbbe..00000000000 --- a/xcompile/lib/md5-stream.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Functions to compute MD5 message digest of files or memory blocks. - according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Ulrich Drepper , 1995. */ - -#include - -/* Specification. */ -#if HAVE_OPENSSL_MD5 -# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE -#endif -#include "md5.h" - -#include - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#include "af_alg.h" - -#ifdef _LIBC -# include -# if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -/* We need to keep the namespace clean so define the MD5 function - protected using leading __ . */ -# define md5_init_ctx __md5_init_ctx -# define md5_process_block __md5_process_block -# define md5_process_bytes __md5_process_bytes -# define md5_finish_ctx __md5_finish_ctx -# define md5_stream __md5_stream -#endif - -#define BLOCKSIZE 32768 -#if BLOCKSIZE % 64 != 0 -# error "invalid BLOCKSIZE" -#endif - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -int -md5_stream (FILE *stream, void *resblock) -{ - switch (afalg_stream (stream, "md5", resblock, MD5_DIGEST_SIZE)) - { - case 0: return 0; - case -EIO: return 1; - } - - char *buffer = malloc (BLOCKSIZE + 72); - if (!buffer) - return 1; - - struct md5_ctx ctx; - md5_init_ctx (&ctx); - size_t sum; - - /* Iterate over full file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - while (1) - { - /* Either process a partial fread() from this loop, - or the fread() in afalg_stream may have gotten EOF. - We need to avoid a subsequent fread() as EOF may - not be sticky. For details of such systems, see: - https://sourceware.org/bugzilla/show_bug.cgi?id=1190 */ - if (feof (stream)) - goto process_partial_block; - - n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - - if (sum == BLOCKSIZE) - break; - - if (n == 0) - { - /* Check for the error flag IFF N == 0, so that we don't - exit the loop after a partial read due to e.g., EAGAIN - or EWOULDBLOCK. */ - if (ferror (stream)) - { - free (buffer); - return 1; - } - goto process_partial_block; - } - } - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - md5_process_block (buffer, BLOCKSIZE, &ctx); - } - -process_partial_block: - - /* Process any remaining bytes. */ - if (sum > 0) - md5_process_bytes (buffer, sum, &ctx); - - /* Construct result in desired memory. */ - md5_finish_ctx (&ctx, resblock); - free (buffer); - return 0; -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/md5.c b/xcompile/lib/md5.c deleted file mode 100644 index 4a6accf28ff..00000000000 --- a/xcompile/lib/md5.c +++ /dev/null @@ -1,394 +0,0 @@ -/* Functions to compute MD5 message digest of files or memory blocks. - according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Ulrich Drepper , 1995. */ - -#include - -/* Specification. */ -#if HAVE_OPENSSL_MD5 -# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE -#endif -#include "md5.h" - -#include -#include -#include - -#ifdef _LIBC -# include -# if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -/* We need to keep the namespace clean so define the MD5 function - protected using leading __ . */ -# define md5_init_ctx __md5_init_ctx -# define md5_process_block __md5_process_block -# define md5_process_bytes __md5_process_bytes -# define md5_finish_ctx __md5_finish_ctx -# define md5_read_ctx __md5_read_ctx -# define md5_buffer __md5_buffer -#endif - -#include -#ifdef WORDS_BIGENDIAN -# define SWAP(n) bswap_32 (n) -#else -# define SWAP(n) (n) -#endif - -#if ! HAVE_OPENSSL_MD5 - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -void -md5_init_ctx (struct md5_ctx *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the 4 byte value from v into the memory location pointed to by *cp, - If your architecture allows unaligned access this is equivalent to - * (uint32_t *) cp = v */ -static void -set_uint32 (char *cp, uint32_t v) -{ - memcpy (cp, &v, sizeof v); -} - -/* Put result from CTX in first 16 bytes following RESBUF. The result - must be in little endian byte order. */ -void * -md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) -{ - char *r = resbuf; - set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); - set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); - set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); - set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -void * -md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) -{ - /* Take yet unprocessed bytes into account. */ - uint32_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer[size - 2] = SWAP (ctx->total[0] << 3); - ctx->buffer[size - 1] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - - memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); - - /* Process last bytes. */ - md5_process_block (ctx->buffer, size * 4, ctx); - - return md5_read_ctx (ctx, resbuf); -} - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -md5_buffer (const char *buffer, size_t len, void *resblock) -{ - struct md5_ctx ctx; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return md5_finish_ctx (&ctx, resblock); -} - - -void -md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) - { - md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy (ctx->buffer, - &((char *) ctx->buffer)[(left_over + add) & ~63], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 64) - { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) - if (UNALIGNED_P (buffer)) - while (len > 64) - { - md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - else -#endif - { - md5_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - size_t left_over = ctx->buflen; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, len); - left_over += len; - if (left_over >= 64) - { - md5_process_block (ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy (ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ - -void -md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) -{ - uint32_t correct_words[16]; - const uint32_t *words = buffer; - size_t nwords = len / sizeof (uint32_t); - const uint32_t *endp = words + nwords; - uint32_t A = ctx->A; - uint32_t B = ctx->B; - uint32_t C = ctx->C; - uint32_t D = ctx->D; - uint32_t lolen = len; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) - { - uint32_t *cwp = correct_words; - uint32_t A_save = A; - uint32_t B_save = B; - uint32_t C_save = C; - uint32_t D_save = D; - - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ - ++words; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - - Here is an equivalent invocation using Perl: - - perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' - */ - - /* Round 1. */ - OP (A, B, C, D, 7, 0xd76aa478); - OP (D, A, B, C, 12, 0xe8c7b756); - OP (C, D, A, B, 17, 0x242070db); - OP (B, C, D, A, 22, 0xc1bdceee); - OP (A, B, C, D, 7, 0xf57c0faf); - OP (D, A, B, C, 12, 0x4787c62a); - OP (C, D, A, B, 17, 0xa8304613); - OP (B, C, D, A, 22, 0xfd469501); - OP (A, B, C, D, 7, 0x698098d8); - OP (D, A, B, C, 12, 0x8b44f7af); - OP (C, D, A, B, 17, 0xffff5bb1); - OP (B, C, D, A, 22, 0x895cd7be); - OP (A, B, C, D, 7, 0x6b901122); - OP (D, A, B, C, 12, 0xfd987193); - OP (C, D, A, B, 17, 0xa679438e); - OP (B, C, D, A, 22, 0x49b40821); - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ - OP (FG, A, B, C, D, 1, 5, 0xf61e2562); - OP (FG, D, A, B, C, 6, 9, 0xc040b340); - OP (FG, C, D, A, B, 11, 14, 0x265e5a51); - OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP (FG, A, B, C, D, 5, 5, 0xd62f105d); - OP (FG, D, A, B, C, 10, 9, 0x02441453); - OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP (FG, D, A, B, C, 14, 9, 0xc33707d6); - OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP (FG, B, C, D, A, 8, 20, 0x455a14ed); - OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP (FG, C, D, A, B, 7, 14, 0x676f02d9); - OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); - - /* Round 3. */ - OP (FH, A, B, C, D, 5, 4, 0xfffa3942); - OP (FH, D, A, B, C, 8, 11, 0x8771f681); - OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP (FH, B, C, D, A, 14, 23, 0xfde5380c); - OP (FH, A, B, C, D, 1, 4, 0xa4beea44); - OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP (FH, B, C, D, A, 6, 23, 0x04881d05); - OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); - - /* Round 4. */ - OP (FI, A, B, C, D, 0, 6, 0xf4292244); - OP (FI, D, A, B, C, 7, 10, 0x432aff97); - OP (FI, C, D, A, B, 14, 15, 0xab9423a7); - OP (FI, B, C, D, A, 5, 21, 0xfc93a039); - OP (FI, A, B, C, D, 12, 6, 0x655b59c3); - OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP (FI, C, D, A, B, 10, 15, 0xffeff47d); - OP (FI, B, C, D, A, 1, 21, 0x85845dd1); - OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP (FI, C, D, A, B, 6, 15, 0xa3014314); - OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP (FI, A, B, C, D, 4, 6, 0xf7537e82); - OP (FI, D, A, B, C, 11, 10, 0xbd3af235); - OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP (FI, B, C, D, A, 9, 21, 0xeb86d391); - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/md5.h b/xcompile/lib/md5.h deleted file mode 100644 index f34e7cb8dfa..00000000000 --- a/xcompile/lib/md5.h +++ /dev/null @@ -1,151 +0,0 @@ -/* Declaration of functions and data types used for MD5 sum computing - library functions. - Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2023 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _MD5_H -#define _MD5_H 1 - -#include -#include - -# if HAVE_OPENSSL_MD5 -# ifndef OPENSSL_API_COMPAT -# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ -# endif -# include -# endif - -#define MD5_DIGEST_SIZE 16 -#define MD5_BLOCK_SIZE 64 - -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -# else -# define __GNUC_PREREQ(maj, min) 0 -# endif -#endif - -#ifndef __THROW -# if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major__ >= 4) -# define __THROW throw () -# else -# define __THROW -# endif -#endif - -#ifndef _LIBC -# define __md5_buffer md5_buffer -# define __md5_finish_ctx md5_finish_ctx -# define __md5_init_ctx md5_init_ctx -# define __md5_process_block md5_process_block -# define __md5_process_bytes md5_process_bytes -# define __md5_read_ctx md5_read_ctx -# define __md5_stream md5_stream -#endif - -# ifdef __cplusplus -extern "C" { -# endif - -# if HAVE_OPENSSL_MD5 -# define GL_OPENSSL_NAME 5 -# include "gl_openssl.h" -# else -/* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - - uint32_t total[2]; - uint32_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* - * The following three functions are build up the low level used in - * the functions 'md5_stream' and 'md5_buffer'. - */ - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void __md5_process_block (const void *buffer, size_t len, - struct md5_ctx *ctx) __THROW; - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void __md5_process_bytes (const void *buffer, size_t len, - struct md5_ctx *ctx) __THROW; - -/* Process the remaining bytes in the buffer and put result from CTX - in first 16 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *restrict resbuf) - __THROW; - - -/* Put result from CTX in first 16 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *restrict resbuf) - __THROW; - - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *__md5_buffer (const char *buffer, size_t len, - void *restrict resblock) __THROW; - -# endif - -/* Compute MD5 message digest for bytes read from STREAM. - STREAM is an open file stream. Regular files are handled more efficiently. - The contents of STREAM from its current position to its end will be read. - The case that the last operation on STREAM was an 'ungetc' is not supported. - The resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -extern int __md5_stream (FILE *stream, void *resblock) __THROW; - - -# ifdef __cplusplus -} -# endif - -#endif /* md5.h */ - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/memmem.c b/xcompile/lib/memmem.c deleted file mode 100644 index c0b48c1b25d..00000000000 --- a/xcompile/lib/memmem.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2023 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* This particular implementation was written by Eric Blake, 2008. */ - -#ifndef _LIBC -# include -#endif - -/* Specification of memmem. */ -#include - -#define RETURN_TYPE void * -#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l)) -#include "str-two-way.h" - -/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK - if NEEDLE_LEN is 0, otherwise NULL if NEEDLE is not found in - HAYSTACK. */ -void * -memmem (const void *haystack_start, size_t haystack_len, - const void *needle_start, size_t needle_len) -{ - /* Abstract memory is considered to be an array of 'unsigned char' values, - not an array of 'char' values. See ISO C 99 section 6.2.6.1. */ - const unsigned char *haystack = (const unsigned char *) haystack_start; - const unsigned char *needle = (const unsigned char *) needle_start; - - if (needle_len == 0) - /* The first occurrence of the empty string is deemed to occur at - the beginning of the string. */ - return (void *) haystack; - - /* Sanity check, otherwise the loop might search through the whole - memory. */ - if (__builtin_expect (haystack_len < needle_len, 0)) - return NULL; - - /* Use optimizations in memchr when possible, to reduce the search - size of haystack using a linear algorithm with a smaller - coefficient. However, avoid memchr for long needles, since we - can often achieve sublinear performance. */ - if (needle_len < LONG_NEEDLE_THRESHOLD) - { - haystack = memchr (haystack, *needle, haystack_len); - if (!haystack || __builtin_expect (needle_len == 1, 0)) - return (void *) haystack; - haystack_len -= haystack - (const unsigned char *) haystack_start; - if (haystack_len < needle_len) - return NULL; - return two_way_short_needle (haystack, haystack_len, needle, needle_len); - } - else - return two_way_long_needle (haystack, haystack_len, needle, needle_len); -} - -#undef LONG_NEEDLE_THRESHOLD diff --git a/xcompile/lib/mempcpy.c b/xcompile/lib/mempcpy.c deleted file mode 100644 index 24a3135988f..00000000000 --- a/xcompile/lib/mempcpy.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copy memory area and return pointer after last written byte. - Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* A function definition is only needed if HAVE_MEMPCPY is not defined. */ -#if !HAVE_MEMPCPY - -/* Copy N bytes of SRC to DEST, return pointer to bytes after the - last written byte. */ -void * -mempcpy (void *dest, const void *src, size_t n) -{ - return (char *) memcpy (dest, src, n) + n; -} - -#endif diff --git a/xcompile/lib/memrchr.c b/xcompile/lib/memrchr.c deleted file mode 100644 index c5b1fe8b2e3..00000000000 --- a/xcompile/lib/memrchr.c +++ /dev/null @@ -1,161 +0,0 @@ -/* memrchr -- find the last occurrence of a byte in a memory block - - Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2023 Free Software - Foundation, Inc. - - Based on strlen implementation by Torbjorn Granlund (tege@sics.se), - with help from Dan Sahlin (dan@sics.se) and - commentary by Jim Blandy (jimb@ai.mit.edu); - adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), - and implemented by Roland McGrath (roland@ai.mit.edu). - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#if defined _LIBC -# include -#else -# include -# define reg_char char -#endif - -#include -#include - -#undef __memrchr -#ifdef _LIBC -# undef memrchr -#endif - -#ifndef weak_alias -# define __memrchr memrchr -#endif - -/* Search no more than N bytes of S for C. */ -void * -__memrchr (void const *s, int c_in, size_t n) -{ - /* On 32-bit hardware, choosing longword to be a 32-bit unsigned - long instead of a 64-bit uintmax_t tends to give better - performance. On 64-bit hardware, unsigned long is generally 64 - bits already. Change this typedef to experiment with - performance. */ - typedef unsigned long int longword; - - const unsigned char *char_ptr; - const longword *longword_ptr; - longword repeated_one; - longword repeated_c; - unsigned reg_char c; - - c = (unsigned char) c_in; - - /* Handle the last few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s + n; - n > 0 && (size_t) char_ptr % sizeof (longword) != 0; - --n) - if (*--char_ptr == c) - return (void *) char_ptr; - - longword_ptr = (const void *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to any size longwords. */ - - /* Compute auxiliary longword values: - repeated_one is a value which has a 1 in every byte. - repeated_c has c in every byte. */ - repeated_one = 0x01010101; - repeated_c = c | (c << 8); - repeated_c |= repeated_c << 16; - if (0xffffffffU < (longword) -1) - { - repeated_one |= repeated_one << 31 << 1; - repeated_c |= repeated_c << 31 << 1; - if (8 < sizeof (longword)) - { - size_t i; - - for (i = 64; i < sizeof (longword) * 8; i *= 2) - { - repeated_one |= repeated_one << i; - repeated_c |= repeated_c << i; - } - } - } - - /* Instead of the traditional loop which tests each byte, we will test a - longword at a time. The tricky part is testing if *any of the four* - bytes in the longword in question are equal to c. We first use an xor - with repeated_c. This reduces the task to testing whether *any of the - four* bytes in longword1 is zero. - - We compute tmp = - ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). - That is, we perform the following operations: - 1. Subtract repeated_one. - 2. & ~longword1. - 3. & a mask consisting of 0x80 in every byte. - Consider what happens in each byte: - - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, - and step 3 transforms it into 0x80. A carry can also be propagated - to more significant bytes. - - If a byte of longword1 is nonzero, let its lowest 1 bit be at - position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, - the byte ends in a single bit of value 0 and k bits of value 1. - After step 2, the result is just k bits of value 1: 2^k - 1. After - step 3, the result is 0. And no carry is produced. - So, if longword1 has only non-zero bytes, tmp is zero. - Whereas if longword1 has a zero byte, call j the position of the least - significant zero byte. Then the result has a zero at positions 0, ..., - j-1 and a 0x80 at position j. We cannot predict the result at the more - significant bytes (positions j+1..3), but it does not matter since we - already have a non-zero bit at position 8*j+7. - - So, the test whether any byte in longword1 is zero is equivalent to - testing whether tmp is nonzero. */ - - while (n >= sizeof (longword)) - { - longword longword1 = *--longword_ptr ^ repeated_c; - - if ((((longword1 - repeated_one) & ~longword1) - & (repeated_one << 7)) != 0) - { - longword_ptr++; - break; - } - n -= sizeof (longword); - } - - char_ptr = (const unsigned char *) longword_ptr; - - /* At this point, we know that either n < sizeof (longword), or one of the - sizeof (longword) bytes starting at char_ptr is == c. On little-endian - machines, we could determine the first such byte without any further - memory accesses, just by looking at the tmp result from the last loop - iteration. But this does not work on big-endian machines. Choose code - that works in both cases. */ - - while (n-- > 0) - { - if (*--char_ptr == c) - return (void *) char_ptr; - } - - return NULL; -} -#ifdef weak_alias -weak_alias (__memrchr, memrchr) -#endif diff --git a/xcompile/lib/memset_explicit.c b/xcompile/lib/memset_explicit.c deleted file mode 100644 index 6d21a5e8797..00000000000 --- a/xcompile/lib/memset_explicit.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Erase sensitive data from memory. - Copyright 2022-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* memset_s need this define */ -#if HAVE_MEMSET_S -# define __STDC_WANT_LIB_EXT1__ 1 -#endif - -#include - -/* Set S's bytes to C, where S has LEN bytes. The compiler will not - optimize effects away, even if S is dead after the call. */ -void * -memset_explicit (void *s, int c, size_t len) -{ -#if HAVE_EXPLICIT_MEMSET - return explicit_memset (s, c, len); -#elif HAVE_MEMSET_S - (void) memset_s (s, len, c, len); - return s; -#elif defined __GNUC__ && !defined __clang__ - memset (s, c, len); - /* Compiler barrier. */ - __asm__ volatile ("" ::: "memory"); - return s; -#elif defined __clang__ - memset (s, c, len); - /* Compiler barrier. */ - /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the - whole thing is dead and eliminates it. Use 'g' to work around this - problem. See . */ - __asm__ volatile ("" : : "g"(s) : "memory"); - return s; -#else - /* Invoke memset through a volatile function pointer. This defeats compiler - optimizations. */ - void * (* const volatile volatile_memset) (void *, int, size_t) = memset; - return volatile_memset (s, c, len); -#endif -} diff --git a/xcompile/lib/min-max.h b/xcompile/lib/min-max.h deleted file mode 100644 index 997cdd191eb..00000000000 --- a/xcompile/lib/min-max.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef min -# define min(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef max -# define max(a,b) ((a) > (b) ? (a) : (b)) -#endif diff --git a/xcompile/lib/mini-gmp-gnulib.c b/xcompile/lib/mini-gmp-gnulib.c deleted file mode 100644 index b15ce0ff754..00000000000 --- a/xcompile/lib/mini-gmp-gnulib.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Tailor mini-gmp.c for Gnulib-using applications. - - Copyright 2018-2023 Free Software Foundation, Inc. - - This file is free software. - It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+". - You can redistribute it and/or modify it under either - - the terms of the GNU Lesser General Public License as published - by the Free Software Foundation, either version 3, or (at your - option) any later version, or - - the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) - any later version, or - - the same dual license "the GNU LGPLv3+ or the GNU GPLv2+". - - This file is distributed in the hope that 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 and the GNU General Public License - for more details. - - You should have received a copy of the GNU Lesser General Public - License and of the GNU General Public License along with this - program. If not, see . */ - -#include - -#include -#include - -#include "mini-gmp.h" - -/* Pacify GCC -Wsuggest-attribute=const, pure, malloc. */ -#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) -# pragma GCC diagnostic ignored "-Wsuggest-attribute=const" -# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" -#endif -#if 8 <= __GNUC__ -# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc" -#endif - -/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls. */ -#if (defined NDEBUG \ - && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || defined __clang__)) -# pragma GCC diagnostic ignored "-Wunused-variable" -#endif - -#include "mini-gmp.c" diff --git a/xcompile/lib/mini-gmp.c b/xcompile/lib/mini-gmp.c deleted file mode 100644 index ea037b801dc..00000000000 --- a/xcompile/lib/mini-gmp.c +++ /dev/null @@ -1,4620 +0,0 @@ -/* mini-gmp, a minimalistic implementation of a GNU GMP subset. - - Contributed to the GNU project by Niels Möller - Additional functionalities and improvements by Marco Bodrato. - -Copyright 1991-1997, 1999-2022 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP 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 General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -/* NOTE: All functions in this file which are not declared in - mini-gmp.h are internal, and are not intended to be compatible - with GMP or with future versions of mini-gmp. */ - -/* Much of the material copied from GMP files, including: gmp-impl.h, - longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c, - mpn/generic/lshift.c, mpn/generic/mul_1.c, - mpn/generic/mul_basecase.c, mpn/generic/rshift.c, - mpn/generic/sbpi1_div_qr.c, mpn/generic/sub_n.c, - mpn/generic/submul_1.c. */ - -#include -#include -#include -#include -#include -#include - -#include "mini-gmp.h" - -#if !defined(MINI_GMP_DONT_USE_FLOAT_H) -#include -#endif - - -/* Macros */ -#define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) - -#define GMP_LIMB_MAX ((mp_limb_t) ~ (mp_limb_t) 0) -#define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1)) - -#define GMP_HLIMB_BIT ((mp_limb_t) 1 << (GMP_LIMB_BITS / 2)) -#define GMP_LLIMB_MASK (GMP_HLIMB_BIT - 1) - -#define GMP_ULONG_BITS (sizeof(unsigned long) * CHAR_BIT) -#define GMP_ULONG_HIGHBIT ((unsigned long) 1 << (GMP_ULONG_BITS - 1)) - -#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) -#define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1)) - -#define GMP_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define GMP_MAX(a, b) ((a) > (b) ? (a) : (b)) - -#define GMP_CMP(a,b) (((a) > (b)) - ((a) < (b))) - -#if defined(DBL_MANT_DIG) && FLT_RADIX == 2 -#define GMP_DBL_MANT_BITS DBL_MANT_DIG -#else -#define GMP_DBL_MANT_BITS (53) -#endif - -/* Return non-zero if xp,xsize and yp,ysize overlap. - If xp+xsize<=yp there's no overlap, or if yp+ysize<=xp there's no - overlap. If both these are false, there's an overlap. */ -#define GMP_MPN_OVERLAP_P(xp, xsize, yp, ysize) \ - ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp)) - -#define gmp_assert_nocarry(x) do { \ - mp_limb_t __cy = (x); \ - assert (__cy == 0); \ - (void) (__cy); \ - } while (0) - -#define gmp_clz(count, x) do { \ - mp_limb_t __clz_x = (x); \ - unsigned __clz_c = 0; \ - int LOCAL_SHIFT_BITS = 8; \ - if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) \ - for (; \ - (__clz_x & ((mp_limb_t) 0xff << (GMP_LIMB_BITS - 8))) == 0; \ - __clz_c += 8) \ - { __clz_x <<= LOCAL_SHIFT_BITS; } \ - for (; (__clz_x & GMP_LIMB_HIGHBIT) == 0; __clz_c++) \ - __clz_x <<= 1; \ - (count) = __clz_c; \ - } while (0) - -#define gmp_ctz(count, x) do { \ - mp_limb_t __ctz_x = (x); \ - unsigned __ctz_c = 0; \ - gmp_clz (__ctz_c, __ctz_x & - __ctz_x); \ - (count) = GMP_LIMB_BITS - 1 - __ctz_c; \ - } while (0) - -#define gmp_add_ssaaaa(sh, sl, ah, al, bh, bl) \ - do { \ - mp_limb_t __x; \ - __x = (al) + (bl); \ - (sh) = (ah) + (bh) + (__x < (al)); \ - (sl) = __x; \ - } while (0) - -#define gmp_sub_ddmmss(sh, sl, ah, al, bh, bl) \ - do { \ - mp_limb_t __x; \ - __x = (al) - (bl); \ - (sh) = (ah) - (bh) - ((al) < (bl)); \ - (sl) = __x; \ - } while (0) - -#define gmp_umul_ppmm(w1, w0, u, v) \ - do { \ - int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; \ - if (sizeof(unsigned int) * CHAR_BIT >= 2 * GMP_LIMB_BITS) \ - { \ - unsigned int __ww = (unsigned int) (u) * (v); \ - w0 = (mp_limb_t) __ww; \ - w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \ - } \ - else if (GMP_ULONG_BITS >= 2 * GMP_LIMB_BITS) \ - { \ - unsigned long int __ww = (unsigned long int) (u) * (v); \ - w0 = (mp_limb_t) __ww; \ - w1 = (mp_limb_t) (__ww >> LOCAL_GMP_LIMB_BITS); \ - } \ - else { \ - mp_limb_t __x0, __x1, __x2, __x3; \ - unsigned __ul, __vl, __uh, __vh; \ - mp_limb_t __u = (u), __v = (v); \ - assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); \ - \ - __ul = __u & GMP_LLIMB_MASK; \ - __uh = __u >> (GMP_LIMB_BITS / 2); \ - __vl = __v & GMP_LLIMB_MASK; \ - __vh = __v >> (GMP_LIMB_BITS / 2); \ - \ - __x0 = (mp_limb_t) __ul * __vl; \ - __x1 = (mp_limb_t) __ul * __vh; \ - __x2 = (mp_limb_t) __uh * __vl; \ - __x3 = (mp_limb_t) __uh * __vh; \ - \ - __x1 += __x0 >> (GMP_LIMB_BITS / 2);/* this can't give carry */ \ - __x1 += __x2; /* but this indeed can */ \ - if (__x1 < __x2) /* did we get it? */ \ - __x3 += GMP_HLIMB_BIT; /* yes, add it in the proper pos. */ \ - \ - (w1) = __x3 + (__x1 >> (GMP_LIMB_BITS / 2)); \ - (w0) = (__x1 << (GMP_LIMB_BITS / 2)) + (__x0 & GMP_LLIMB_MASK); \ - } \ - } while (0) - -#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di) \ - do { \ - mp_limb_t _qh, _ql, _r, _mask; \ - gmp_umul_ppmm (_qh, _ql, (nh), (di)); \ - gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl)); \ - _r = (nl) - _qh * (d); \ - _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */ \ - _qh += _mask; \ - _r += _mask & (d); \ - if (_r >= (d)) \ - { \ - _r -= (d); \ - _qh++; \ - } \ - \ - (r) = _r; \ - (q) = _qh; \ - } while (0) - -#define gmp_udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \ - do { \ - mp_limb_t _q0, _t1, _t0, _mask; \ - gmp_umul_ppmm ((q), _q0, (n2), (dinv)); \ - gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \ - \ - /* Compute the two most significant limbs of n - q'd */ \ - (r1) = (n1) - (d1) * (q); \ - gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0)); \ - gmp_umul_ppmm (_t1, _t0, (d0), (q)); \ - gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \ - (q)++; \ - \ - /* Conditionally adjust q and the remainders */ \ - _mask = - (mp_limb_t) ((r1) >= _q0); \ - (q) += _mask; \ - gmp_add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \ - if ((r1) >= (d1)) \ - { \ - if ((r1) > (d1) || (r0) >= (d0)) \ - { \ - (q)++; \ - gmp_sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ - } \ - } \ - } while (0) - -/* Swap macros. */ -#define MP_LIMB_T_SWAP(x, y) \ - do { \ - mp_limb_t __mp_limb_t_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mp_limb_t_swap__tmp; \ - } while (0) -#define MP_SIZE_T_SWAP(x, y) \ - do { \ - mp_size_t __mp_size_t_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mp_size_t_swap__tmp; \ - } while (0) -#define MP_BITCNT_T_SWAP(x,y) \ - do { \ - mp_bitcnt_t __mp_bitcnt_t_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mp_bitcnt_t_swap__tmp; \ - } while (0) -#define MP_PTR_SWAP(x, y) \ - do { \ - mp_ptr __mp_ptr_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mp_ptr_swap__tmp; \ - } while (0) -#define MP_SRCPTR_SWAP(x, y) \ - do { \ - mp_srcptr __mp_srcptr_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mp_srcptr_swap__tmp; \ - } while (0) - -#define MPN_PTR_SWAP(xp,xs, yp,ys) \ - do { \ - MP_PTR_SWAP (xp, yp); \ - MP_SIZE_T_SWAP (xs, ys); \ - } while(0) -#define MPN_SRCPTR_SWAP(xp,xs, yp,ys) \ - do { \ - MP_SRCPTR_SWAP (xp, yp); \ - MP_SIZE_T_SWAP (xs, ys); \ - } while(0) - -#define MPZ_PTR_SWAP(x, y) \ - do { \ - mpz_ptr __mpz_ptr_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mpz_ptr_swap__tmp; \ - } while (0) -#define MPZ_SRCPTR_SWAP(x, y) \ - do { \ - mpz_srcptr __mpz_srcptr_swap__tmp = (x); \ - (x) = (y); \ - (y) = __mpz_srcptr_swap__tmp; \ - } while (0) - -const int mp_bits_per_limb = GMP_LIMB_BITS; - - -/* Memory allocation and other helper functions. */ -static void -gmp_die (const char *msg) -{ - fprintf (stderr, "%s\n", msg); - abort(); -} - -static void * -gmp_default_alloc (size_t size) -{ - void *p; - - assert (size > 0); - - p = malloc (size); - if (!p) - gmp_die("gmp_default_alloc: Virtual memory exhausted."); - - return p; -} - -static void * -gmp_default_realloc (void *old, size_t unused_old_size, size_t new_size) -{ - void * p; - - p = realloc (old, new_size); - - if (!p) - gmp_die("gmp_default_realloc: Virtual memory exhausted."); - - return p; -} - -static void -gmp_default_free (void *p, size_t unused_size) -{ - free (p); -} - -static void * (*gmp_allocate_func) (size_t) = gmp_default_alloc; -static void * (*gmp_reallocate_func) (void *, size_t, size_t) = gmp_default_realloc; -static void (*gmp_free_func) (void *, size_t) = gmp_default_free; - -void -mp_get_memory_functions (void *(**alloc_func) (size_t), - void *(**realloc_func) (void *, size_t, size_t), - void (**free_func) (void *, size_t)) -{ - if (alloc_func) - *alloc_func = gmp_allocate_func; - - if (realloc_func) - *realloc_func = gmp_reallocate_func; - - if (free_func) - *free_func = gmp_free_func; -} - -void -mp_set_memory_functions (void *(*alloc_func) (size_t), - void *(*realloc_func) (void *, size_t, size_t), - void (*free_func) (void *, size_t)) -{ - if (!alloc_func) - alloc_func = gmp_default_alloc; - if (!realloc_func) - realloc_func = gmp_default_realloc; - if (!free_func) - free_func = gmp_default_free; - - gmp_allocate_func = alloc_func; - gmp_reallocate_func = realloc_func; - gmp_free_func = free_func; -} - -#define gmp_alloc(size) ((*gmp_allocate_func)((size))) -#define gmp_free(p, size) ((*gmp_free_func) ((p), (size))) -#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, old_size, size)) - -static mp_ptr -gmp_alloc_limbs (mp_size_t size) -{ - return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t)); -} - -static mp_ptr -gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size) -{ - assert (size > 0); - return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * sizeof (mp_limb_t)); -} - -static void -gmp_free_limbs (mp_ptr old, mp_size_t size) -{ - gmp_free (old, size * sizeof (mp_limb_t)); -} - - -/* MPN interface */ - -void -mpn_copyi (mp_ptr d, mp_srcptr s, mp_size_t n) -{ - mp_size_t i; - for (i = 0; i < n; i++) - d[i] = s[i]; -} - -void -mpn_copyd (mp_ptr d, mp_srcptr s, mp_size_t n) -{ - while (--n >= 0) - d[n] = s[n]; -} - -int -mpn_cmp (mp_srcptr ap, mp_srcptr bp, mp_size_t n) -{ - while (--n >= 0) - { - if (ap[n] != bp[n]) - return ap[n] > bp[n] ? 1 : -1; - } - return 0; -} - -static int -mpn_cmp4 (mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) -{ - if (an != bn) - return an < bn ? -1 : 1; - else - return mpn_cmp (ap, bp, an); -} - -static mp_size_t -mpn_normalized_size (mp_srcptr xp, mp_size_t n) -{ - while (n > 0 && xp[n-1] == 0) - --n; - return n; -} - -int -mpn_zero_p(mp_srcptr rp, mp_size_t n) -{ - return mpn_normalized_size (rp, n) == 0; -} - -void -mpn_zero (mp_ptr rp, mp_size_t n) -{ - while (--n >= 0) - rp[n] = 0; -} - -mp_limb_t -mpn_add_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) -{ - mp_size_t i; - - assert (n > 0); - i = 0; - do - { - mp_limb_t r = ap[i] + b; - /* Carry out */ - b = (r < b); - rp[i] = r; - } - while (++i < n); - - return b; -} - -mp_limb_t -mpn_add_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) -{ - mp_size_t i; - mp_limb_t cy; - - for (i = 0, cy = 0; i < n; i++) - { - mp_limb_t a, b, r; - a = ap[i]; b = bp[i]; - r = a + cy; - cy = (r < cy); - r += b; - cy += (r < b); - rp[i] = r; - } - return cy; -} - -mp_limb_t -mpn_add (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) -{ - mp_limb_t cy; - - assert (an >= bn); - - cy = mpn_add_n (rp, ap, bp, bn); - if (an > bn) - cy = mpn_add_1 (rp + bn, ap + bn, an - bn, cy); - return cy; -} - -mp_limb_t -mpn_sub_1 (mp_ptr rp, mp_srcptr ap, mp_size_t n, mp_limb_t b) -{ - mp_size_t i; - - assert (n > 0); - - i = 0; - do - { - mp_limb_t a = ap[i]; - /* Carry out */ - mp_limb_t cy = a < b; - rp[i] = a - b; - b = cy; - } - while (++i < n); - - return b; -} - -mp_limb_t -mpn_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) -{ - mp_size_t i; - mp_limb_t cy; - - for (i = 0, cy = 0; i < n; i++) - { - mp_limb_t a, b; - a = ap[i]; b = bp[i]; - b += cy; - cy = (b < cy); - cy += (a < b); - rp[i] = a - b; - } - return cy; -} - -mp_limb_t -mpn_sub (mp_ptr rp, mp_srcptr ap, mp_size_t an, mp_srcptr bp, mp_size_t bn) -{ - mp_limb_t cy; - - assert (an >= bn); - - cy = mpn_sub_n (rp, ap, bp, bn); - if (an > bn) - cy = mpn_sub_1 (rp + bn, ap + bn, an - bn, cy); - return cy; -} - -mp_limb_t -mpn_mul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) -{ - mp_limb_t ul, cl, hpl, lpl; - - assert (n >= 1); - - cl = 0; - do - { - ul = *up++; - gmp_umul_ppmm (hpl, lpl, ul, vl); - - lpl += cl; - cl = (lpl < cl) + hpl; - - *rp++ = lpl; - } - while (--n != 0); - - return cl; -} - -mp_limb_t -mpn_addmul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) -{ - mp_limb_t ul, cl, hpl, lpl, rl; - - assert (n >= 1); - - cl = 0; - do - { - ul = *up++; - gmp_umul_ppmm (hpl, lpl, ul, vl); - - lpl += cl; - cl = (lpl < cl) + hpl; - - rl = *rp; - lpl = rl + lpl; - cl += lpl < rl; - *rp++ = lpl; - } - while (--n != 0); - - return cl; -} - -mp_limb_t -mpn_submul_1 (mp_ptr rp, mp_srcptr up, mp_size_t n, mp_limb_t vl) -{ - mp_limb_t ul, cl, hpl, lpl, rl; - - assert (n >= 1); - - cl = 0; - do - { - ul = *up++; - gmp_umul_ppmm (hpl, lpl, ul, vl); - - lpl += cl; - cl = (lpl < cl) + hpl; - - rl = *rp; - lpl = rl - lpl; - cl += lpl > rl; - *rp++ = lpl; - } - while (--n != 0); - - return cl; -} - -mp_limb_t -mpn_mul (mp_ptr rp, mp_srcptr up, mp_size_t un, mp_srcptr vp, mp_size_t vn) -{ - assert (un >= vn); - assert (vn >= 1); - assert (!GMP_MPN_OVERLAP_P(rp, un + vn, up, un)); - assert (!GMP_MPN_OVERLAP_P(rp, un + vn, vp, vn)); - - /* We first multiply by the low order limb. This result can be - stored, not added, to rp. We also avoid a loop for zeroing this - way. */ - - rp[un] = mpn_mul_1 (rp, up, un, vp[0]); - - /* Now accumulate the product of up[] and the next higher limb from - vp[]. */ - - while (--vn >= 1) - { - rp += 1, vp += 1; - rp[un] = mpn_addmul_1 (rp, up, un, vp[0]); - } - return rp[un]; -} - -void -mpn_mul_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) -{ - mpn_mul (rp, ap, n, bp, n); -} - -void -mpn_sqr (mp_ptr rp, mp_srcptr ap, mp_size_t n) -{ - mpn_mul (rp, ap, n, ap, n); -} - -mp_limb_t -mpn_lshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) -{ - mp_limb_t high_limb, low_limb; - unsigned int tnc; - mp_limb_t retval; - - assert (n >= 1); - assert (cnt >= 1); - assert (cnt < GMP_LIMB_BITS); - - up += n; - rp += n; - - tnc = GMP_LIMB_BITS - cnt; - low_limb = *--up; - retval = low_limb >> tnc; - high_limb = (low_limb << cnt); - - while (--n != 0) - { - low_limb = *--up; - *--rp = high_limb | (low_limb >> tnc); - high_limb = (low_limb << cnt); - } - *--rp = high_limb; - - return retval; -} - -mp_limb_t -mpn_rshift (mp_ptr rp, mp_srcptr up, mp_size_t n, unsigned int cnt) -{ - mp_limb_t high_limb, low_limb; - unsigned int tnc; - mp_limb_t retval; - - assert (n >= 1); - assert (cnt >= 1); - assert (cnt < GMP_LIMB_BITS); - - tnc = GMP_LIMB_BITS - cnt; - high_limb = *up++; - retval = (high_limb << tnc); - low_limb = high_limb >> cnt; - - while (--n != 0) - { - high_limb = *up++; - *rp++ = low_limb | (high_limb << tnc); - low_limb = high_limb >> cnt; - } - *rp = low_limb; - - return retval; -} - -static mp_bitcnt_t -mpn_common_scan (mp_limb_t limb, mp_size_t i, mp_srcptr up, mp_size_t un, - mp_limb_t ux) -{ - unsigned cnt; - - assert (ux == 0 || ux == GMP_LIMB_MAX); - assert (0 <= i && i <= un ); - - while (limb == 0) - { - i++; - if (i == un) - return (ux == 0 ? ~(mp_bitcnt_t) 0 : un * GMP_LIMB_BITS); - limb = ux ^ up[i]; - } - gmp_ctz (cnt, limb); - return (mp_bitcnt_t) i * GMP_LIMB_BITS + cnt; -} - -mp_bitcnt_t -mpn_scan1 (mp_srcptr ptr, mp_bitcnt_t bit) -{ - mp_size_t i; - i = bit / GMP_LIMB_BITS; - - return mpn_common_scan ( ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), - i, ptr, i, 0); -} - -mp_bitcnt_t -mpn_scan0 (mp_srcptr ptr, mp_bitcnt_t bit) -{ - mp_size_t i; - i = bit / GMP_LIMB_BITS; - - return mpn_common_scan (~ptr[i] & (GMP_LIMB_MAX << (bit % GMP_LIMB_BITS)), - i, ptr, i, GMP_LIMB_MAX); -} - -void -mpn_com (mp_ptr rp, mp_srcptr up, mp_size_t n) -{ - while (--n >= 0) - *rp++ = ~ *up++; -} - -mp_limb_t -mpn_neg (mp_ptr rp, mp_srcptr up, mp_size_t n) -{ - while (*up == 0) - { - *rp = 0; - if (!--n) - return 0; - ++up; ++rp; - } - *rp = - *up; - mpn_com (++rp, ++up, --n); - return 1; -} - - -/* MPN division interface. */ - -/* The 3/2 inverse is defined as - - m = floor( (B^3-1) / (B u1 + u0)) - B -*/ -mp_limb_t -mpn_invert_3by2 (mp_limb_t u1, mp_limb_t u0) -{ - mp_limb_t r, m; - - { - mp_limb_t p, ql; - unsigned ul, uh, qh; - - assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); - /* For notation, let b denote the half-limb base, so that B = b^2. - Split u1 = b uh + ul. */ - ul = u1 & GMP_LLIMB_MASK; - uh = u1 >> (GMP_LIMB_BITS / 2); - - /* Approximation of the high half of quotient. Differs from the 2/1 - inverse of the half limb uh, since we have already subtracted - u0. */ - qh = (u1 ^ GMP_LIMB_MAX) / uh; - - /* Adjust to get a half-limb 3/2 inverse, i.e., we want - - qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u - = floor( (b (~u) + b-1) / u), - - and the remainder - - r = b (~u) + b-1 - qh (b uh + ul) - = b (~u - qh uh) + b-1 - qh ul - - Subtraction of qh ul may underflow, which implies adjustments. - But by normalization, 2 u >= B > qh ul, so we need to adjust by - at most 2. - */ - - r = ((~u1 - (mp_limb_t) qh * uh) << (GMP_LIMB_BITS / 2)) | GMP_LLIMB_MASK; - - p = (mp_limb_t) qh * ul; - /* Adjustment steps taken from udiv_qrnnd_c */ - if (r < p) - { - qh--; - r += u1; - if (r >= u1) /* i.e. we didn't get carry when adding to r */ - if (r < p) - { - qh--; - r += u1; - } - } - r -= p; - - /* Low half of the quotient is - - ql = floor ( (b r + b-1) / u1). - - This is a 3/2 division (on half-limbs), for which qh is a - suitable inverse. */ - - p = (r >> (GMP_LIMB_BITS / 2)) * qh + r; - /* Unlike full-limb 3/2, we can add 1 without overflow. For this to - work, it is essential that ql is a full mp_limb_t. */ - ql = (p >> (GMP_LIMB_BITS / 2)) + 1; - - /* By the 3/2 trick, we don't need the high half limb. */ - r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1; - - if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2)))) - { - ql--; - r += u1; - } - m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql; - if (r >= u1) - { - m++; - r -= u1; - } - } - - /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a - 3/2 inverse. */ - if (u0 > 0) - { - mp_limb_t th, tl; - r = ~r; - r += u0; - if (r < u0) - { - m--; - if (r >= u1) - { - m--; - r -= u1; - } - r -= u1; - } - gmp_umul_ppmm (th, tl, u0, m); - r += th; - if (r < th) - { - m--; - m -= ((r > u1) | ((r == u1) & (tl > u0))); - } - } - - return m; -} - -struct gmp_div_inverse -{ - /* Normalization shift count. */ - unsigned shift; - /* Normalized divisor (d0 unused for mpn_div_qr_1) */ - mp_limb_t d1, d0; - /* Inverse, for 2/1 or 3/2. */ - mp_limb_t di; -}; - -static void -mpn_div_qr_1_invert (struct gmp_div_inverse *inv, mp_limb_t d) -{ - unsigned shift; - - assert (d > 0); - gmp_clz (shift, d); - inv->shift = shift; - inv->d1 = d << shift; - inv->di = mpn_invert_limb (inv->d1); -} - -static void -mpn_div_qr_2_invert (struct gmp_div_inverse *inv, - mp_limb_t d1, mp_limb_t d0) -{ - unsigned shift; - - assert (d1 > 0); - gmp_clz (shift, d1); - inv->shift = shift; - if (shift > 0) - { - d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); - d0 <<= shift; - } - inv->d1 = d1; - inv->d0 = d0; - inv->di = mpn_invert_3by2 (d1, d0); -} - -static void -mpn_div_qr_invert (struct gmp_div_inverse *inv, - mp_srcptr dp, mp_size_t dn) -{ - assert (dn > 0); - - if (dn == 1) - mpn_div_qr_1_invert (inv, dp[0]); - else if (dn == 2) - mpn_div_qr_2_invert (inv, dp[1], dp[0]); - else - { - unsigned shift; - mp_limb_t d1, d0; - - d1 = dp[dn-1]; - d0 = dp[dn-2]; - assert (d1 > 0); - gmp_clz (shift, d1); - inv->shift = shift; - if (shift > 0) - { - d1 = (d1 << shift) | (d0 >> (GMP_LIMB_BITS - shift)); - d0 = (d0 << shift) | (dp[dn-3] >> (GMP_LIMB_BITS - shift)); - } - inv->d1 = d1; - inv->d0 = d0; - inv->di = mpn_invert_3by2 (d1, d0); - } -} - -/* Not matching current public gmp interface, rather corresponding to - the sbpi1_div_* functions. */ -static mp_limb_t -mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn, - const struct gmp_div_inverse *inv) -{ - mp_limb_t d, di; - mp_limb_t r; - mp_ptr tp = NULL; - mp_size_t tn = 0; - - if (inv->shift > 0) - { - /* Shift, reusing qp area if possible. In-place shift if qp == np. */ - tp = qp; - if (!tp) - { - tn = nn; - tp = gmp_alloc_limbs (tn); - } - r = mpn_lshift (tp, np, nn, inv->shift); - np = tp; - } - else - r = 0; - - d = inv->d1; - di = inv->di; - while (--nn >= 0) - { - mp_limb_t q; - - gmp_udiv_qrnnd_preinv (q, r, r, np[nn], d, di); - if (qp) - qp[nn] = q; - } - if (tn) - gmp_free_limbs (tp, tn); - - return r >> inv->shift; -} - -static void -mpn_div_qr_2_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn, - const struct gmp_div_inverse *inv) -{ - unsigned shift; - mp_size_t i; - mp_limb_t d1, d0, di, r1, r0; - - assert (nn >= 2); - shift = inv->shift; - d1 = inv->d1; - d0 = inv->d0; - di = inv->di; - - if (shift > 0) - r1 = mpn_lshift (np, np, nn, shift); - else - r1 = 0; - - r0 = np[nn - 1]; - - i = nn - 2; - do - { - mp_limb_t n0, q; - n0 = np[i]; - gmp_udiv_qr_3by2 (q, r1, r0, r1, r0, n0, d1, d0, di); - - if (qp) - qp[i] = q; - } - while (--i >= 0); - - if (shift > 0) - { - assert ((r0 & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - shift))) == 0); - r0 = (r0 >> shift) | (r1 << (GMP_LIMB_BITS - shift)); - r1 >>= shift; - } - - np[1] = r1; - np[0] = r0; -} - -static void -mpn_div_qr_pi1 (mp_ptr qp, - mp_ptr np, mp_size_t nn, mp_limb_t n1, - mp_srcptr dp, mp_size_t dn, - mp_limb_t dinv) -{ - mp_size_t i; - - mp_limb_t d1, d0; - mp_limb_t cy, cy1; - mp_limb_t q; - - assert (dn > 2); - assert (nn >= dn); - - d1 = dp[dn - 1]; - d0 = dp[dn - 2]; - - assert ((d1 & GMP_LIMB_HIGHBIT) != 0); - /* Iteration variable is the index of the q limb. - * - * We divide - * by - */ - - i = nn - dn; - do - { - mp_limb_t n0 = np[dn-1+i]; - - if (n1 == d1 && n0 == d0) - { - q = GMP_LIMB_MAX; - mpn_submul_1 (np+i, dp, dn, q); - n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */ - } - else - { - gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv); - - cy = mpn_submul_1 (np + i, dp, dn-2, q); - - cy1 = n0 < cy; - n0 = n0 - cy; - cy = n1 < cy1; - n1 = n1 - cy1; - np[dn-2+i] = n0; - - if (cy != 0) - { - n1 += d1 + mpn_add_n (np + i, np + i, dp, dn - 1); - q--; - } - } - - if (qp) - qp[i] = q; - } - while (--i >= 0); - - np[dn - 1] = n1; -} - -static void -mpn_div_qr_preinv (mp_ptr qp, mp_ptr np, mp_size_t nn, - mp_srcptr dp, mp_size_t dn, - const struct gmp_div_inverse *inv) -{ - assert (dn > 0); - assert (nn >= dn); - - if (dn == 1) - np[0] = mpn_div_qr_1_preinv (qp, np, nn, inv); - else if (dn == 2) - mpn_div_qr_2_preinv (qp, np, nn, inv); - else - { - mp_limb_t nh; - unsigned shift; - - assert (inv->d1 == dp[dn-1]); - assert (inv->d0 == dp[dn-2]); - assert ((inv->d1 & GMP_LIMB_HIGHBIT) != 0); - - shift = inv->shift; - if (shift > 0) - nh = mpn_lshift (np, np, nn, shift); - else - nh = 0; - - mpn_div_qr_pi1 (qp, np, nn, nh, dp, dn, inv->di); - - if (shift > 0) - gmp_assert_nocarry (mpn_rshift (np, np, dn, shift)); - } -} - -static void -mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn) -{ - struct gmp_div_inverse inv; - mp_ptr tp = NULL; - - assert (dn > 0); - assert (nn >= dn); - - mpn_div_qr_invert (&inv, dp, dn); - if (dn > 2 && inv.shift > 0) - { - tp = gmp_alloc_limbs (dn); - gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift)); - dp = tp; - } - mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv); - if (tp) - gmp_free_limbs (tp, dn); -} - - -/* MPN base conversion. */ -static unsigned -mpn_base_power_of_two_p (unsigned b) -{ - switch (b) - { - case 2: return 1; - case 4: return 2; - case 8: return 3; - case 16: return 4; - case 32: return 5; - case 64: return 6; - case 128: return 7; - case 256: return 8; - default: return 0; - } -} - -struct mpn_base_info -{ - /* bb is the largest power of the base which fits in one limb, and - exp is the corresponding exponent. */ - unsigned exp; - mp_limb_t bb; -}; - -static void -mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b) -{ - mp_limb_t m; - mp_limb_t p; - unsigned exp; - - m = GMP_LIMB_MAX / b; - for (exp = 1, p = b; p <= m; exp++) - p *= b; - - info->exp = exp; - info->bb = p; -} - -static mp_bitcnt_t -mpn_limb_size_in_base_2 (mp_limb_t u) -{ - unsigned shift; - - assert (u > 0); - gmp_clz (shift, u); - return GMP_LIMB_BITS - shift; -} - -static size_t -mpn_get_str_bits (unsigned char *sp, unsigned bits, mp_srcptr up, mp_size_t un) -{ - unsigned char mask; - size_t sn, j; - mp_size_t i; - unsigned shift; - - sn = ((un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]) - + bits - 1) / bits; - - mask = (1U << bits) - 1; - - for (i = 0, j = sn, shift = 0; j-- > 0;) - { - unsigned char digit = up[i] >> shift; - - shift += bits; - - if (shift >= GMP_LIMB_BITS && ++i < un) - { - shift -= GMP_LIMB_BITS; - digit |= up[i] << (bits - shift); - } - sp[j] = digit & mask; - } - return sn; -} - -/* We generate digits from the least significant end, and reverse at - the end. */ -static size_t -mpn_limb_get_str (unsigned char *sp, mp_limb_t w, - const struct gmp_div_inverse *binv) -{ - mp_size_t i; - for (i = 0; w > 0; i++) - { - mp_limb_t h, l, r; - - h = w >> (GMP_LIMB_BITS - binv->shift); - l = w << binv->shift; - - gmp_udiv_qrnnd_preinv (w, r, h, l, binv->d1, binv->di); - assert ((r & (GMP_LIMB_MAX >> (GMP_LIMB_BITS - binv->shift))) == 0); - r >>= binv->shift; - - sp[i] = r; - } - return i; -} - -static size_t -mpn_get_str_other (unsigned char *sp, - int base, const struct mpn_base_info *info, - mp_ptr up, mp_size_t un) -{ - struct gmp_div_inverse binv; - size_t sn; - size_t i; - - mpn_div_qr_1_invert (&binv, base); - - sn = 0; - - if (un > 1) - { - struct gmp_div_inverse bbinv; - mpn_div_qr_1_invert (&bbinv, info->bb); - - do - { - mp_limb_t w; - size_t done; - w = mpn_div_qr_1_preinv (up, up, un, &bbinv); - un -= (up[un-1] == 0); - done = mpn_limb_get_str (sp + sn, w, &binv); - - for (sn += done; done < info->exp; done++) - sp[sn++] = 0; - } - while (un > 1); - } - sn += mpn_limb_get_str (sp + sn, up[0], &binv); - - /* Reverse order */ - for (i = 0; 2*i + 1 < sn; i++) - { - unsigned char t = sp[i]; - sp[i] = sp[sn - i - 1]; - sp[sn - i - 1] = t; - } - - return sn; -} - -size_t -mpn_get_str (unsigned char *sp, int base, mp_ptr up, mp_size_t un) -{ - unsigned bits; - - assert (un > 0); - assert (up[un-1] > 0); - - bits = mpn_base_power_of_two_p (base); - if (bits) - return mpn_get_str_bits (sp, bits, up, un); - else - { - struct mpn_base_info info; - - mpn_get_base_info (&info, base); - return mpn_get_str_other (sp, base, &info, up, un); - } -} - -static mp_size_t -mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn, - unsigned bits) -{ - mp_size_t rn; - mp_limb_t limb; - unsigned shift; - - for (limb = 0, rn = 0, shift = 0; sn-- > 0; ) - { - limb |= (mp_limb_t) sp[sn] << shift; - shift += bits; - if (shift >= GMP_LIMB_BITS) - { - shift -= GMP_LIMB_BITS; - rp[rn++] = limb; - /* Next line is correct also if shift == 0, - bits == 8, and mp_limb_t == unsigned char. */ - limb = (unsigned int) sp[sn] >> (bits - shift); - } - } - if (limb != 0) - rp[rn++] = limb; - else - rn = mpn_normalized_size (rp, rn); - return rn; -} - -/* Result is usually normalized, except for all-zero input, in which - case a single zero limb is written at *RP, and 1 is returned. */ -static mp_size_t -mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn, - mp_limb_t b, const struct mpn_base_info *info) -{ - mp_size_t rn; - mp_limb_t w; - unsigned k; - size_t j; - - assert (sn > 0); - - k = 1 + (sn - 1) % info->exp; - - j = 0; - w = sp[j++]; - while (--k != 0) - w = w * b + sp[j++]; - - rp[0] = w; - - for (rn = 1; j < sn;) - { - mp_limb_t cy; - - w = sp[j++]; - for (k = 1; k < info->exp; k++) - w = w * b + sp[j++]; - - cy = mpn_mul_1 (rp, rp, rn, info->bb); - cy += mpn_add_1 (rp, rp, rn, w); - if (cy > 0) - rp[rn++] = cy; - } - assert (j == sn); - - return rn; -} - -mp_size_t -mpn_set_str (mp_ptr rp, const unsigned char *sp, size_t sn, int base) -{ - unsigned bits; - - if (sn == 0) - return 0; - - bits = mpn_base_power_of_two_p (base); - if (bits) - return mpn_set_str_bits (rp, sp, sn, bits); - else - { - struct mpn_base_info info; - - mpn_get_base_info (&info, base); - return mpn_set_str_other (rp, sp, sn, base, &info); - } -} - - -/* MPZ interface */ -void -mpz_init (mpz_t r) -{ - static const mp_limb_t dummy_limb = GMP_LIMB_MAX & 0xc1a0; - - r->_mp_alloc = 0; - r->_mp_size = 0; - r->_mp_d = (mp_ptr) &dummy_limb; -} - -/* The utility of this function is a bit limited, since many functions - assigns the result variable using mpz_swap. */ -void -mpz_init2 (mpz_t r, mp_bitcnt_t bits) -{ - mp_size_t rn; - - bits -= (bits != 0); /* Round down, except if 0 */ - rn = 1 + bits / GMP_LIMB_BITS; - - r->_mp_alloc = rn; - r->_mp_size = 0; - r->_mp_d = gmp_alloc_limbs (rn); -} - -void -mpz_clear (mpz_t r) -{ - if (r->_mp_alloc) - gmp_free_limbs (r->_mp_d, r->_mp_alloc); -} - -static mp_ptr -mpz_realloc (mpz_t r, mp_size_t size) -{ - size = GMP_MAX (size, 1); - - if (r->_mp_alloc) - r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size); - else - r->_mp_d = gmp_alloc_limbs (size); - r->_mp_alloc = size; - - if (GMP_ABS (r->_mp_size) > size) - r->_mp_size = 0; - - return r->_mp_d; -} - -/* Realloc for an mpz_t WHAT if it has less than NEEDED limbs. */ -#define MPZ_REALLOC(z,n) ((n) > (z)->_mp_alloc \ - ? mpz_realloc(z,n) \ - : (z)->_mp_d) - -/* MPZ assignment and basic conversions. */ -void -mpz_set_si (mpz_t r, signed long int x) -{ - if (x >= 0) - mpz_set_ui (r, x); - else /* (x < 0) */ - if (GMP_LIMB_BITS < GMP_ULONG_BITS) - { - mpz_set_ui (r, GMP_NEG_CAST (unsigned long int, x)); - mpz_neg (r, r); - } - else - { - r->_mp_size = -1; - MPZ_REALLOC (r, 1)[0] = GMP_NEG_CAST (unsigned long int, x); - } -} - -void -mpz_set_ui (mpz_t r, unsigned long int x) -{ - if (x > 0) - { - r->_mp_size = 1; - MPZ_REALLOC (r, 1)[0] = x; - if (GMP_LIMB_BITS < GMP_ULONG_BITS) - { - int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; - while (x >>= LOCAL_GMP_LIMB_BITS) - { - ++ r->_mp_size; - MPZ_REALLOC (r, r->_mp_size)[r->_mp_size - 1] = x; - } - } - } - else - r->_mp_size = 0; -} - -void -mpz_set (mpz_t r, const mpz_t x) -{ - /* Allow the NOP r == x */ - if (r != x) - { - mp_size_t n; - mp_ptr rp; - - n = GMP_ABS (x->_mp_size); - rp = MPZ_REALLOC (r, n); - - mpn_copyi (rp, x->_mp_d, n); - r->_mp_size = x->_mp_size; - } -} - -void -mpz_init_set_si (mpz_t r, signed long int x) -{ - mpz_init (r); - mpz_set_si (r, x); -} - -void -mpz_init_set_ui (mpz_t r, unsigned long int x) -{ - mpz_init (r); - mpz_set_ui (r, x); -} - -void -mpz_init_set (mpz_t r, const mpz_t x) -{ - mpz_init (r); - mpz_set (r, x); -} - -int -mpz_fits_slong_p (const mpz_t u) -{ - return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0; -} - -static int -mpn_absfits_ulong_p (mp_srcptr up, mp_size_t un) -{ - int ulongsize = GMP_ULONG_BITS / GMP_LIMB_BITS; - mp_limb_t ulongrem = 0; - - if (GMP_ULONG_BITS % GMP_LIMB_BITS != 0) - ulongrem = (mp_limb_t) (ULONG_MAX >> GMP_LIMB_BITS * ulongsize) + 1; - - return un <= ulongsize || (up[ulongsize] < ulongrem && un == ulongsize + 1); -} - -int -mpz_fits_ulong_p (const mpz_t u) -{ - mp_size_t us = u->_mp_size; - - return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us); -} - -int -mpz_fits_sint_p (const mpz_t u) -{ - return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0; -} - -int -mpz_fits_uint_p (const mpz_t u) -{ - return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0; -} - -int -mpz_fits_sshort_p (const mpz_t u) -{ - return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0; -} - -int -mpz_fits_ushort_p (const mpz_t u) -{ - return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0; -} - -long int -mpz_get_si (const mpz_t u) -{ - unsigned long r = mpz_get_ui (u); - unsigned long c = -LONG_MAX - LONG_MIN; - - if (u->_mp_size < 0) - /* This expression is necessary to properly handle -LONG_MIN */ - return -(long) c - (long) ((r - c) & LONG_MAX); - else - return (long) (r & LONG_MAX); -} - -unsigned long int -mpz_get_ui (const mpz_t u) -{ - if (GMP_LIMB_BITS < GMP_ULONG_BITS) - { - int LOCAL_GMP_LIMB_BITS = GMP_LIMB_BITS; - unsigned long r = 0; - mp_size_t n = GMP_ABS (u->_mp_size); - n = GMP_MIN (n, 1 + (mp_size_t) (GMP_ULONG_BITS - 1) / GMP_LIMB_BITS); - while (--n >= 0) - r = (r << LOCAL_GMP_LIMB_BITS) + u->_mp_d[n]; - return r; - } - - return u->_mp_size == 0 ? 0 : u->_mp_d[0]; -} - -size_t -mpz_size (const mpz_t u) -{ - return GMP_ABS (u->_mp_size); -} - -mp_limb_t -mpz_getlimbn (const mpz_t u, mp_size_t n) -{ - if (n >= 0 && n < GMP_ABS (u->_mp_size)) - return u->_mp_d[n]; - else - return 0; -} - -void -mpz_realloc2 (mpz_t x, mp_bitcnt_t n) -{ - mpz_realloc (x, 1 + (n - (n != 0)) / GMP_LIMB_BITS); -} - -mp_srcptr -mpz_limbs_read (mpz_srcptr x) -{ - return x->_mp_d; -} - -mp_ptr -mpz_limbs_modify (mpz_t x, mp_size_t n) -{ - assert (n > 0); - return MPZ_REALLOC (x, n); -} - -mp_ptr -mpz_limbs_write (mpz_t x, mp_size_t n) -{ - return mpz_limbs_modify (x, n); -} - -void -mpz_limbs_finish (mpz_t x, mp_size_t xs) -{ - mp_size_t xn; - xn = mpn_normalized_size (x->_mp_d, GMP_ABS (xs)); - x->_mp_size = xs < 0 ? -xn : xn; -} - -static mpz_srcptr -mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs) -{ - x->_mp_alloc = 0; - x->_mp_d = (mp_ptr) xp; - x->_mp_size = xs; - return x; -} - -mpz_srcptr -mpz_roinit_n (mpz_t x, mp_srcptr xp, mp_size_t xs) -{ - mpz_roinit_normal_n (x, xp, xs); - mpz_limbs_finish (x, xs); - return x; -} - - -/* Conversions and comparison to double. */ -void -mpz_set_d (mpz_t r, double x) -{ - int sign; - mp_ptr rp; - mp_size_t rn, i; - double B; - double Bi; - mp_limb_t f; - - /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is - zero or infinity. */ - if (x != x || x == x * 0.5) - { - r->_mp_size = 0; - return; - } - - sign = x < 0.0 ; - if (sign) - x = - x; - - if (x < 1.0) - { - r->_mp_size = 0; - return; - } - B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); - Bi = 1.0 / B; - for (rn = 1; x >= B; rn++) - x *= Bi; - - rp = MPZ_REALLOC (r, rn); - - f = (mp_limb_t) x; - x -= f; - assert (x < 1.0); - i = rn-1; - rp[i] = f; - while (--i >= 0) - { - x = B * x; - f = (mp_limb_t) x; - x -= f; - assert (x < 1.0); - rp[i] = f; - } - - r->_mp_size = sign ? - rn : rn; -} - -void -mpz_init_set_d (mpz_t r, double x) -{ - mpz_init (r); - mpz_set_d (r, x); -} - -double -mpz_get_d (const mpz_t u) -{ - int m; - mp_limb_t l; - mp_size_t un; - double x; - double B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); - - un = GMP_ABS (u->_mp_size); - - if (un == 0) - return 0.0; - - l = u->_mp_d[--un]; - gmp_clz (m, l); - m = m + GMP_DBL_MANT_BITS - GMP_LIMB_BITS; - if (m < 0) - l &= GMP_LIMB_MAX << -m; - - for (x = l; --un >= 0;) - { - x = B*x; - if (m > 0) { - l = u->_mp_d[un]; - m -= GMP_LIMB_BITS; - if (m < 0) - l &= GMP_LIMB_MAX << -m; - x += l; - } - } - - if (u->_mp_size < 0) - x = -x; - - return x; -} - -int -mpz_cmpabs_d (const mpz_t x, double d) -{ - mp_size_t xn; - double B, Bi; - mp_size_t i; - - xn = x->_mp_size; - d = GMP_ABS (d); - - if (xn != 0) - { - xn = GMP_ABS (xn); - - B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1); - Bi = 1.0 / B; - - /* Scale d so it can be compared with the top limb. */ - for (i = 1; i < xn; i++) - d *= Bi; - - if (d >= B) - return -1; - - /* Compare floor(d) to top limb, subtract and cancel when equal. */ - for (i = xn; i-- > 0;) - { - mp_limb_t f, xl; - - f = (mp_limb_t) d; - xl = x->_mp_d[i]; - if (xl > f) - return 1; - else if (xl < f) - return -1; - d = B * (d - f); - } - } - return - (d > 0.0); -} - -int -mpz_cmp_d (const mpz_t x, double d) -{ - if (x->_mp_size < 0) - { - if (d >= 0.0) - return -1; - else - return -mpz_cmpabs_d (x, d); - } - else - { - if (d < 0.0) - return 1; - else - return mpz_cmpabs_d (x, d); - } -} - - -/* MPZ comparisons and the like. */ -int -mpz_sgn (const mpz_t u) -{ - return GMP_CMP (u->_mp_size, 0); -} - -int -mpz_cmp_si (const mpz_t u, long v) -{ - mp_size_t usize = u->_mp_size; - - if (v >= 0) - return mpz_cmp_ui (u, v); - else if (usize >= 0) - return 1; - else - return - mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, v)); -} - -int -mpz_cmp_ui (const mpz_t u, unsigned long v) -{ - mp_size_t usize = u->_mp_size; - - if (usize < 0) - return -1; - else - return mpz_cmpabs_ui (u, v); -} - -int -mpz_cmp (const mpz_t a, const mpz_t b) -{ - mp_size_t asize = a->_mp_size; - mp_size_t bsize = b->_mp_size; - - if (asize != bsize) - return (asize < bsize) ? -1 : 1; - else if (asize >= 0) - return mpn_cmp (a->_mp_d, b->_mp_d, asize); - else - return mpn_cmp (b->_mp_d, a->_mp_d, -asize); -} - -int -mpz_cmpabs_ui (const mpz_t u, unsigned long v) -{ - mp_size_t un = GMP_ABS (u->_mp_size); - - if (! mpn_absfits_ulong_p (u->_mp_d, un)) - return 1; - else - { - unsigned long uu = mpz_get_ui (u); - return GMP_CMP(uu, v); - } -} - -int -mpz_cmpabs (const mpz_t u, const mpz_t v) -{ - return mpn_cmp4 (u->_mp_d, GMP_ABS (u->_mp_size), - v->_mp_d, GMP_ABS (v->_mp_size)); -} - -void -mpz_abs (mpz_t r, const mpz_t u) -{ - mpz_set (r, u); - r->_mp_size = GMP_ABS (r->_mp_size); -} - -void -mpz_neg (mpz_t r, const mpz_t u) -{ - mpz_set (r, u); - r->_mp_size = -r->_mp_size; -} - -void -mpz_swap (mpz_t u, mpz_t v) -{ - MP_SIZE_T_SWAP (u->_mp_alloc, v->_mp_alloc); - MPN_PTR_SWAP (u->_mp_d, u->_mp_size, v->_mp_d, v->_mp_size); -} - - -/* MPZ addition and subtraction */ - - -void -mpz_add_ui (mpz_t r, const mpz_t a, unsigned long b) -{ - mpz_t bb; - mpz_init_set_ui (bb, b); - mpz_add (r, a, bb); - mpz_clear (bb); -} - -void -mpz_sub_ui (mpz_t r, const mpz_t a, unsigned long b) -{ - mpz_ui_sub (r, b, a); - mpz_neg (r, r); -} - -void -mpz_ui_sub (mpz_t r, unsigned long a, const mpz_t b) -{ - mpz_neg (r, b); - mpz_add_ui (r, r, a); -} - -static mp_size_t -mpz_abs_add (mpz_t r, const mpz_t a, const mpz_t b) -{ - mp_size_t an = GMP_ABS (a->_mp_size); - mp_size_t bn = GMP_ABS (b->_mp_size); - mp_ptr rp; - mp_limb_t cy; - - if (an < bn) - { - MPZ_SRCPTR_SWAP (a, b); - MP_SIZE_T_SWAP (an, bn); - } - - rp = MPZ_REALLOC (r, an + 1); - cy = mpn_add (rp, a->_mp_d, an, b->_mp_d, bn); - - rp[an] = cy; - - return an + cy; -} - -static mp_size_t -mpz_abs_sub (mpz_t r, const mpz_t a, const mpz_t b) -{ - mp_size_t an = GMP_ABS (a->_mp_size); - mp_size_t bn = GMP_ABS (b->_mp_size); - int cmp; - mp_ptr rp; - - cmp = mpn_cmp4 (a->_mp_d, an, b->_mp_d, bn); - if (cmp > 0) - { - rp = MPZ_REALLOC (r, an); - gmp_assert_nocarry (mpn_sub (rp, a->_mp_d, an, b->_mp_d, bn)); - return mpn_normalized_size (rp, an); - } - else if (cmp < 0) - { - rp = MPZ_REALLOC (r, bn); - gmp_assert_nocarry (mpn_sub (rp, b->_mp_d, bn, a->_mp_d, an)); - return -mpn_normalized_size (rp, bn); - } - else - return 0; -} - -void -mpz_add (mpz_t r, const mpz_t a, const mpz_t b) -{ - mp_size_t rn; - - if ( (a->_mp_size ^ b->_mp_size) >= 0) - rn = mpz_abs_add (r, a, b); - else - rn = mpz_abs_sub (r, a, b); - - r->_mp_size = a->_mp_size >= 0 ? rn : - rn; -} - -void -mpz_sub (mpz_t r, const mpz_t a, const mpz_t b) -{ - mp_size_t rn; - - if ( (a->_mp_size ^ b->_mp_size) >= 0) - rn = mpz_abs_sub (r, a, b); - else - rn = mpz_abs_add (r, a, b); - - r->_mp_size = a->_mp_size >= 0 ? rn : - rn; -} - - -/* MPZ multiplication */ -void -mpz_mul_si (mpz_t r, const mpz_t u, long int v) -{ - if (v < 0) - { - mpz_mul_ui (r, u, GMP_NEG_CAST (unsigned long int, v)); - mpz_neg (r, r); - } - else - mpz_mul_ui (r, u, v); -} - -void -mpz_mul_ui (mpz_t r, const mpz_t u, unsigned long int v) -{ - mpz_t vv; - mpz_init_set_ui (vv, v); - mpz_mul (r, u, vv); - mpz_clear (vv); - return; -} - -void -mpz_mul (mpz_t r, const mpz_t u, const mpz_t v) -{ - int sign; - mp_size_t un, vn, rn; - mpz_t t; - mp_ptr tp; - - un = u->_mp_size; - vn = v->_mp_size; - - if (un == 0 || vn == 0) - { - r->_mp_size = 0; - return; - } - - sign = (un ^ vn) < 0; - - un = GMP_ABS (un); - vn = GMP_ABS (vn); - - mpz_init2 (t, (un + vn) * GMP_LIMB_BITS); - - tp = t->_mp_d; - if (un >= vn) - mpn_mul (tp, u->_mp_d, un, v->_mp_d, vn); - else - mpn_mul (tp, v->_mp_d, vn, u->_mp_d, un); - - rn = un + vn; - rn -= tp[rn-1] == 0; - - t->_mp_size = sign ? - rn : rn; - mpz_swap (r, t); - mpz_clear (t); -} - -void -mpz_mul_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bits) -{ - mp_size_t un, rn; - mp_size_t limbs; - unsigned shift; - mp_ptr rp; - - un = GMP_ABS (u->_mp_size); - if (un == 0) - { - r->_mp_size = 0; - return; - } - - limbs = bits / GMP_LIMB_BITS; - shift = bits % GMP_LIMB_BITS; - - rn = un + limbs + (shift > 0); - rp = MPZ_REALLOC (r, rn); - if (shift > 0) - { - mp_limb_t cy = mpn_lshift (rp + limbs, u->_mp_d, un, shift); - rp[rn-1] = cy; - rn -= (cy == 0); - } - else - mpn_copyd (rp + limbs, u->_mp_d, un); - - mpn_zero (rp, limbs); - - r->_mp_size = (u->_mp_size < 0) ? - rn : rn; -} - -void -mpz_addmul_ui (mpz_t r, const mpz_t u, unsigned long int v) -{ - mpz_t t; - mpz_init_set_ui (t, v); - mpz_mul (t, u, t); - mpz_add (r, r, t); - mpz_clear (t); -} - -void -mpz_submul_ui (mpz_t r, const mpz_t u, unsigned long int v) -{ - mpz_t t; - mpz_init_set_ui (t, v); - mpz_mul (t, u, t); - mpz_sub (r, r, t); - mpz_clear (t); -} - -void -mpz_addmul (mpz_t r, const mpz_t u, const mpz_t v) -{ - mpz_t t; - mpz_init (t); - mpz_mul (t, u, v); - mpz_add (r, r, t); - mpz_clear (t); -} - -void -mpz_submul (mpz_t r, const mpz_t u, const mpz_t v) -{ - mpz_t t; - mpz_init (t); - mpz_mul (t, u, v); - mpz_sub (r, r, t); - mpz_clear (t); -} - - -/* MPZ division */ -enum mpz_div_round_mode { GMP_DIV_FLOOR, GMP_DIV_CEIL, GMP_DIV_TRUNC }; - -/* Allows q or r to be zero. Returns 1 iff remainder is non-zero. */ -static int -mpz_div_qr (mpz_t q, mpz_t r, - const mpz_t n, const mpz_t d, enum mpz_div_round_mode mode) -{ - mp_size_t ns, ds, nn, dn, qs; - ns = n->_mp_size; - ds = d->_mp_size; - - if (ds == 0) - gmp_die("mpz_div_qr: Divide by zero."); - - if (ns == 0) - { - if (q) - q->_mp_size = 0; - if (r) - r->_mp_size = 0; - return 0; - } - - nn = GMP_ABS (ns); - dn = GMP_ABS (ds); - - qs = ds ^ ns; - - if (nn < dn) - { - if (mode == GMP_DIV_CEIL && qs >= 0) - { - /* q = 1, r = n - d */ - if (r) - mpz_sub (r, n, d); - if (q) - mpz_set_ui (q, 1); - } - else if (mode == GMP_DIV_FLOOR && qs < 0) - { - /* q = -1, r = n + d */ - if (r) - mpz_add (r, n, d); - if (q) - mpz_set_si (q, -1); - } - else - { - /* q = 0, r = d */ - if (r) - mpz_set (r, n); - if (q) - q->_mp_size = 0; - } - return 1; - } - else - { - mp_ptr np, qp; - mp_size_t qn, rn; - mpz_t tq, tr; - - mpz_init_set (tr, n); - np = tr->_mp_d; - - qn = nn - dn + 1; - - if (q) - { - mpz_init2 (tq, qn * GMP_LIMB_BITS); - qp = tq->_mp_d; - } - else - qp = NULL; - - mpn_div_qr (qp, np, nn, d->_mp_d, dn); - - if (qp) - { - qn -= (qp[qn-1] == 0); - - tq->_mp_size = qs < 0 ? -qn : qn; - } - rn = mpn_normalized_size (np, dn); - tr->_mp_size = ns < 0 ? - rn : rn; - - if (mode == GMP_DIV_FLOOR && qs < 0 && rn != 0) - { - if (q) - mpz_sub_ui (tq, tq, 1); - if (r) - mpz_add (tr, tr, d); - } - else if (mode == GMP_DIV_CEIL && qs >= 0 && rn != 0) - { - if (q) - mpz_add_ui (tq, tq, 1); - if (r) - mpz_sub (tr, tr, d); - } - - if (q) - { - mpz_swap (tq, q); - mpz_clear (tq); - } - if (r) - mpz_swap (tr, r); - - mpz_clear (tr); - - return rn != 0; - } -} - -void -mpz_cdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, r, n, d, GMP_DIV_CEIL); -} - -void -mpz_fdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, r, n, d, GMP_DIV_FLOOR); -} - -void -mpz_tdiv_qr (mpz_t q, mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, r, n, d, GMP_DIV_TRUNC); -} - -void -mpz_cdiv_q (mpz_t q, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, NULL, n, d, GMP_DIV_CEIL); -} - -void -mpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, NULL, n, d, GMP_DIV_FLOOR); -} - -void -mpz_tdiv_q (mpz_t q, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC); -} - -void -mpz_cdiv_r (mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (NULL, r, n, d, GMP_DIV_CEIL); -} - -void -mpz_fdiv_r (mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (NULL, r, n, d, GMP_DIV_FLOOR); -} - -void -mpz_tdiv_r (mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (NULL, r, n, d, GMP_DIV_TRUNC); -} - -void -mpz_mod (mpz_t r, const mpz_t n, const mpz_t d) -{ - mpz_div_qr (NULL, r, n, d, d->_mp_size >= 0 ? GMP_DIV_FLOOR : GMP_DIV_CEIL); -} - -static void -mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index, - enum mpz_div_round_mode mode) -{ - mp_size_t un, qn; - mp_size_t limb_cnt; - mp_ptr qp; - int adjust; - - un = u->_mp_size; - if (un == 0) - { - q->_mp_size = 0; - return; - } - limb_cnt = bit_index / GMP_LIMB_BITS; - qn = GMP_ABS (un) - limb_cnt; - bit_index %= GMP_LIMB_BITS; - - if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */ - /* Note: Below, the final indexing at limb_cnt is valid because at - that point we have qn > 0. */ - adjust = (qn <= 0 - || !mpn_zero_p (u->_mp_d, limb_cnt) - || (u->_mp_d[limb_cnt] - & (((mp_limb_t) 1 << bit_index) - 1))); - else - adjust = 0; - - if (qn <= 0) - qn = 0; - else - { - qp = MPZ_REALLOC (q, qn); - - if (bit_index != 0) - { - mpn_rshift (qp, u->_mp_d + limb_cnt, qn, bit_index); - qn -= qp[qn - 1] == 0; - } - else - { - mpn_copyi (qp, u->_mp_d + limb_cnt, qn); - } - } - - q->_mp_size = qn; - - if (adjust) - mpz_add_ui (q, q, 1); - if (un < 0) - mpz_neg (q, q); -} - -static void -mpz_div_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t bit_index, - enum mpz_div_round_mode mode) -{ - mp_size_t us, un, rn; - mp_ptr rp; - mp_limb_t mask; - - us = u->_mp_size; - if (us == 0 || bit_index == 0) - { - r->_mp_size = 0; - return; - } - rn = (bit_index + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; - assert (rn > 0); - - rp = MPZ_REALLOC (r, rn); - un = GMP_ABS (us); - - mask = GMP_LIMB_MAX >> (rn * GMP_LIMB_BITS - bit_index); - - if (rn > un) - { - /* Quotient (with truncation) is zero, and remainder is - non-zero */ - if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ - { - /* Have to negate and sign extend. */ - mp_size_t i; - - gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un)); - for (i = un; i < rn - 1; i++) - rp[i] = GMP_LIMB_MAX; - - rp[rn-1] = mask; - us = -us; - } - else - { - /* Just copy */ - if (r != u) - mpn_copyi (rp, u->_mp_d, un); - - rn = un; - } - } - else - { - if (r != u) - mpn_copyi (rp, u->_mp_d, rn - 1); - - rp[rn-1] = u->_mp_d[rn-1] & mask; - - if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */ - { - /* If r != 0, compute 2^{bit_count} - r. */ - mpn_neg (rp, rp, rn); - - rp[rn-1] &= mask; - - /* us is not used for anything else, so we can modify it - here to indicate flipped sign. */ - us = -us; - } - } - rn = mpn_normalized_size (rp, rn); - r->_mp_size = us < 0 ? -rn : rn; -} - -void -mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL); -} - -void -mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR); -} - -void -mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC); -} - -void -mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL); -} - -void -mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR); -} - -void -mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt) -{ - mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC); -} - -void -mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) -{ - gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC)); -} - -int -mpz_divisible_p (const mpz_t n, const mpz_t d) -{ - return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; -} - -int -mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m) -{ - mpz_t t; - int res; - - /* a == b (mod 0) iff a == b */ - if (mpz_sgn (m) == 0) - return (mpz_cmp (a, b) == 0); - - mpz_init (t); - mpz_sub (t, a, b); - res = mpz_divisible_p (t, m); - mpz_clear (t); - - return res; -} - -static unsigned long -mpz_div_qr_ui (mpz_t q, mpz_t r, - const mpz_t n, unsigned long d, enum mpz_div_round_mode mode) -{ - unsigned long ret; - mpz_t rr, dd; - - mpz_init (rr); - mpz_init_set_ui (dd, d); - mpz_div_qr (q, rr, n, dd, mode); - mpz_clear (dd); - ret = mpz_get_ui (rr); - - if (r) - mpz_swap (r, rr); - mpz_clear (rr); - - return ret; -} - -unsigned long -mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL); -} - -unsigned long -mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR); -} - -unsigned long -mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC); -} - -unsigned long -mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL); -} - -unsigned long -mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR); -} - -unsigned long -mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC); -} - -unsigned long -mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL); -} -unsigned long -mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); -} -unsigned long -mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC); -} - -unsigned long -mpz_cdiv_ui (const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL); -} - -unsigned long -mpz_fdiv_ui (const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR); -} - -unsigned long -mpz_tdiv_ui (const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC); -} - -unsigned long -mpz_mod_ui (mpz_t r, const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR); -} - -void -mpz_divexact_ui (mpz_t q, const mpz_t n, unsigned long d) -{ - gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC)); -} - -int -mpz_divisible_ui_p (const mpz_t n, unsigned long d) -{ - return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0; -} - - -/* GCD */ -static mp_limb_t -mpn_gcd_11 (mp_limb_t u, mp_limb_t v) -{ - unsigned shift; - - assert ( (u | v) > 0); - - if (u == 0) - return v; - else if (v == 0) - return u; - - gmp_ctz (shift, u | v); - - u >>= shift; - v >>= shift; - - if ( (u & 1) == 0) - MP_LIMB_T_SWAP (u, v); - - while ( (v & 1) == 0) - v >>= 1; - - while (u != v) - { - if (u > v) - { - u -= v; - do - u >>= 1; - while ( (u & 1) == 0); - } - else - { - v -= u; - do - v >>= 1; - while ( (v & 1) == 0); - } - } - return u << shift; -} - -unsigned long -mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v) -{ - mpz_t t; - mpz_init_set_ui(t, v); - mpz_gcd (t, u, t); - if (v > 0) - v = mpz_get_ui (t); - - if (g) - mpz_swap (t, g); - - mpz_clear (t); - - return v; -} - -static mp_bitcnt_t -mpz_make_odd (mpz_t r) -{ - mp_bitcnt_t shift; - - assert (r->_mp_size > 0); - /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */ - shift = mpn_scan1 (r->_mp_d, 0); - mpz_tdiv_q_2exp (r, r, shift); - - return shift; -} - -void -mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v) -{ - mpz_t tu, tv; - mp_bitcnt_t uz, vz, gz; - - if (u->_mp_size == 0) - { - mpz_abs (g, v); - return; - } - if (v->_mp_size == 0) - { - mpz_abs (g, u); - return; - } - - mpz_init (tu); - mpz_init (tv); - - mpz_abs (tu, u); - uz = mpz_make_odd (tu); - mpz_abs (tv, v); - vz = mpz_make_odd (tv); - gz = GMP_MIN (uz, vz); - - if (tu->_mp_size < tv->_mp_size) - mpz_swap (tu, tv); - - mpz_tdiv_r (tu, tu, tv); - if (tu->_mp_size == 0) - { - mpz_swap (g, tv); - } - else - for (;;) - { - int c; - - mpz_make_odd (tu); - c = mpz_cmp (tu, tv); - if (c == 0) - { - mpz_swap (g, tu); - break; - } - if (c < 0) - mpz_swap (tu, tv); - - if (tv->_mp_size == 1) - { - mp_limb_t *gp; - - mpz_tdiv_r (tu, tu, tv); - gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */ - *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]); - - g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */ - break; - } - mpz_sub (tu, tu, tv); - } - mpz_clear (tu); - mpz_clear (tv); - mpz_mul_2exp (g, g, gz); -} - -void -mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v) -{ - mpz_t tu, tv, s0, s1, t0, t1; - mp_bitcnt_t uz, vz, gz; - mp_bitcnt_t power; - - if (u->_mp_size == 0) - { - /* g = 0 u + sgn(v) v */ - signed long sign = mpz_sgn (v); - mpz_abs (g, v); - if (s) - s->_mp_size = 0; - if (t) - mpz_set_si (t, sign); - return; - } - - if (v->_mp_size == 0) - { - /* g = sgn(u) u + 0 v */ - signed long sign = mpz_sgn (u); - mpz_abs (g, u); - if (s) - mpz_set_si (s, sign); - if (t) - t->_mp_size = 0; - return; - } - - mpz_init (tu); - mpz_init (tv); - mpz_init (s0); - mpz_init (s1); - mpz_init (t0); - mpz_init (t1); - - mpz_abs (tu, u); - uz = mpz_make_odd (tu); - mpz_abs (tv, v); - vz = mpz_make_odd (tv); - gz = GMP_MIN (uz, vz); - - uz -= gz; - vz -= gz; - - /* Cofactors corresponding to odd gcd. gz handled later. */ - if (tu->_mp_size < tv->_mp_size) - { - mpz_swap (tu, tv); - MPZ_SRCPTR_SWAP (u, v); - MPZ_PTR_SWAP (s, t); - MP_BITCNT_T_SWAP (uz, vz); - } - - /* Maintain - * - * u = t0 tu + t1 tv - * v = s0 tu + s1 tv - * - * where u and v denote the inputs with common factors of two - * eliminated, and det (s0, t0; s1, t1) = 2^p. Then - * - * 2^p tu = s1 u - t1 v - * 2^p tv = -s0 u + t0 v - */ - - /* After initial division, tu = q tv + tu', we have - * - * u = 2^uz (tu' + q tv) - * v = 2^vz tv - * - * or - * - * t0 = 2^uz, t1 = 2^uz q - * s0 = 0, s1 = 2^vz - */ - - mpz_tdiv_qr (t1, tu, tu, tv); - mpz_mul_2exp (t1, t1, uz); - - mpz_setbit (s1, vz); - power = uz + vz; - - if (tu->_mp_size > 0) - { - mp_bitcnt_t shift; - shift = mpz_make_odd (tu); - mpz_setbit (t0, uz + shift); - power += shift; - - for (;;) - { - int c; - c = mpz_cmp (tu, tv); - if (c == 0) - break; - - if (c < 0) - { - /* tv = tv' + tu - * - * u = t0 tu + t1 (tv' + tu) = (t0 + t1) tu + t1 tv' - * v = s0 tu + s1 (tv' + tu) = (s0 + s1) tu + s1 tv' */ - - mpz_sub (tv, tv, tu); - mpz_add (t0, t0, t1); - mpz_add (s0, s0, s1); - - shift = mpz_make_odd (tv); - mpz_mul_2exp (t1, t1, shift); - mpz_mul_2exp (s1, s1, shift); - } - else - { - mpz_sub (tu, tu, tv); - mpz_add (t1, t0, t1); - mpz_add (s1, s0, s1); - - shift = mpz_make_odd (tu); - mpz_mul_2exp (t0, t0, shift); - mpz_mul_2exp (s0, s0, shift); - } - power += shift; - } - } - else - mpz_setbit (t0, uz); - - /* Now tv = odd part of gcd, and -s0 and t0 are corresponding - cofactors. */ - - mpz_mul_2exp (tv, tv, gz); - mpz_neg (s0, s0); - - /* 2^p g = s0 u + t0 v. Eliminate one factor of two at a time. To - adjust cofactors, we need u / g and v / g */ - - mpz_divexact (s1, v, tv); - mpz_abs (s1, s1); - mpz_divexact (t1, u, tv); - mpz_abs (t1, t1); - - while (power-- > 0) - { - /* s0 u + t0 v = (s0 - v/g) u - (t0 + u/g) v */ - if (mpz_odd_p (s0) || mpz_odd_p (t0)) - { - mpz_sub (s0, s0, s1); - mpz_add (t0, t0, t1); - } - assert (mpz_even_p (t0) && mpz_even_p (s0)); - mpz_tdiv_q_2exp (s0, s0, 1); - mpz_tdiv_q_2exp (t0, t0, 1); - } - - /* Arrange so that |s| < |u| / 2g */ - mpz_add (s1, s0, s1); - if (mpz_cmpabs (s0, s1) > 0) - { - mpz_swap (s0, s1); - mpz_sub (t0, t0, t1); - } - if (u->_mp_size < 0) - mpz_neg (s0, s0); - if (v->_mp_size < 0) - mpz_neg (t0, t0); - - mpz_swap (g, tv); - if (s) - mpz_swap (s, s0); - if (t) - mpz_swap (t, t0); - - mpz_clear (tu); - mpz_clear (tv); - mpz_clear (s0); - mpz_clear (s1); - mpz_clear (t0); - mpz_clear (t1); -} - -void -mpz_lcm (mpz_t r, const mpz_t u, const mpz_t v) -{ - mpz_t g; - - if (u->_mp_size == 0 || v->_mp_size == 0) - { - r->_mp_size = 0; - return; - } - - mpz_init (g); - - mpz_gcd (g, u, v); - mpz_divexact (g, u, g); - mpz_mul (r, g, v); - - mpz_clear (g); - mpz_abs (r, r); -} - -void -mpz_lcm_ui (mpz_t r, const mpz_t u, unsigned long v) -{ - if (v == 0 || u->_mp_size == 0) - { - r->_mp_size = 0; - return; - } - - v /= mpz_gcd_ui (NULL, u, v); - mpz_mul_ui (r, u, v); - - mpz_abs (r, r); -} - -int -mpz_invert (mpz_t r, const mpz_t u, const mpz_t m) -{ - mpz_t g, tr; - int invertible; - - if (u->_mp_size == 0 || mpz_cmpabs_ui (m, 1) <= 0) - return 0; - - mpz_init (g); - mpz_init (tr); - - mpz_gcdext (g, tr, NULL, u, m); - invertible = (mpz_cmp_ui (g, 1) == 0); - - if (invertible) - { - if (tr->_mp_size < 0) - { - if (m->_mp_size >= 0) - mpz_add (tr, tr, m); - else - mpz_sub (tr, tr, m); - } - mpz_swap (r, tr); - } - - mpz_clear (g); - mpz_clear (tr); - return invertible; -} - - -/* Higher level operations (sqrt, pow and root) */ - -void -mpz_pow_ui (mpz_t r, const mpz_t b, unsigned long e) -{ - unsigned long bit; - mpz_t tr; - mpz_init_set_ui (tr, 1); - - bit = GMP_ULONG_HIGHBIT; - do - { - mpz_mul (tr, tr, tr); - if (e & bit) - mpz_mul (tr, tr, b); - bit >>= 1; - } - while (bit > 0); - - mpz_swap (r, tr); - mpz_clear (tr); -} - -void -mpz_ui_pow_ui (mpz_t r, unsigned long blimb, unsigned long e) -{ - mpz_t b; - - mpz_init_set_ui (b, blimb); - mpz_pow_ui (r, b, e); - mpz_clear (b); -} - -void -mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const mpz_t m) -{ - mpz_t tr; - mpz_t base; - mp_size_t en, mn; - mp_srcptr mp; - struct gmp_div_inverse minv; - unsigned shift; - mp_ptr tp = NULL; - - en = GMP_ABS (e->_mp_size); - mn = GMP_ABS (m->_mp_size); - if (mn == 0) - gmp_die ("mpz_powm: Zero modulo."); - - if (en == 0) - { - mpz_set_ui (r, mpz_cmpabs_ui (m, 1)); - return; - } - - mp = m->_mp_d; - mpn_div_qr_invert (&minv, mp, mn); - shift = minv.shift; - - if (shift > 0) - { - /* To avoid shifts, we do all our reductions, except the final - one, using a *normalized* m. */ - minv.shift = 0; - - tp = gmp_alloc_limbs (mn); - gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift)); - mp = tp; - } - - mpz_init (base); - - if (e->_mp_size < 0) - { - if (!mpz_invert (base, b, m)) - gmp_die ("mpz_powm: Negative exponent and non-invertible base."); - } - else - { - mp_size_t bn; - mpz_abs (base, b); - - bn = base->_mp_size; - if (bn >= mn) - { - mpn_div_qr_preinv (NULL, base->_mp_d, base->_mp_size, mp, mn, &minv); - bn = mn; - } - - /* We have reduced the absolute value. Now take care of the - sign. Note that we get zero represented non-canonically as - m. */ - if (b->_mp_size < 0) - { - mp_ptr bp = MPZ_REALLOC (base, mn); - gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn)); - bn = mn; - } - base->_mp_size = mpn_normalized_size (base->_mp_d, bn); - } - mpz_init_set_ui (tr, 1); - - while (--en >= 0) - { - mp_limb_t w = e->_mp_d[en]; - mp_limb_t bit; - - bit = GMP_LIMB_HIGHBIT; - do - { - mpz_mul (tr, tr, tr); - if (w & bit) - mpz_mul (tr, tr, base); - if (tr->_mp_size > mn) - { - mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); - tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); - } - bit >>= 1; - } - while (bit > 0); - } - - /* Final reduction */ - if (tr->_mp_size >= mn) - { - minv.shift = shift; - mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv); - tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn); - } - if (tp) - gmp_free_limbs (tp, mn); - - mpz_swap (r, tr); - mpz_clear (tr); - mpz_clear (base); -} - -void -mpz_powm_ui (mpz_t r, const mpz_t b, unsigned long elimb, const mpz_t m) -{ - mpz_t e; - - mpz_init_set_ui (e, elimb); - mpz_powm (r, b, e, m); - mpz_clear (e); -} - -/* x=trunc(y^(1/z)), r=y-x^z */ -void -mpz_rootrem (mpz_t x, mpz_t r, const mpz_t y, unsigned long z) -{ - int sgn; - mp_bitcnt_t bc; - mpz_t t, u; - - sgn = y->_mp_size < 0; - if ((~z & sgn) != 0) - gmp_die ("mpz_rootrem: Negative argument, with even root."); - if (z == 0) - gmp_die ("mpz_rootrem: Zeroth root."); - - if (mpz_cmpabs_ui (y, 1) <= 0) { - if (x) - mpz_set (x, y); - if (r) - r->_mp_size = 0; - return; - } - - mpz_init (u); - mpz_init (t); - bc = (mpz_sizeinbase (y, 2) - 1) / z + 1; - mpz_setbit (t, bc); - - if (z == 2) /* simplify sqrt loop: z-1 == 1 */ - do { - mpz_swap (u, t); /* u = x */ - mpz_tdiv_q (t, y, u); /* t = y/x */ - mpz_add (t, t, u); /* t = y/x + x */ - mpz_tdiv_q_2exp (t, t, 1); /* x'= (y/x + x)/2 */ - } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ - else /* z != 2 */ { - mpz_t v; - - mpz_init (v); - if (sgn) - mpz_neg (t, t); - - do { - mpz_swap (u, t); /* u = x */ - mpz_pow_ui (t, u, z - 1); /* t = x^(z-1) */ - mpz_tdiv_q (t, y, t); /* t = y/x^(z-1) */ - mpz_mul_ui (v, u, z - 1); /* v = x*(z-1) */ - mpz_add (t, t, v); /* t = y/x^(z-1) + x*(z-1) */ - mpz_tdiv_q_ui (t, t, z); /* x'=(y/x^(z-1) + x*(z-1))/z */ - } while (mpz_cmpabs (t, u) < 0); /* |x'| < |x| */ - - mpz_clear (v); - } - - if (r) { - mpz_pow_ui (t, u, z); - mpz_sub (r, y, t); - } - if (x) - mpz_swap (x, u); - mpz_clear (u); - mpz_clear (t); -} - -int -mpz_root (mpz_t x, const mpz_t y, unsigned long z) -{ - int res; - mpz_t r; - - mpz_init (r); - mpz_rootrem (x, r, y, z); - res = r->_mp_size == 0; - mpz_clear (r); - - return res; -} - -/* Compute s = floor(sqrt(u)) and r = u - s^2. Allows r == NULL */ -void -mpz_sqrtrem (mpz_t s, mpz_t r, const mpz_t u) -{ - mpz_rootrem (s, r, u, 2); -} - -void -mpz_sqrt (mpz_t s, const mpz_t u) -{ - mpz_rootrem (s, NULL, u, 2); -} - -int -mpz_perfect_square_p (const mpz_t u) -{ - if (u->_mp_size <= 0) - return (u->_mp_size == 0); - else - return mpz_root (NULL, u, 2); -} - -int -mpn_perfect_square_p (mp_srcptr p, mp_size_t n) -{ - mpz_t t; - - assert (n > 0); - assert (p [n-1] != 0); - return mpz_root (NULL, mpz_roinit_normal_n (t, p, n), 2); -} - -mp_size_t -mpn_sqrtrem (mp_ptr sp, mp_ptr rp, mp_srcptr p, mp_size_t n) -{ - mpz_t s, r, u; - mp_size_t res; - - assert (n > 0); - assert (p [n-1] != 0); - - mpz_init (r); - mpz_init (s); - mpz_rootrem (s, r, mpz_roinit_normal_n (u, p, n), 2); - - assert (s->_mp_size == (n+1)/2); - mpn_copyd (sp, s->_mp_d, s->_mp_size); - mpz_clear (s); - res = r->_mp_size; - if (rp) - mpn_copyd (rp, r->_mp_d, res); - mpz_clear (r); - return res; -} - -/* Combinatorics */ - -void -mpz_mfac_uiui (mpz_t x, unsigned long n, unsigned long m) -{ - mpz_set_ui (x, n + (n == 0)); - if (m + 1 < 2) return; - while (n > m + 1) - mpz_mul_ui (x, x, n -= m); -} - -void -mpz_2fac_ui (mpz_t x, unsigned long n) -{ - mpz_mfac_uiui (x, n, 2); -} - -void -mpz_fac_ui (mpz_t x, unsigned long n) -{ - mpz_mfac_uiui (x, n, 1); -} - -void -mpz_bin_uiui (mpz_t r, unsigned long n, unsigned long k) -{ - mpz_t t; - - mpz_set_ui (r, k <= n); - - if (k > (n >> 1)) - k = (k <= n) ? n - k : 0; - - mpz_init (t); - mpz_fac_ui (t, k); - - for (; k > 0; --k) - mpz_mul_ui (r, r, n--); - - mpz_divexact (r, r, t); - mpz_clear (t); -} - - -/* Primality testing */ - -/* Computes Kronecker (a/b) with odd b, a!=0 and GCD(a,b) = 1 */ -/* Adapted from JACOBI_BASE_METHOD==4 in mpn/generic/jacbase.c */ -static int -gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b) -{ - int c, bit = 0; - - assert (b & 1); - assert (a != 0); - /* assert (mpn_gcd_11 (a, b) == 1); */ - - /* Below, we represent a and b shifted right so that the least - significant one bit is implicit. */ - b >>= 1; - - gmp_ctz(c, a); - a >>= 1; - - for (;;) - { - a >>= c; - /* (2/b) = -1 if b = 3 or 5 mod 8 */ - bit ^= c & (b ^ (b >> 1)); - if (a < b) - { - if (a == 0) - return bit & 1 ? -1 : 1; - bit ^= a & b; - a = b - a; - b -= a; - } - else - { - a -= b; - assert (a != 0); - } - - gmp_ctz(c, a); - ++c; - } -} - -static void -gmp_lucas_step_k_2k (mpz_t V, mpz_t Qk, const mpz_t n) -{ - mpz_mod (Qk, Qk, n); - /* V_{2k} <- V_k ^ 2 - 2Q^k */ - mpz_mul (V, V, V); - mpz_submul_ui (V, Qk, 2); - mpz_tdiv_r (V, V, n); - /* Q^{2k} = (Q^k)^2 */ - mpz_mul (Qk, Qk, Qk); -} - -/* Computes V_k, Q^k (mod n) for the Lucas' sequence */ -/* with P=1, Q=Q; k = (n>>b0)|1. */ -/* Requires an odd n > 4; b0 > 0; -2*Q must not overflow a long */ -/* Returns (U_k == 0) and sets V=V_k and Qk=Q^k. */ -static int -gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q, - mp_bitcnt_t b0, const mpz_t n) -{ - mp_bitcnt_t bs; - mpz_t U; - int res; - - assert (b0 > 0); - assert (Q <= - (LONG_MIN / 2)); - assert (Q >= - (LONG_MAX / 2)); - assert (mpz_cmp_ui (n, 4) > 0); - assert (mpz_odd_p (n)); - - mpz_init_set_ui (U, 1); /* U1 = 1 */ - mpz_set_ui (V, 1); /* V1 = 1 */ - mpz_set_si (Qk, Q); - - for (bs = mpz_sizeinbase (n, 2) - 1; --bs >= b0;) - { - /* U_{2k} <- U_k * V_k */ - mpz_mul (U, U, V); - /* V_{2k} <- V_k ^ 2 - 2Q^k */ - /* Q^{2k} = (Q^k)^2 */ - gmp_lucas_step_k_2k (V, Qk, n); - - /* A step k->k+1 is performed if the bit in $n$ is 1 */ - /* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */ - /* should be 1 in $n+1$ (bs == b0) */ - if (b0 == bs || mpz_tstbit (n, bs)) - { - /* Q^{k+1} <- Q^k * Q */ - mpz_mul_si (Qk, Qk, Q); - /* U_{k+1} <- (U_k + V_k) / 2 */ - mpz_swap (U, V); /* Keep in V the old value of U_k */ - mpz_add (U, U, V); - /* We have to compute U/2, so we need an even value, */ - /* equivalent (mod n) */ - if (mpz_odd_p (U)) - mpz_add (U, U, n); - mpz_tdiv_q_2exp (U, U, 1); - /* V_{k+1} <-(D*U_k + V_k) / 2 = - U_{k+1} + (D-1)/2*U_k = U_{k+1} - 2Q*U_k */ - mpz_mul_si (V, V, -2*Q); - mpz_add (V, U, V); - mpz_tdiv_r (V, V, n); - } - mpz_tdiv_r (U, U, n); - } - - res = U->_mp_size == 0; - mpz_clear (U); - return res; -} - -/* Performs strong Lucas' test on x, with parameters suggested */ -/* for the BPSW test. Qk is only passed to recycle a variable. */ -/* Requires GCD (x,6) = 1.*/ -static int -gmp_stronglucas (const mpz_t x, mpz_t Qk) -{ - mp_bitcnt_t b0; - mpz_t V, n; - mp_limb_t maxD, D; /* The absolute value is stored. */ - long Q; - mp_limb_t tl; - - /* Test on the absolute value. */ - mpz_roinit_normal_n (n, x->_mp_d, GMP_ABS (x->_mp_size)); - - assert (mpz_odd_p (n)); - /* assert (mpz_gcd_ui (NULL, n, 6) == 1); */ - if (mpz_root (Qk, n, 2)) - return 0; /* A square is composite. */ - - /* Check Ds up to square root (in case, n is prime) - or avoid overflows */ - maxD = (Qk->_mp_size == 1) ? Qk->_mp_d [0] - 1 : GMP_LIMB_MAX; - - D = 3; - /* Search a D such that (D/n) = -1 in the sequence 5,-7,9,-11,.. */ - /* For those Ds we have (D/n) = (n/|D|) */ - do - { - if (D >= maxD) - return 1 + (D != GMP_LIMB_MAX); /* (1 + ! ~ D) */ - D += 2; - tl = mpz_tdiv_ui (n, D); - if (tl == 0) - return 0; - } - while (gmp_jacobi_coprime (tl, D) == 1); - - mpz_init (V); - - /* n-(D/n) = n+1 = d*2^{b0}, with d = (n>>b0) | 1 */ - b0 = mpn_common_scan (~ n->_mp_d[0], 0, n->_mp_d, n->_mp_size, GMP_LIMB_MAX); - /* b0 = mpz_scan0 (n, 0); */ - - /* D= P^2 - 4Q; P = 1; Q = (1-D)/4 */ - Q = (D & 2) ? (long) (D >> 2) + 1 : -(long) (D >> 2); - - if (! gmp_lucas_mod (V, Qk, Q, b0, n)) /* If Ud != 0 */ - while (V->_mp_size != 0 && --b0 != 0) /* while Vk != 0 */ - /* V <- V ^ 2 - 2Q^k */ - /* Q^{2k} = (Q^k)^2 */ - gmp_lucas_step_k_2k (V, Qk, n); - - mpz_clear (V); - return (b0 != 0); -} - -static int -gmp_millerrabin (const mpz_t n, const mpz_t nm1, mpz_t y, - const mpz_t q, mp_bitcnt_t k) -{ - assert (k > 0); - - /* Caller must initialize y to the base. */ - mpz_powm (y, y, q, n); - - if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0) - return 1; - - while (--k > 0) - { - mpz_powm_ui (y, y, 2, n); - if (mpz_cmp (y, nm1) == 0) - return 1; - } - return 0; -} - -/* This product is 0xc0cfd797, and fits in 32 bits. */ -#define GMP_PRIME_PRODUCT \ - (3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL) - -/* Bit (p+1)/2 is set, for each odd prime <= 61 */ -#define GMP_PRIME_MASK 0xc96996dcUL - -int -mpz_probab_prime_p (const mpz_t n, int reps) -{ - mpz_t nm1; - mpz_t q; - mpz_t y; - mp_bitcnt_t k; - int is_prime; - int j; - - /* Note that we use the absolute value of n only, for compatibility - with the real GMP. */ - if (mpz_even_p (n)) - return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0; - - /* Above test excludes n == 0 */ - assert (n->_mp_size != 0); - - if (mpz_cmpabs_ui (n, 64) < 0) - return (GMP_PRIME_MASK >> (n->_mp_d[0] >> 1)) & 2; - - if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1) - return 0; - - /* All prime factors are >= 31. */ - if (mpz_cmpabs_ui (n, 31*31) < 0) - return 2; - - mpz_init (nm1); - mpz_init (q); - - /* Find q and k, where q is odd and n = 1 + 2**k * q. */ - mpz_abs (nm1, n); - nm1->_mp_d[0] -= 1; - /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */ - k = mpn_scan1 (nm1->_mp_d, 0); - mpz_tdiv_q_2exp (q, nm1, k); - - /* BPSW test */ - mpz_init_set_ui (y, 2); - is_prime = gmp_millerrabin (n, nm1, y, q, k) && gmp_stronglucas (n, y); - reps -= 24; /* skip the first 24 repetitions */ - - /* Use Miller-Rabin, with a deterministic sequence of bases, a[j] = - j^2 + j + 41 using Euler's polynomial. We potentially stop early, - if a[j] >= n - 1. Since n >= 31*31, this can happen only if reps > - 30 (a[30] == 971 > 31*31 == 961). */ - - for (j = 0; is_prime & (j < reps); j++) - { - mpz_set_ui (y, (unsigned long) j*j+j+41); - if (mpz_cmp (y, nm1) >= 0) - { - /* Don't try any further bases. This "early" break does not affect - the result for any reasonable reps value (<=5000 was tested) */ - assert (j >= 30); - break; - } - is_prime = gmp_millerrabin (n, nm1, y, q, k); - } - mpz_clear (nm1); - mpz_clear (q); - mpz_clear (y); - - return is_prime; -} - - -/* Logical operations and bit manipulation. */ - -/* Numbers are treated as if represented in two's complement (and - infinitely sign extended). For a negative values we get the two's - complement from -x = ~x + 1, where ~ is bitwise complement. - Negation transforms - - xxxx10...0 - - into - - yyyy10...0 - - where yyyy is the bitwise complement of xxxx. So least significant - bits, up to and including the first one bit, are unchanged, and - the more significant bits are all complemented. - - To change a bit from zero to one in a negative number, subtract the - corresponding power of two from the absolute value. This can never - underflow. To change a bit from one to zero, add the corresponding - power of two, and this might overflow. E.g., if x = -001111, the - two's complement is 110001. Clearing the least significant bit, we - get two's complement 110000, and -010000. */ - -int -mpz_tstbit (const mpz_t d, mp_bitcnt_t bit_index) -{ - mp_size_t limb_index; - unsigned shift; - mp_size_t ds; - mp_size_t dn; - mp_limb_t w; - int bit; - - ds = d->_mp_size; - dn = GMP_ABS (ds); - limb_index = bit_index / GMP_LIMB_BITS; - if (limb_index >= dn) - return ds < 0; - - shift = bit_index % GMP_LIMB_BITS; - w = d->_mp_d[limb_index]; - bit = (w >> shift) & 1; - - if (ds < 0) - { - /* d < 0. Check if any of the bits below is set: If so, our bit - must be complemented. */ - if (shift > 0 && (mp_limb_t) (w << (GMP_LIMB_BITS - shift)) > 0) - return bit ^ 1; - while (--limb_index >= 0) - if (d->_mp_d[limb_index] > 0) - return bit ^ 1; - } - return bit; -} - -static void -mpz_abs_add_bit (mpz_t d, mp_bitcnt_t bit_index) -{ - mp_size_t dn, limb_index; - mp_limb_t bit; - mp_ptr dp; - - dn = GMP_ABS (d->_mp_size); - - limb_index = bit_index / GMP_LIMB_BITS; - bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); - - if (limb_index >= dn) - { - mp_size_t i; - /* The bit should be set outside of the end of the number. - We have to increase the size of the number. */ - dp = MPZ_REALLOC (d, limb_index + 1); - - dp[limb_index] = bit; - for (i = dn; i < limb_index; i++) - dp[i] = 0; - dn = limb_index + 1; - } - else - { - mp_limb_t cy; - - dp = d->_mp_d; - - cy = mpn_add_1 (dp + limb_index, dp + limb_index, dn - limb_index, bit); - if (cy > 0) - { - dp = MPZ_REALLOC (d, dn + 1); - dp[dn++] = cy; - } - } - - d->_mp_size = (d->_mp_size < 0) ? - dn : dn; -} - -static void -mpz_abs_sub_bit (mpz_t d, mp_bitcnt_t bit_index) -{ - mp_size_t dn, limb_index; - mp_ptr dp; - mp_limb_t bit; - - dn = GMP_ABS (d->_mp_size); - dp = d->_mp_d; - - limb_index = bit_index / GMP_LIMB_BITS; - bit = (mp_limb_t) 1 << (bit_index % GMP_LIMB_BITS); - - assert (limb_index < dn); - - gmp_assert_nocarry (mpn_sub_1 (dp + limb_index, dp + limb_index, - dn - limb_index, bit)); - dn = mpn_normalized_size (dp, dn); - d->_mp_size = (d->_mp_size < 0) ? - dn : dn; -} - -void -mpz_setbit (mpz_t d, mp_bitcnt_t bit_index) -{ - if (!mpz_tstbit (d, bit_index)) - { - if (d->_mp_size >= 0) - mpz_abs_add_bit (d, bit_index); - else - mpz_abs_sub_bit (d, bit_index); - } -} - -void -mpz_clrbit (mpz_t d, mp_bitcnt_t bit_index) -{ - if (mpz_tstbit (d, bit_index)) - { - if (d->_mp_size >= 0) - mpz_abs_sub_bit (d, bit_index); - else - mpz_abs_add_bit (d, bit_index); - } -} - -void -mpz_combit (mpz_t d, mp_bitcnt_t bit_index) -{ - if (mpz_tstbit (d, bit_index) ^ (d->_mp_size < 0)) - mpz_abs_sub_bit (d, bit_index); - else - mpz_abs_add_bit (d, bit_index); -} - -void -mpz_com (mpz_t r, const mpz_t u) -{ - mpz_add_ui (r, u, 1); - mpz_neg (r, r); -} - -void -mpz_and (mpz_t r, const mpz_t u, const mpz_t v) -{ - mp_size_t un, vn, rn, i; - mp_ptr up, vp, rp; - - mp_limb_t ux, vx, rx; - mp_limb_t uc, vc, rc; - mp_limb_t ul, vl, rl; - - un = GMP_ABS (u->_mp_size); - vn = GMP_ABS (v->_mp_size); - if (un < vn) - { - MPZ_SRCPTR_SWAP (u, v); - MP_SIZE_T_SWAP (un, vn); - } - if (vn == 0) - { - r->_mp_size = 0; - return; - } - - uc = u->_mp_size < 0; - vc = v->_mp_size < 0; - rc = uc & vc; - - ux = -uc; - vx = -vc; - rx = -rc; - - /* If the smaller input is positive, higher limbs don't matter. */ - rn = vx ? un : vn; - - rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); - - up = u->_mp_d; - vp = v->_mp_d; - - i = 0; - do - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - vl = (vp[i] ^ vx) + vc; - vc = vl < vc; - - rl = ( (ul & vl) ^ rx) + rc; - rc = rl < rc; - rp[i] = rl; - } - while (++i < vn); - assert (vc == 0); - - for (; i < rn; i++) - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - rl = ( (ul & vx) ^ rx) + rc; - rc = rl < rc; - rp[i] = rl; - } - if (rc) - rp[rn++] = rc; - else - rn = mpn_normalized_size (rp, rn); - - r->_mp_size = rx ? -rn : rn; -} - -void -mpz_ior (mpz_t r, const mpz_t u, const mpz_t v) -{ - mp_size_t un, vn, rn, i; - mp_ptr up, vp, rp; - - mp_limb_t ux, vx, rx; - mp_limb_t uc, vc, rc; - mp_limb_t ul, vl, rl; - - un = GMP_ABS (u->_mp_size); - vn = GMP_ABS (v->_mp_size); - if (un < vn) - { - MPZ_SRCPTR_SWAP (u, v); - MP_SIZE_T_SWAP (un, vn); - } - if (vn == 0) - { - mpz_set (r, u); - return; - } - - uc = u->_mp_size < 0; - vc = v->_mp_size < 0; - rc = uc | vc; - - ux = -uc; - vx = -vc; - rx = -rc; - - /* If the smaller input is negative, by sign extension higher limbs - don't matter. */ - rn = vx ? vn : un; - - rp = MPZ_REALLOC (r, rn + (mp_size_t) rc); - - up = u->_mp_d; - vp = v->_mp_d; - - i = 0; - do - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - vl = (vp[i] ^ vx) + vc; - vc = vl < vc; - - rl = ( (ul | vl) ^ rx) + rc; - rc = rl < rc; - rp[i] = rl; - } - while (++i < vn); - assert (vc == 0); - - for (; i < rn; i++) - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - rl = ( (ul | vx) ^ rx) + rc; - rc = rl < rc; - rp[i] = rl; - } - if (rc) - rp[rn++] = rc; - else - rn = mpn_normalized_size (rp, rn); - - r->_mp_size = rx ? -rn : rn; -} - -void -mpz_xor (mpz_t r, const mpz_t u, const mpz_t v) -{ - mp_size_t un, vn, i; - mp_ptr up, vp, rp; - - mp_limb_t ux, vx, rx; - mp_limb_t uc, vc, rc; - mp_limb_t ul, vl, rl; - - un = GMP_ABS (u->_mp_size); - vn = GMP_ABS (v->_mp_size); - if (un < vn) - { - MPZ_SRCPTR_SWAP (u, v); - MP_SIZE_T_SWAP (un, vn); - } - if (vn == 0) - { - mpz_set (r, u); - return; - } - - uc = u->_mp_size < 0; - vc = v->_mp_size < 0; - rc = uc ^ vc; - - ux = -uc; - vx = -vc; - rx = -rc; - - rp = MPZ_REALLOC (r, un + (mp_size_t) rc); - - up = u->_mp_d; - vp = v->_mp_d; - - i = 0; - do - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - vl = (vp[i] ^ vx) + vc; - vc = vl < vc; - - rl = (ul ^ vl ^ rx) + rc; - rc = rl < rc; - rp[i] = rl; - } - while (++i < vn); - assert (vc == 0); - - for (; i < un; i++) - { - ul = (up[i] ^ ux) + uc; - uc = ul < uc; - - rl = (ul ^ ux) + rc; - rc = rl < rc; - rp[i] = rl; - } - if (rc) - rp[un++] = rc; - else - un = mpn_normalized_size (rp, un); - - r->_mp_size = rx ? -un : un; -} - -static unsigned -gmp_popcount_limb (mp_limb_t x) -{ - unsigned c; - - /* Do 16 bits at a time, to avoid limb-sized constants. */ - int LOCAL_SHIFT_BITS = 16; - for (c = 0; x > 0;) - { - unsigned w = x - ((x >> 1) & 0x5555); - w = ((w >> 2) & 0x3333) + (w & 0x3333); - w = (w >> 4) + w; - w = ((w >> 8) & 0x000f) + (w & 0x000f); - c += w; - if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS) - x >>= LOCAL_SHIFT_BITS; - else - x = 0; - } - return c; -} - -mp_bitcnt_t -mpn_popcount (mp_srcptr p, mp_size_t n) -{ - mp_size_t i; - mp_bitcnt_t c; - - for (c = 0, i = 0; i < n; i++) - c += gmp_popcount_limb (p[i]); - - return c; -} - -mp_bitcnt_t -mpz_popcount (const mpz_t u) -{ - mp_size_t un; - - un = u->_mp_size; - - if (un < 0) - return ~(mp_bitcnt_t) 0; - - return mpn_popcount (u->_mp_d, un); -} - -mp_bitcnt_t -mpz_hamdist (const mpz_t u, const mpz_t v) -{ - mp_size_t un, vn, i; - mp_limb_t uc, vc, ul, vl, comp; - mp_srcptr up, vp; - mp_bitcnt_t c; - - un = u->_mp_size; - vn = v->_mp_size; - - if ( (un ^ vn) < 0) - return ~(mp_bitcnt_t) 0; - - comp = - (uc = vc = (un < 0)); - if (uc) - { - assert (vn < 0); - un = -un; - vn = -vn; - } - - up = u->_mp_d; - vp = v->_mp_d; - - if (un < vn) - MPN_SRCPTR_SWAP (up, un, vp, vn); - - for (i = 0, c = 0; i < vn; i++) - { - ul = (up[i] ^ comp) + uc; - uc = ul < uc; - - vl = (vp[i] ^ comp) + vc; - vc = vl < vc; - - c += gmp_popcount_limb (ul ^ vl); - } - assert (vc == 0); - - for (; i < un; i++) - { - ul = (up[i] ^ comp) + uc; - uc = ul < uc; - - c += gmp_popcount_limb (ul ^ comp); - } - - return c; -} - -mp_bitcnt_t -mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit) -{ - mp_ptr up; - mp_size_t us, un, i; - mp_limb_t limb, ux; - - us = u->_mp_size; - un = GMP_ABS (us); - i = starting_bit / GMP_LIMB_BITS; - - /* Past the end there's no 1 bits for u>=0, or an immediate 1 bit - for u<0. Notice this test picks up any u==0 too. */ - if (i >= un) - return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit); - - up = u->_mp_d; - ux = 0; - limb = up[i]; - - if (starting_bit != 0) - { - if (us < 0) - { - ux = mpn_zero_p (up, i); - limb = ~ limb + ux; - ux = - (mp_limb_t) (limb >= ux); - } - - /* Mask to 0 all bits before starting_bit, thus ignoring them. */ - limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS); - } - - return mpn_common_scan (limb, i, up, un, ux); -} - -mp_bitcnt_t -mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit) -{ - mp_ptr up; - mp_size_t us, un, i; - mp_limb_t limb, ux; - - us = u->_mp_size; - ux = - (mp_limb_t) (us >= 0); - un = GMP_ABS (us); - i = starting_bit / GMP_LIMB_BITS; - - /* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for - u<0. Notice this test picks up all cases of u==0 too. */ - if (i >= un) - return (ux ? starting_bit : ~(mp_bitcnt_t) 0); - - up = u->_mp_d; - limb = up[i] ^ ux; - - if (ux == 0) - limb -= mpn_zero_p (up, i); /* limb = ~(~limb + zero_p) */ - - /* Mask all bits before starting_bit, thus ignoring them. */ - limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS); - - return mpn_common_scan (limb, i, up, un, ux); -} - - -/* MPZ base conversion. */ - -size_t -mpz_sizeinbase (const mpz_t u, int base) -{ - mp_size_t un, tn; - mp_srcptr up; - mp_ptr tp; - mp_bitcnt_t bits; - struct gmp_div_inverse bi; - size_t ndigits; - - assert (base >= 2); - assert (base <= 62); - - un = GMP_ABS (u->_mp_size); - if (un == 0) - return 1; - - up = u->_mp_d; - - bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2 (up[un-1]); - switch (base) - { - case 2: - return bits; - case 4: - return (bits + 1) / 2; - case 8: - return (bits + 2) / 3; - case 16: - return (bits + 3) / 4; - case 32: - return (bits + 4) / 5; - /* FIXME: Do something more clever for the common case of base - 10. */ - } - - tp = gmp_alloc_limbs (un); - mpn_copyi (tp, up, un); - mpn_div_qr_1_invert (&bi, base); - - tn = un; - ndigits = 0; - do - { - ndigits++; - mpn_div_qr_1_preinv (tp, tp, tn, &bi); - tn -= (tp[tn-1] == 0); - } - while (tn > 0); - - gmp_free_limbs (tp, un); - return ndigits; -} - -char * -mpz_get_str (char *sp, int base, const mpz_t u) -{ - unsigned bits; - const char *digits; - mp_size_t un; - size_t i, sn, osn; - - digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - if (base > 1) - { - if (base <= 36) - digits = "0123456789abcdefghijklmnopqrstuvwxyz"; - else if (base > 62) - return NULL; - } - else if (base >= -1) - base = 10; - else - { - base = -base; - if (base > 36) - return NULL; - } - - sn = 1 + mpz_sizeinbase (u, base); - if (!sp) - { - osn = 1 + sn; - sp = (char *) gmp_alloc (osn); - } - else - osn = 0; - un = GMP_ABS (u->_mp_size); - - if (un == 0) - { - sp[0] = '0'; - sn = 1; - goto ret; - } - - i = 0; - - if (u->_mp_size < 0) - sp[i++] = '-'; - - bits = mpn_base_power_of_two_p (base); - - if (bits) - /* Not modified in this case. */ - sn = i + mpn_get_str_bits ((unsigned char *) sp + i, bits, u->_mp_d, un); - else - { - struct mpn_base_info info; - mp_ptr tp; - - mpn_get_base_info (&info, base); - tp = gmp_alloc_limbs (un); - mpn_copyi (tp, u->_mp_d, un); - - sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, un); - gmp_free_limbs (tp, un); - } - - for (; i < sn; i++) - sp[i] = digits[(unsigned char) sp[i]]; - -ret: - sp[sn] = '\0'; - if (osn && osn != sn + 1) - sp = (char*) gmp_realloc (sp, osn, sn + 1); - return sp; -} - -int -mpz_set_str (mpz_t r, const char *sp, int base) -{ - unsigned bits, value_of_a; - mp_size_t rn, alloc; - mp_ptr rp; - size_t dn, sn; - int sign; - unsigned char *dp; - - assert (base == 0 || (base >= 2 && base <= 62)); - - while (isspace( (unsigned char) *sp)) - sp++; - - sign = (*sp == '-'); - sp += sign; - - if (base == 0) - { - if (sp[0] == '0') - { - if (sp[1] == 'x' || sp[1] == 'X') - { - base = 16; - sp += 2; - } - else if (sp[1] == 'b' || sp[1] == 'B') - { - base = 2; - sp += 2; - } - else - base = 8; - } - else - base = 10; - } - - if (!*sp) - { - r->_mp_size = 0; - return -1; - } - sn = strlen(sp); - dp = (unsigned char *) gmp_alloc (sn); - - value_of_a = (base > 36) ? 36 : 10; - for (dn = 0; *sp; sp++) - { - unsigned digit; - - if (isspace ((unsigned char) *sp)) - continue; - else if (*sp >= '0' && *sp <= '9') - digit = *sp - '0'; - else if (*sp >= 'a' && *sp <= 'z') - digit = *sp - 'a' + value_of_a; - else if (*sp >= 'A' && *sp <= 'Z') - digit = *sp - 'A' + 10; - else - digit = base; /* fail */ - - if (digit >= (unsigned) base) - { - gmp_free (dp, sn); - r->_mp_size = 0; - return -1; - } - - dp[dn++] = digit; - } - - if (!dn) - { - gmp_free (dp, sn); - r->_mp_size = 0; - return -1; - } - bits = mpn_base_power_of_two_p (base); - - if (bits > 0) - { - alloc = (dn * bits + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; - rp = MPZ_REALLOC (r, alloc); - rn = mpn_set_str_bits (rp, dp, dn, bits); - } - else - { - struct mpn_base_info info; - mpn_get_base_info (&info, base); - alloc = (dn + info.exp - 1) / info.exp; - rp = MPZ_REALLOC (r, alloc); - rn = mpn_set_str_other (rp, dp, dn, base, &info); - /* Normalization, needed for all-zero input. */ - assert (rn > 0); - rn -= rp[rn-1] == 0; - } - assert (rn <= alloc); - gmp_free (dp, sn); - - r->_mp_size = sign ? - rn : rn; - - return 0; -} - -int -mpz_init_set_str (mpz_t r, const char *sp, int base) -{ - mpz_init (r); - return mpz_set_str (r, sp, base); -} - -size_t -mpz_out_str (FILE *stream, int base, const mpz_t x) -{ - char *str; - size_t len, n; - - str = mpz_get_str (NULL, base, x); - if (!str) - return 0; - len = strlen (str); - n = fwrite (str, 1, len, stream); - gmp_free (str, len + 1); - return n; -} - - -static int -gmp_detect_endian (void) -{ - static const int i = 2; - const unsigned char *p = (const unsigned char *) &i; - return 1 - *p; -} - -/* Import and export. Does not support nails. */ -void -mpz_import (mpz_t r, size_t count, int order, size_t size, int endian, - size_t nails, const void *src) -{ - const unsigned char *p; - ptrdiff_t word_step; - mp_ptr rp; - mp_size_t rn; - - /* The current (partial) limb. */ - mp_limb_t limb; - /* The number of bytes already copied to this limb (starting from - the low end). */ - size_t bytes; - /* The index where the limb should be stored, when completed. */ - mp_size_t i; - - if (nails != 0) - gmp_die ("mpz_import: Nails not supported."); - - assert (order == 1 || order == -1); - assert (endian >= -1 && endian <= 1); - - if (endian == 0) - endian = gmp_detect_endian (); - - p = (unsigned char *) src; - - word_step = (order != endian) ? 2 * size : 0; - - /* Process bytes from the least significant end, so point p at the - least significant word. */ - if (order == 1) - { - p += size * (count - 1); - word_step = - word_step; - } - - /* And at least significant byte of that word. */ - if (endian == 1) - p += (size - 1); - - rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t); - rp = MPZ_REALLOC (r, rn); - - for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step) - { - size_t j; - for (j = 0; j < size; j++, p -= (ptrdiff_t) endian) - { - limb |= (mp_limb_t) *p << (bytes++ * CHAR_BIT); - if (bytes == sizeof(mp_limb_t)) - { - rp[i++] = limb; - bytes = 0; - limb = 0; - } - } - } - assert (i + (bytes > 0) == rn); - if (limb != 0) - rp[i++] = limb; - else - i = mpn_normalized_size (rp, i); - - r->_mp_size = i; -} - -void * -mpz_export (void *r, size_t *countp, int order, size_t size, int endian, - size_t nails, const mpz_t u) -{ - size_t count; - mp_size_t un; - - if (nails != 0) - gmp_die ("mpz_export: Nails not supported."); - - assert (order == 1 || order == -1); - assert (endian >= -1 && endian <= 1); - assert (size > 0 || u->_mp_size == 0); - - un = u->_mp_size; - count = 0; - if (un != 0) - { - size_t k; - unsigned char *p; - ptrdiff_t word_step; - /* The current (partial) limb. */ - mp_limb_t limb; - /* The number of bytes left to do in this limb. */ - size_t bytes; - /* The index where the limb was read. */ - mp_size_t i; - - un = GMP_ABS (un); - - /* Count bytes in top limb. */ - limb = u->_mp_d[un-1]; - assert (limb != 0); - - k = (GMP_LIMB_BITS <= CHAR_BIT); - if (!k) - { - do { - int LOCAL_CHAR_BIT = CHAR_BIT; - k++; limb >>= LOCAL_CHAR_BIT; - } while (limb != 0); - } - /* else limb = 0; */ - - count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size; - - if (!r) - r = gmp_alloc (count * size); - - if (endian == 0) - endian = gmp_detect_endian (); - - p = (unsigned char *) r; - - word_step = (order != endian) ? 2 * size : 0; - - /* Process bytes from the least significant end, so point p at the - least significant word. */ - if (order == 1) - { - p += size * (count - 1); - word_step = - word_step; - } - - /* And at least significant byte of that word. */ - if (endian == 1) - p += (size - 1); - - for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step) - { - size_t j; - for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian) - { - if (sizeof (mp_limb_t) == 1) - { - if (i < un) - *p = u->_mp_d[i++]; - else - *p = 0; - } - else - { - int LOCAL_CHAR_BIT = CHAR_BIT; - if (bytes == 0) - { - if (i < un) - limb = u->_mp_d[i++]; - bytes = sizeof (mp_limb_t); - } - *p = limb; - limb >>= LOCAL_CHAR_BIT; - bytes--; - } - } - } - assert (i == un); - assert (k == count); - } - - if (countp) - *countp = count; - - return r; -} diff --git a/xcompile/lib/mini-gmp.h b/xcompile/lib/mini-gmp.h deleted file mode 100644 index 59c24cf5111..00000000000 --- a/xcompile/lib/mini-gmp.h +++ /dev/null @@ -1,310 +0,0 @@ -/* mini-gmp, a minimalistic implementation of a GNU GMP subset. - -Copyright 2011-2015, 2017, 2019-2021 Free Software Foundation, Inc. - -This file is part of the GNU MP Library. - -The GNU MP Library is free software; you can redistribute it and/or modify -it under the terms of either: - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at your - option) any later version. - -or - - * the GNU General Public License as published by the Free Software - Foundation; either version 2 of the License, or (at your option) any - later version. - -or both in parallel, as here. - -The GNU MP 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 General Public License -for more details. - -You should have received copies of the GNU General Public License and the -GNU Lesser General Public License along with the GNU MP Library. If not, -see https://www.gnu.org/licenses/. */ - -/* About mini-gmp: This is a minimal implementation of a subset of the - GMP interface. It is intended for inclusion into applications which - have modest bignums needs, as a fallback when the real GMP library - is not installed. - - This file defines the public interface. */ - -#ifndef __MINI_GMP_H__ -#define __MINI_GMP_H__ - -/* For size_t */ -#include - -#if defined (__cplusplus) -extern "C" { -#endif - -void mp_set_memory_functions (void *(*) (size_t), - void *(*) (void *, size_t, size_t), - void (*) (void *, size_t)); - -void mp_get_memory_functions (void *(**) (size_t), - void *(**) (void *, size_t, size_t), - void (**) (void *, size_t)); - -#ifndef MINI_GMP_LIMB_TYPE -#define MINI_GMP_LIMB_TYPE long -#endif - -typedef unsigned MINI_GMP_LIMB_TYPE mp_limb_t; -typedef long mp_size_t; -typedef unsigned long mp_bitcnt_t; - -typedef mp_limb_t *mp_ptr; -typedef const mp_limb_t *mp_srcptr; - -typedef struct -{ - int _mp_alloc; /* Number of *limbs* allocated and pointed - to by the _mp_d field. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ -} __mpz_struct; - -typedef __mpz_struct mpz_t[1]; - -typedef __mpz_struct *mpz_ptr; -typedef const __mpz_struct *mpz_srcptr; - -extern const int mp_bits_per_limb; - -void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t); -void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t); -void mpn_zero (mp_ptr, mp_size_t); - -int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t); -int mpn_zero_p (mp_srcptr, mp_size_t); - -mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); -mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); - -mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); -mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); - -mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); -mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); -mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); - -mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t); -void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t); -void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t); -int mpn_perfect_square_p (mp_srcptr, mp_size_t); -mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t); - -mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); -mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int); - -mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t); -mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t); - -void mpn_com (mp_ptr, mp_srcptr, mp_size_t); -mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t); - -mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t); - -mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t); -#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0) - -size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t); -mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int); - -void mpz_init (mpz_t); -void mpz_init2 (mpz_t, mp_bitcnt_t); -void mpz_clear (mpz_t); - -#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0]) -#define mpz_even_p(z) (! mpz_odd_p (z)) - -int mpz_sgn (const mpz_t); -int mpz_cmp_si (const mpz_t, long); -int mpz_cmp_ui (const mpz_t, unsigned long); -int mpz_cmp (const mpz_t, const mpz_t); -int mpz_cmpabs_ui (const mpz_t, unsigned long); -int mpz_cmpabs (const mpz_t, const mpz_t); -int mpz_cmp_d (const mpz_t, double); -int mpz_cmpabs_d (const mpz_t, double); - -void mpz_abs (mpz_t, const mpz_t); -void mpz_neg (mpz_t, const mpz_t); -void mpz_swap (mpz_t, mpz_t); - -void mpz_add_ui (mpz_t, const mpz_t, unsigned long); -void mpz_add (mpz_t, const mpz_t, const mpz_t); -void mpz_sub_ui (mpz_t, const mpz_t, unsigned long); -void mpz_ui_sub (mpz_t, unsigned long, const mpz_t); -void mpz_sub (mpz_t, const mpz_t, const mpz_t); - -void mpz_mul_si (mpz_t, const mpz_t, long int); -void mpz_mul_ui (mpz_t, const mpz_t, unsigned long int); -void mpz_mul (mpz_t, const mpz_t, const mpz_t); -void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_addmul_ui (mpz_t, const mpz_t, unsigned long int); -void mpz_addmul (mpz_t, const mpz_t, const mpz_t); -void mpz_submul_ui (mpz_t, const mpz_t, unsigned long int); -void mpz_submul (mpz_t, const mpz_t, const mpz_t); - -void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); -void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); -void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t); -void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t); -void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t); -void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t); -void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t); -void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t); -void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t); - -void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); -void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t); - -void mpz_mod (mpz_t, const mpz_t, const mpz_t); - -void mpz_divexact (mpz_t, const mpz_t, const mpz_t); - -int mpz_divisible_p (const mpz_t, const mpz_t); -int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t); - -unsigned long mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); -unsigned long mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); -unsigned long mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, unsigned long); -unsigned long mpz_cdiv_q_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_fdiv_q_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_tdiv_q_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_cdiv_r_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_fdiv_r_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_tdiv_r_ui (mpz_t, const mpz_t, unsigned long); -unsigned long mpz_cdiv_ui (const mpz_t, unsigned long); -unsigned long mpz_fdiv_ui (const mpz_t, unsigned long); -unsigned long mpz_tdiv_ui (const mpz_t, unsigned long); - -unsigned long mpz_mod_ui (mpz_t, const mpz_t, unsigned long); - -void mpz_divexact_ui (mpz_t, const mpz_t, unsigned long); - -int mpz_divisible_ui_p (const mpz_t, unsigned long); - -unsigned long mpz_gcd_ui (mpz_t, const mpz_t, unsigned long); -void mpz_gcd (mpz_t, const mpz_t, const mpz_t); -void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t); -void mpz_lcm_ui (mpz_t, const mpz_t, unsigned long); -void mpz_lcm (mpz_t, const mpz_t, const mpz_t); -int mpz_invert (mpz_t, const mpz_t, const mpz_t); - -void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t); -void mpz_sqrt (mpz_t, const mpz_t); -int mpz_perfect_square_p (const mpz_t); - -void mpz_pow_ui (mpz_t, const mpz_t, unsigned long); -void mpz_ui_pow_ui (mpz_t, unsigned long, unsigned long); -void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t); -void mpz_powm_ui (mpz_t, const mpz_t, unsigned long, const mpz_t); - -void mpz_rootrem (mpz_t, mpz_t, const mpz_t, unsigned long); -int mpz_root (mpz_t, const mpz_t, unsigned long); - -void mpz_fac_ui (mpz_t, unsigned long); -void mpz_2fac_ui (mpz_t, unsigned long); -void mpz_mfac_uiui (mpz_t, unsigned long, unsigned long); -void mpz_bin_uiui (mpz_t, unsigned long, unsigned long); - -int mpz_probab_prime_p (const mpz_t, int); - -int mpz_tstbit (const mpz_t, mp_bitcnt_t); -void mpz_setbit (mpz_t, mp_bitcnt_t); -void mpz_clrbit (mpz_t, mp_bitcnt_t); -void mpz_combit (mpz_t, mp_bitcnt_t); - -void mpz_com (mpz_t, const mpz_t); -void mpz_and (mpz_t, const mpz_t, const mpz_t); -void mpz_ior (mpz_t, const mpz_t, const mpz_t); -void mpz_xor (mpz_t, const mpz_t, const mpz_t); - -mp_bitcnt_t mpz_popcount (const mpz_t); -mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t); -mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t); -mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t); - -int mpz_fits_slong_p (const mpz_t); -int mpz_fits_ulong_p (const mpz_t); -int mpz_fits_sint_p (const mpz_t); -int mpz_fits_uint_p (const mpz_t); -int mpz_fits_sshort_p (const mpz_t); -int mpz_fits_ushort_p (const mpz_t); -long int mpz_get_si (const mpz_t); -unsigned long int mpz_get_ui (const mpz_t); -double mpz_get_d (const mpz_t); -size_t mpz_size (const mpz_t); -mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t); - -void mpz_realloc2 (mpz_t, mp_bitcnt_t); -mp_srcptr mpz_limbs_read (mpz_srcptr); -mp_ptr mpz_limbs_modify (mpz_t, mp_size_t); -mp_ptr mpz_limbs_write (mpz_t, mp_size_t); -void mpz_limbs_finish (mpz_t, mp_size_t); -mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t); - -#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }} - -void mpz_set_si (mpz_t, signed long int); -void mpz_set_ui (mpz_t, unsigned long int); -void mpz_set (mpz_t, const mpz_t); -void mpz_set_d (mpz_t, double); - -void mpz_init_set_si (mpz_t, signed long int); -void mpz_init_set_ui (mpz_t, unsigned long int); -void mpz_init_set (mpz_t, const mpz_t); -void mpz_init_set_d (mpz_t, double); - -size_t mpz_sizeinbase (const mpz_t, int); -char *mpz_get_str (char *, int, const mpz_t); -int mpz_set_str (mpz_t, const char *, int); -int mpz_init_set_str (mpz_t, const char *, int); - -/* This long list taken from gmp.h. */ -/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, - defines EOF but not FILE. */ -#if defined (FILE) \ - || defined (H_STDIO) \ - || defined (_H_STDIO) /* AIX */ \ - || defined (_STDIO_H) /* glibc, Sun, SCO */ \ - || defined (_STDIO_H_) /* BSD, OSF */ \ - || defined (__STDIO_H) /* Borland */ \ - || defined (__STDIO_H__) /* IRIX */ \ - || defined (_STDIO_INCLUDED) /* HPUX */ \ - || defined (__dj_include_stdio_h_) /* DJGPP */ \ - || defined (_FILE_DEFINED) /* Microsoft */ \ - || defined (__STDIO__) /* Apple MPW MrC */ \ - || defined (_MSL_STDIO_H) /* Metrowerks */ \ - || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ - || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \ - || defined (__STDIO_LOADED) /* VMS */ \ - || defined (_STDIO) /* HPE NonStop */ \ - || defined (__DEFINED_FILE) /* musl */ -size_t mpz_out_str (FILE *, int, const mpz_t); -#endif - -void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *); -void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t); - -#if defined (__cplusplus) -} -#endif -#endif /* __MINI_GMP_H__ */ diff --git a/xcompile/lib/minmax.h b/xcompile/lib/minmax.h deleted file mode 100644 index 1fbfc6616cf..00000000000 --- a/xcompile/lib/minmax.h +++ /dev/null @@ -1,60 +0,0 @@ -/* MIN, MAX macros. - Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _MINMAX_H -#define _MINMAX_H - -/* Note: MIN, MAX are also defined in on some systems - (glibc, IRIX, HP-UX, OSF/1). Therefore you might get warnings about - MIN, MAX macro redefinitions on some systems; the workaround is to - #include this file as the last one among the #include list. */ - -/* Before we define the following symbols we get the file - since otherwise we get redefinitions on some systems if is - included after this file. Likewise for . - If more than one of these system headers define MIN and MAX, pick just - one of the headers (because the definitions most likely are the same). */ -#if HAVE_MINMAX_IN_LIMITS_H -# include -#elif HAVE_MINMAX_IN_SYS_PARAM_H -# include -#endif - -/* Note: MIN and MAX should be used with two arguments of the - same type. They might not return the minimum and maximum of their two - arguments, if the arguments have different types or have unusual - floating-point values. For example, on a typical host with 32-bit 'int', - 64-bit 'long long', and 64-bit IEEE 754 'double' types: - - MAX (-1, 2147483648) returns 4294967295. - MAX (9007199254740992.0, 9007199254740993) returns 9007199254740992.0. - MAX (NaN, 0.0) returns 0.0. - MAX (+0.0, -0.0) returns -0.0. - - and in each case the answer is in some sense bogus. */ - -/* MAX(a,b) returns the maximum of A and B. */ -#ifndef MAX -# define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -/* MIN(a,b) returns the minimum of A and B. */ -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#endif /* _MINMAX_H */ diff --git a/xcompile/lib/mkostemp.c b/xcompile/lib/mkostemp.c deleted file mode 100644 index 5cd5b3ac583..00000000000 --- a/xcompile/lib/mkostemp.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2023 Free Software - Foundation, Inc. - This file is derived from the one in the GNU C Library. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if !_LIBC -# include -#endif - -#include - -#if !_LIBC -# include "tempname.h" -# define __gen_tempname gen_tempname -# ifndef __GTFILE -# define __GT_FILE GT_FILE -# endif -#endif - -#include - -#ifndef __GT_FILE -# define __GT_FILE 0 -#endif - -/* Generate a unique temporary file name from XTEMPLATE. - The last six characters of XTEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - Then open the file and return a fd. */ -int -mkostemp (char *xtemplate, int flags) -{ - return __gen_tempname (xtemplate, 0, flags, __GT_FILE); -} diff --git a/xcompile/lib/mktime-internal.h b/xcompile/lib/mktime-internal.h deleted file mode 100644 index 709c36bdf56..00000000000 --- a/xcompile/lib/mktime-internal.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Internals of mktime and related functions - Copyright 2016-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Eggert . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -/* mktime_offset_t is a signed type wide enough to hold a UTC offset - in seconds, and used as part of the type of the offset-guess - argument to mktime_internal. In Glibc, it is always long int. - When in Gnulib, use time_t on platforms where time_t - is signed, to be compatible with platforms like BeOS that export - this implementation detail of mktime. On platforms where time_t is - unsigned, GNU and POSIX code can assume 'int' is at least 32 bits - which is wide enough for a UTC offset. */ -#ifdef _LIBC -typedef long int mktime_offset_t; -#elif defined TIME_T_IS_SIGNED -typedef time_t mktime_offset_t; -#else -typedef int mktime_offset_t; -#endif - -/* The source code uses identifiers like __time64_t for glibc - timestamps that can contain 64-bit values even when time_t is only - 32 bits. These are just macros for the ordinary identifiers unless - compiling within glibc when time_t is 32 bits. */ -#if ! (defined _LIBC && __TIMESIZE != 64) -# undef __time64_t -# define __time64_t time_t -# define __gmtime64_r __gmtime_r -# define __localtime64_r __localtime_r -# define __mktime64 mktime -# define __timegm64 timegm -#endif - -#ifndef _LIBC - -/* Although glibc source code uses leading underscores, Gnulib wants - ordinary names. - - Portable standalone applications should supply a that - declares a POSIX-compliant localtime_r, for the benefit of older - implementations that lack localtime_r or have a nonstandard one. - Similarly for gmtime_r. See the gnulib time_r module for one way - to implement this. */ - -# undef __gmtime_r -# undef __localtime_r -# define __gmtime_r gmtime_r -# define __localtime_r localtime_r - -# define __mktime_internal mktime_internal - -#endif - -/* Subroutine of mktime. Return the time_t representation of TP and - normalize TP, given that a struct tm * maps to a time_t as performed - by FUNC. Record next guess for localtime-gmtime offset in *OFFSET. */ -extern __time64_t __mktime_internal (struct tm *tp, - struct tm *(*func) (__time64_t const *, - struct tm *), - mktime_offset_t *offset) attribute_hidden; diff --git a/xcompile/lib/mktime.c b/xcompile/lib/mktime.c deleted file mode 100644 index 94a4320e6ca..00000000000 --- a/xcompile/lib/mktime.c +++ /dev/null @@ -1,578 +0,0 @@ -/* Convert a 'struct tm' to a time_t value. - Copyright (C) 1993-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Eggert . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* The following macros influence what gets defined when this file is compiled: - - Macro/expression Which gnulib module This compilation unit - should define - - _LIBC (glibc proper) mktime - - NEED_MKTIME_WORKING mktime rpl_mktime - || NEED_MKTIME_WINDOWS - - NEED_MKTIME_INTERNAL mktime-internal mktime_internal - */ - -#ifndef _LIBC -# include -#endif - -/* Assume that leap seconds are possible, unless told otherwise. - If the host has a 'zic' command with a '-L leapsecondfilename' option, - then it supports leap seconds; otherwise it probably doesn't. */ -#ifndef LEAP_SECONDS_POSSIBLE -# define LEAP_SECONDS_POSSIBLE 1 -#endif - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#ifndef NEED_MKTIME_INTERNAL -# define NEED_MKTIME_INTERNAL 0 -#endif -#ifndef NEED_MKTIME_WINDOWS -# define NEED_MKTIME_WINDOWS 0 -#endif -#ifndef NEED_MKTIME_WORKING -# define NEED_MKTIME_WORKING 0 -#endif - -#include "mktime-internal.h" - -#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS) -static void -my_tzset (void) -{ -# if NEED_MKTIME_WINDOWS - /* Rectify the value of the environment variable TZ. - There are four possible kinds of such values: - - Traditional US time zone names, e.g. "PST8PDT". Syntax: see - - - Time zone names based on geography, that contain one or more - slashes, e.g. "Europe/Moscow". - - Time zone names based on geography, without slashes, e.g. - "Singapore". - - Time zone names that contain explicit DST rules. Syntax: see - - The Microsoft CRT understands only the first kind. It produces incorrect - results if the value of TZ is of the other kinds. - But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value - of the second kind for most geographies, or of the first kind in a few - other geographies. If it is of the second kind, neutralize it. For the - Microsoft CRT, an absent or empty TZ means the time zone that the user - has set in the Windows Control Panel. - If the value of TZ is of the third or fourth kind -- Cygwin programs - understand these syntaxes as well --, it does not matter whether we - neutralize it or not, since these values occur only when a Cygwin user - has set TZ explicitly; this case is 1. rare and 2. under the user's - responsibility. */ - const char *tz = getenv ("TZ"); - if (tz != NULL && strchr (tz, '/') != NULL) - _putenv ("TZ="); -# else - tzset (); -# endif -} -# undef __tzset -# define __tzset() my_tzset () -#endif - -#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL - -/* A signed type that can represent an integer number of years - multiplied by four times the number of seconds in a year. It is - needed when converting a tm_year value times the number of seconds - in a year. The factor of four comes because these products need - to be subtracted from each other, and sometimes with an offset - added to them, and then with another timestamp added, without - worrying about overflow. - - Much of the code uses long_int to represent __time64_t values, to - lessen the hassle of dealing with platforms where __time64_t is - unsigned, and because long_int should suffice to represent all - __time64_t values that mktime can generate even on platforms where - __time64_t is wider than the int components of struct tm. */ - -#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60 -typedef long int long_int; -#else -typedef long long int long_int; -#endif -verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60); - -/* Shift A right by B bits portably, by dividing A by 2**B and - truncating towards minus infinity. B should be in the range 0 <= B - <= LONG_INT_BITS - 2, where LONG_INT_BITS is the number of useful - bits in a long_int. LONG_INT_BITS is at least 32. - - ISO C99 says that A >> B is implementation-defined if A < 0. Some - implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift - right in the usual way when A < 0, so SHR falls back on division if - ordinary A >> B doesn't seem to be the usual signed shift. */ - -static long_int -shr (long_int a, int b) -{ - long_int one = 1; - return (-one >> 1 == -1 - ? a >> b - : (a + (a < 0)) / (one << b) - (a < 0)); -} - -/* Bounds for the intersection of __time64_t and long_int. */ - -static long_int const mktime_min - = ((TYPE_SIGNED (__time64_t) - && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int)) - ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t)); -static long_int const mktime_max - = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t) - ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t)); - -#define EPOCH_YEAR 1970 -#define TM_YEAR_BASE 1900 -verify (TM_YEAR_BASE % 100 == 0); - -/* Is YEAR + TM_YEAR_BASE a leap year? */ -static bool -leapyear (long_int year) -{ - /* Don't add YEAR to TM_YEAR_BASE, as that might overflow. - Also, work even if YEAR is negative. */ - return - ((year & 3) == 0 - && (year % 100 != 0 - || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3))); -} - -/* How many days come before each month (0-12). */ -#ifndef _LIBC -static -#endif -const unsigned short int __mon_yday[2][13] = - { - /* Normal years. */ - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, - /* Leap years. */ - { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } - }; - - -/* Do the values A and B differ according to the rules for tm_isdst? - A and B differ if one is zero and the other positive. */ -static bool -isdst_differ (int a, int b) -{ - return (!a != !b) && (0 <= a) && (0 <= b); -} - -/* Return an integer value measuring (YEAR1-YDAY1 HOUR1:MIN1:SEC1) - - (YEAR0-YDAY0 HOUR0:MIN0:SEC0) in seconds, assuming that the clocks - were not adjusted between the timestamps. - - The YEAR values uses the same numbering as TP->tm_year. Values - need not be in the usual range. However, YEAR1 - YEAR0 must not - overflow even when multiplied by three times the number of seconds - in a year, and likewise for YDAY1 - YDAY0 and three times the - number of seconds in a day. */ - -static long_int -ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1, - int year0, int yday0, int hour0, int min0, int sec0) -{ - verify (-1 / 2 == 0); - - /* Compute intervening leap days correctly even if year is negative. - Take care to avoid integer overflow here. */ - int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3); - int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3); - int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0); - int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0); - int a400 = shr (a100, 2); - int b400 = shr (b100, 2); - int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); - - /* Compute the desired time without overflowing. */ - long_int years = year1 - year0; - long_int days = 365 * years + yday1 - yday0 + intervening_leap_days; - long_int hours = 24 * days + hour1 - hour0; - long_int minutes = 60 * hours + min1 - min0; - long_int seconds = 60 * minutes + sec1 - sec0; - return seconds; -} - -/* Return the average of A and B, even if A + B would overflow. - Round toward positive infinity. */ -static long_int -long_int_avg (long_int a, long_int b) -{ - return shr (a, 1) + shr (b, 1) + ((a | b) & 1); -} - -/* Return a long_int value corresponding to (YEAR-YDAY HOUR:MIN:SEC) - minus *TP seconds, assuming no clock adjustments occurred between - the two timestamps. - - YEAR and YDAY must not be so large that multiplying them by three times the - number of seconds in a year (or day, respectively) would overflow long_int. - *TP should be in the usual range. */ -static long_int -tm_diff (long_int year, long_int yday, int hour, int min, int sec, - struct tm const *tp) -{ - return ydhms_diff (year, yday, hour, min, sec, - tp->tm_year, tp->tm_yday, - tp->tm_hour, tp->tm_min, tp->tm_sec); -} - -/* Use CONVERT to convert T to a struct tm value in *TM. T must be in - range for __time64_t. Return TM if successful, NULL (setting errno) on - failure. */ -static struct tm * -convert_time (struct tm *(*convert) (const __time64_t *, struct tm *), - long_int t, struct tm *tm) -{ - __time64_t x = t; - return convert (&x, tm); -} - -/* Use CONVERT to convert *T to a broken down time in *TP. - If *T is out of range for conversion, adjust it so that - it is the nearest in-range value and then convert that. - A value is in range if it fits in both __time64_t and long_int. - Return TP on success, NULL (setting errno) on failure. */ -static struct tm * -ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *), - long_int *t, struct tm *tp) -{ - long_int t1 = (*t < mktime_min ? mktime_min - : *t <= mktime_max ? *t : mktime_max); - struct tm *r = convert_time (convert, t1, tp); - if (r) - { - *t = t1; - return r; - } - if (errno != EOVERFLOW) - return NULL; - - long_int bad = t1; - long_int ok = 0; - struct tm oktm; oktm.tm_sec = -1; - - /* BAD is a known out-of-range value, and OK is a known in-range one. - Use binary search to narrow the range between BAD and OK until - they differ by 1. */ - while (true) - { - long_int mid = long_int_avg (ok, bad); - if (mid == ok || mid == bad) - break; - if (convert_time (convert, mid, tp)) - ok = mid, oktm = *tp; - else if (errno != EOVERFLOW) - return NULL; - else - bad = mid; - } - - if (oktm.tm_sec < 0) - return NULL; - *t = ok; - *tp = oktm; - return tp; -} - - -/* Convert *TP to a __time64_t value, inverting - the monotonic and mostly-unit-linear conversion function CONVERT. - Use *OFFSET to keep track of a guess at the offset of the result, - compared to what the result would be for UTC without leap seconds. - If *OFFSET's guess is correct, only one CONVERT call is needed. - If successful, set *TP to the canonicalized struct tm; - otherwise leave *TP alone, return ((time_t) -1) and set errno. - This function is external because it is used also by timegm.c. */ -__time64_t -__mktime_internal (struct tm *tp, - struct tm *(*convert) (const __time64_t *, struct tm *), - mktime_offset_t *offset) -{ - struct tm tm; - - /* The maximum number of probes (calls to CONVERT) should be enough - to handle any combinations of time zone rule changes, solar time, - leap seconds, and oscillations around a spring-forward gap. - POSIX.1 prohibits leap seconds, but some hosts have them anyway. */ - int remaining_probes = 6; - - /* Time requested. Copy it in case CONVERT modifies *TP; this can - occur if TP is localtime's returned value and CONVERT is localtime. */ - int sec = tp->tm_sec; - int min = tp->tm_min; - int hour = tp->tm_hour; - int mday = tp->tm_mday; - int mon = tp->tm_mon; - int year_requested = tp->tm_year; - int isdst = tp->tm_isdst; - - /* 1 if the previous probe was DST. */ - int dst2 = 0; - - /* Ensure that mon is in range, and set year accordingly. */ - int mon_remainder = mon % 12; - int negative_mon_remainder = mon_remainder < 0; - int mon_years = mon / 12 - negative_mon_remainder; - long_int lyear_requested = year_requested; - long_int year = lyear_requested + mon_years; - - /* The other values need not be in range: - the remaining code handles overflows correctly. */ - - /* Calculate day of year from year, month, and day of month. - The result need not be in range. */ - int mon_yday = ((__mon_yday[leapyear (year)] - [mon_remainder + 12 * negative_mon_remainder]) - - 1); - long_int lmday = mday; - long_int yday = mon_yday + lmday; - - mktime_offset_t off = *offset; - int negative_offset_guess; - - int sec_requested = sec; - - if (LEAP_SECONDS_POSSIBLE) - { - /* Handle out-of-range seconds specially, - since ydhms_diff assumes every minute has 60 seconds. */ - if (sec < 0) - sec = 0; - if (59 < sec) - sec = 59; - } - - /* Invert CONVERT by probing. First assume the same offset as last - time. */ - - INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess); - long_int t0 = ydhms_diff (year, yday, hour, min, sec, - EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0, - negative_offset_guess); - long_int t = t0, t1 = t0, t2 = t0; - - /* Repeatedly use the error to improve the guess. */ - - while (true) - { - if (! ranged_convert (convert, &t, &tm)) - return -1; - long_int dt = tm_diff (year, yday, hour, min, sec, &tm); - if (dt == 0) - break; - - if (t == t1 && t != t2 - && (tm.tm_isdst < 0 - || (isdst < 0 - ? dst2 <= (tm.tm_isdst != 0) - : (isdst != 0) != (tm.tm_isdst != 0)))) - /* We can't possibly find a match, as we are oscillating - between two values. The requested time probably falls - within a spring-forward gap of size DT. Follow the common - practice in this case, which is to return a time that is DT - away from the requested time, preferring a time whose - tm_isdst differs from the requested value. (If no tm_isdst - was requested and only one of the two values has a nonzero - tm_isdst, prefer that value.) In practice, this is more - useful than returning -1. */ - goto offset_found; - - remaining_probes--; - if (remaining_probes == 0) - { - __set_errno (EOVERFLOW); - return -1; - } - - t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0; - } - - /* We have a match. Check whether tm.tm_isdst has the requested - value, if any. */ - if (isdst_differ (isdst, tm.tm_isdst)) - { - /* tm.tm_isdst has the wrong value. Look for a neighboring - time with the right value, and use its UTC offset. - - Heuristic: probe the adjacent timestamps in both directions, - looking for the desired isdst. If none is found within a - reasonable duration bound, assume a one-hour DST difference. - This should work for all real time zone histories in the tz - database. */ - - /* +1 if we wanted standard time but got DST, -1 if the reverse. */ - int dst_difference = (isdst == 0) - (tm.tm_isdst == 0); - - /* Distance between probes when looking for a DST boundary. In - tzdata2003a, the shortest period of DST is 601200 seconds - (e.g., America/Recife starting 2000-10-08 01:00), and the - shortest period of non-DST surrounded by DST is 694800 - seconds (Africa/Tunis starting 1943-04-17 01:00). Use the - minimum of these two values, so we don't miss these short - periods when probing. */ - int stride = 601200; - - /* In TZDB 2021e, the longest period of DST (or of non-DST), in - which the DST (or adjacent DST) difference is not one hour, - is 457243209 seconds: e.g., America/Cambridge_Bay with leap - seconds, starting 1965-10-31 00:00 in a switch from - double-daylight time (-05) to standard time (-07), and - continuing to 1980-04-27 02:00 in a switch from standard time - (-07) to daylight time (-06). */ - int duration_max = 457243209; - - /* Search in both directions, so the maximum distance is half - the duration; add the stride to avoid off-by-1 problems. */ - int delta_bound = duration_max / 2 + stride; - - int delta, direction; - - for (delta = stride; delta < delta_bound; delta += stride) - for (direction = -1; direction <= 1; direction += 2) - { - long_int ot; - if (! INT_ADD_WRAPV (t, delta * direction, &ot)) - { - struct tm otm; - if (! ranged_convert (convert, &ot, &otm)) - return -1; - if (! isdst_differ (isdst, otm.tm_isdst)) - { - /* We found the desired tm_isdst. - Extrapolate back to the desired time. */ - long_int gt = ot + tm_diff (year, yday, hour, min, sec, - &otm); - if (mktime_min <= gt && gt <= mktime_max) - { - if (convert_time (convert, gt, &tm)) - { - t = gt; - goto offset_found; - } - if (errno != EOVERFLOW) - return -1; - } - } - } - } - - /* No unusual DST offset was found nearby. Assume one-hour DST. */ - t += 60 * 60 * dst_difference; - if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm)) - goto offset_found; - - __set_errno (EOVERFLOW); - return -1; - } - - offset_found: - /* Set *OFFSET to the low-order bits of T - T0 - NEGATIVE_OFFSET_GUESS. - This is just a heuristic to speed up the next mktime call, and - correctness is unaffected if integer overflow occurs here. */ - INT_SUBTRACT_WRAPV (t, t0, offset); - INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset); - - if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec) - { - /* Adjust time to reflect the tm_sec requested, not the normalized value. - Also, repair any damage from a false match due to a leap second. */ - long_int sec_adjustment = sec == 0 && tm.tm_sec == 60; - sec_adjustment -= sec; - sec_adjustment += sec_requested; - if (INT_ADD_WRAPV (t, sec_adjustment, &t) - || ! (mktime_min <= t && t <= mktime_max)) - { - __set_errno (EOVERFLOW); - return -1; - } - if (! convert_time (convert, t, &tm)) - return -1; - } - - *tp = tm; - return t; -} - -#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL */ - -#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS - -/* Convert *TP to a __time64_t value. */ -__time64_t -__mktime64 (struct tm *tp) -{ - /* POSIX.1 8.1.1 requires that whenever mktime() is called, the - time zone names contained in the external variable 'tzname' shall - be set as if the tzset() function had been called. */ - __tzset (); - -# if defined _LIBC || NEED_MKTIME_WORKING - static mktime_offset_t localtime_offset; - return __mktime_internal (tp, __localtime64_r, &localtime_offset); -# else -# undef mktime - return mktime (tp); -# endif -} -#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */ - -#if defined _LIBC && __TIMESIZE != 64 - -libc_hidden_def (__mktime64) - -time_t -mktime (struct tm *tp) -{ - struct tm tm = *tp; - __time64_t t = __mktime64 (&tm); - if (in_time_t_range (t)) - { - *tp = tm; - return t; - } - else - { - __set_errno (EOVERFLOW); - return -1; - } -} - -#endif - -weak_alias (mktime, timelocal) -libc_hidden_def (mktime) -libc_hidden_weak (timelocal) diff --git a/xcompile/lib/nanosleep.c b/xcompile/lib/nanosleep.c deleted file mode 100644 index 3f295f49b5d..00000000000 --- a/xcompile/lib/nanosleep.c +++ /dev/null @@ -1,193 +0,0 @@ -/* Provide a replacement for the POSIX nanosleep function. - - Copyright (C) 1999-2000, 2002, 2004-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering - and Bruno Haible for the native Windows part */ - -#include - -#include - -#include "intprops.h" - -#include -#include -#include -#include - -#include - -#include - - -enum { BILLION = 1000 * 1000 * 1000 }; - -#if HAVE_BUG_BIG_NANOSLEEP - -int -nanosleep (const struct timespec *requested_delay, - struct timespec *remaining_delay) -# undef nanosleep -{ - /* nanosleep mishandles large sleeps due to internal overflow problems. - The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which - can't sleep more than 24.85 days (2^31 milliseconds). Similarly, - cygwin 1.5.x, which can't sleep more than 49.7 days (2^32 milliseconds). - Solve this by breaking the sleep up into smaller chunks. */ - - if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) - { - errno = EINVAL; - return -1; - } - - { - /* Verify that time_t is large enough. */ - static_assert (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60); - const time_t limit = 24 * 24 * 60 * 60; - time_t seconds = requested_delay->tv_sec; - struct timespec intermediate; - intermediate.tv_nsec = requested_delay->tv_nsec; - - while (limit < seconds) - { - int result; - intermediate.tv_sec = limit; - result = nanosleep (&intermediate, remaining_delay); - seconds -= limit; - if (result) - { - if (remaining_delay) - remaining_delay->tv_sec += seconds; - return result; - } - intermediate.tv_nsec = 0; - } - intermediate.tv_sec = seconds; - return nanosleep (&intermediate, remaining_delay); - } -} - -#elif defined _WIN32 && ! defined __CYGWIN__ -/* Native Windows platforms. */ - -# define WIN32_LEAN_AND_MEAN -# include - -/* The Windows API function Sleep() has a resolution of about 15 ms and takes - at least 5 ms to execute. We use this function for longer time periods. - Additionally, we use busy-looping over short time periods, to get a - resolution of about 0.01 ms. In order to measure such short timespans, - we use the QueryPerformanceCounter() function. */ - -int -nanosleep (const struct timespec *requested_delay, - struct timespec *remaining_delay) -{ - static bool initialized; - /* Number of performance counter increments per nanosecond, - or zero if it could not be determined. */ - static double ticks_per_nanosecond; - - if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) - { - errno = EINVAL; - return -1; - } - - /* For requested delays of one second or more, 15ms resolution is - sufficient. */ - if (requested_delay->tv_sec == 0) - { - if (!initialized) - { - /* Initialize ticks_per_nanosecond. */ - LARGE_INTEGER ticks_per_second; - - if (QueryPerformanceFrequency (&ticks_per_second)) - ticks_per_nanosecond = - (double) ticks_per_second.QuadPart / 1000000000.0; - - initialized = true; - } - if (ticks_per_nanosecond) - { - /* QueryPerformanceFrequency worked. We can use - QueryPerformanceCounter. Use a combination of Sleep and - busy-looping. */ - /* Number of milliseconds to pass to the Sleep function. - Since Sleep can take up to 8 ms less or 8 ms more than requested - (or maybe more if the system is loaded), we subtract 10 ms. */ - int sleep_millis = (int) requested_delay->tv_nsec / 1000000 - 10; - /* Determine how many ticks to delay. */ - LONGLONG wait_ticks = requested_delay->tv_nsec * ticks_per_nanosecond; - /* Start. */ - LARGE_INTEGER counter_before; - if (QueryPerformanceCounter (&counter_before)) - { - /* Wait until the performance counter has reached this value. - We don't need to worry about overflow, because the performance - counter is reset at reboot, and with a frequency of 3.6E6 - ticks per second 63 bits suffice for over 80000 years. */ - LONGLONG wait_until = counter_before.QuadPart + wait_ticks; - /* Use Sleep for the longest part. */ - if (sleep_millis > 0) - Sleep (sleep_millis); - /* Busy-loop for the rest. */ - for (;;) - { - LARGE_INTEGER counter_after; - if (!QueryPerformanceCounter (&counter_after)) - /* QueryPerformanceCounter failed, but succeeded earlier. - Should not happen. */ - break; - if (counter_after.QuadPart >= wait_until) - /* The requested time has elapsed. */ - break; - } - goto done; - } - } - } - /* Implementation for long delays and as fallback. */ - Sleep (requested_delay->tv_sec * 1000 + requested_delay->tv_nsec / 1000000); - - done: - /* Sleep is not interruptible. So there is no remaining delay. */ - if (remaining_delay != NULL) - { - remaining_delay->tv_sec = 0; - remaining_delay->tv_nsec = 0; - } - return 0; -} - -#else -/* Other platforms lacking nanosleep. - It's not clear whether these are still practical porting targets. - For now, just fall back on pselect. */ - -/* Suspend execution for at least *REQUESTED_DELAY seconds. The - *REMAINING_DELAY part isn't implemented yet. */ - -int -nanosleep (const struct timespec *requested_delay, - struct timespec *remaining_delay) -{ - return pselect (0, NULL, NULL, NULL, requested_delay, NULL); -} -#endif diff --git a/xcompile/lib/nproc.c b/xcompile/lib/nproc.c deleted file mode 100644 index 2740c458c11..00000000000 --- a/xcompile/lib/nproc.c +++ /dev/null @@ -1,404 +0,0 @@ -/* Detect the number of processors. - - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Glen Lenker and Bruno Haible. */ - -#include -#include "nproc.h" - -#include -#include -#include - -#if HAVE_PTHREAD_GETAFFINITY_NP && 0 -# include -# include -#endif -#if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP -# include -#endif - -#include - -#if HAVE_SYS_PSTAT_H -# include -#endif - -#if HAVE_SYS_SYSMP_H -# include -#endif - -#if HAVE_SYS_PARAM_H -# include -#endif - -#if HAVE_SYS_SYSCTL_H && ! defined __GLIBC__ -# include -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -#endif - -#include "c-ctype.h" - -#include "minmax.h" - -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) - -/* Return the number of processors available to the current process, based - on a modern system call that returns the "affinity" between the current - process and each CPU. Return 0 if unknown or if such a system call does - not exist. */ -static unsigned long -num_processors_via_affinity_mask (void) -{ - /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np, - but with different APIs. Also it requires linking with -lpthread. - Therefore this code is not enabled. - glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has - sched_getaffinity_np. */ -#if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0 - { - cpu_set_t set; - - if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0) - { - unsigned long count; - -# ifdef CPU_COUNT - /* glibc >= 2.6 has the CPU_COUNT macro. */ - count = CPU_COUNT (&set); -# else - size_t i; - - count = 0; - for (i = 0; i < CPU_SETSIZE; i++) - if (CPU_ISSET (i, &set)) - count++; -# endif - if (count > 0) - return count; - } - } -#elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0 - { - cpuset_t *set; - - set = cpuset_create (); - if (set != NULL) - { - unsigned long count = 0; - - if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set) - == 0) - { - cpuid_t i; - - for (i = 0;; i++) - { - int ret = cpuset_isset (i, set); - if (ret < 0) - break; - if (ret > 0) - count++; - } - } - cpuset_destroy (set); - if (count > 0) - return count; - } - } -#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */ - { - cpu_set_t set; - - if (sched_getaffinity (0, sizeof (set), &set) == 0) - { - unsigned long count; - -# ifdef CPU_COUNT - /* glibc >= 2.6 has the CPU_COUNT macro. */ - count = CPU_COUNT (&set); -# else - size_t i; - - count = 0; - for (i = 0; i < CPU_SETSIZE; i++) - if (CPU_ISSET (i, &set)) - count++; -# endif - if (count > 0) - return count; - } - } -#elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */ - { - cpuset_t *set; - - set = cpuset_create (); - if (set != NULL) - { - unsigned long count = 0; - - if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0) - { - cpuid_t i; - - for (i = 0;; i++) - { - int ret = cpuset_isset (i, set); - if (ret < 0) - break; - if (ret > 0) - count++; - } - } - cpuset_destroy (set); - if (count > 0) - return count; - } - } -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ - { /* This works on native Windows platforms. */ - DWORD_PTR process_mask; - DWORD_PTR system_mask; - - if (GetProcessAffinityMask (GetCurrentProcess (), - &process_mask, &system_mask)) - { - DWORD_PTR mask = process_mask; - unsigned long count = 0; - - for (; mask != 0; mask = mask >> 1) - if (mask & 1) - count++; - if (count > 0) - return count; - } - } -#endif - - return 0; -} - - -/* Return the total number of processors. Here QUERY must be one of - NPROC_ALL, NPROC_CURRENT. The result is guaranteed to be at least 1. */ -static unsigned long int -num_processors_ignoring_omp (enum nproc_query query) -{ - /* On systems with a modern affinity mask system call, we have - sysconf (_SC_NPROCESSORS_CONF) - >= sysconf (_SC_NPROCESSORS_ONLN) - >= num_processors_via_affinity_mask () - The first number is the number of CPUs configured in the system. - The second number is the number of CPUs available to the scheduler. - The third number is the number of CPUs available to the current process. - - Note! On Linux systems with glibc, the first and second number come from - the /sys and /proc file systems (see - glibc/sysdeps/unix/sysv/linux/getsysstats.c). - In some situations these file systems are not mounted, and the sysconf call - returns 1 or 2 (), - which does not reflect the reality. */ - - if (query == NPROC_CURRENT) - { - /* Try the modern affinity mask system call. */ - { - unsigned long nprocs = num_processors_via_affinity_mask (); - - if (nprocs > 0) - return nprocs; - } - -#if defined _SC_NPROCESSORS_ONLN - { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris, - Cygwin, Haiku. */ - long int nprocs = sysconf (_SC_NPROCESSORS_ONLN); - if (nprocs > 0) - return nprocs; - } -#endif - } - else /* query == NPROC_ALL */ - { -#if defined _SC_NPROCESSORS_CONF - { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris, - Cygwin, Haiku. */ - long int nprocs = sysconf (_SC_NPROCESSORS_CONF); - -# if __GLIBC__ >= 2 && defined __linux__ - /* On Linux systems with glibc, this information comes from the /sys and - /proc file systems (see glibc/sysdeps/unix/sysv/linux/getsysstats.c). - In some situations these file systems are not mounted, and the - sysconf call returns 1 or 2. But we wish to guarantee that - num_processors (NPROC_ALL) >= num_processors (NPROC_CURRENT). */ - if (nprocs == 1 || nprocs == 2) - { - unsigned long nprocs_current = num_processors_via_affinity_mask (); - - if (/* nprocs_current > 0 && */ nprocs_current > nprocs) - nprocs = nprocs_current; - } -# endif - - if (nprocs > 0) - return nprocs; - } -#endif - } - -#if HAVE_PSTAT_GETDYNAMIC - { /* This works on HP-UX. */ - struct pst_dynamic psd; - if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0) - { - /* The field psd_proc_cnt contains the number of active processors. - In newer releases of HP-UX 11, the field psd_max_proc_cnt includes - deactivated processors. */ - if (query == NPROC_CURRENT) - { - if (psd.psd_proc_cnt > 0) - return psd.psd_proc_cnt; - } - else - { - if (psd.psd_max_proc_cnt > 0) - return psd.psd_max_proc_cnt; - } - } - } -#endif - -#if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS - { /* This works on IRIX. */ - /* MP_NPROCS yields the number of installed processors. - MP_NAPROCS yields the number of processors available to unprivileged - processes. */ - int nprocs = - sysmp (query == NPROC_CURRENT && getuid () != 0 - ? MP_NAPROCS - : MP_NPROCS); - if (nprocs > 0) - return nprocs; - } -#endif - - /* Finally, as fallback, use the APIs that don't distinguish between - NPROC_CURRENT and NPROC_ALL. */ - -#if HAVE_SYSCTL && ! defined __GLIBC__ && defined HW_NCPU - { /* This works on macOS, FreeBSD, NetBSD, OpenBSD. - macOS 10.14 does not allow mib to be const. */ - int nprocs; - size_t len = sizeof (nprocs); - static int mib[][2] = { -# ifdef HW_NCPUONLINE - { CTL_HW, HW_NCPUONLINE }, -# endif - { CTL_HW, HW_NCPU } - }; - for (int i = 0; i < ARRAY_SIZE (mib); i++) - { - if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0 - && len == sizeof (nprocs) - && 0 < nprocs) - return nprocs; - } - } -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ - { /* This works on native Windows platforms. */ - SYSTEM_INFO system_info; - GetSystemInfo (&system_info); - if (0 < system_info.dwNumberOfProcessors) - return system_info.dwNumberOfProcessors; - } -#endif - - return 1; -} - -/* Parse OMP environment variables without dependence on OMP. - Return 0 for invalid values. */ -static unsigned long int -parse_omp_threads (char const* threads) -{ - unsigned long int ret = 0; - - if (threads == NULL) - return ret; - - /* The OpenMP spec says that the value assigned to the environment variables - "may have leading and trailing white space". */ - while (*threads != '\0' && c_isspace (*threads)) - threads++; - - /* Convert it from positive decimal to 'unsigned long'. */ - if (c_isdigit (*threads)) - { - char *endptr = NULL; - unsigned long int value = strtoul (threads, &endptr, 10); - - if (endptr != NULL) - { - while (*endptr != '\0' && c_isspace (*endptr)) - endptr++; - if (*endptr == '\0') - return value; - /* Also accept the first value in a nesting level, - since we can't determine the nesting level from env vars. */ - else if (*endptr == ',') - return value; - } - } - - return ret; -} - -unsigned long int -num_processors (enum nproc_query query) -{ - unsigned long int omp_env_limit = ULONG_MAX; - - if (query == NPROC_CURRENT_OVERRIDABLE) - { - unsigned long int omp_env_threads; - /* Honor the OpenMP environment variables, recognized also by all - programs that are based on OpenMP. */ - omp_env_threads = parse_omp_threads (getenv ("OMP_NUM_THREADS")); - omp_env_limit = parse_omp_threads (getenv ("OMP_THREAD_LIMIT")); - if (! omp_env_limit) - omp_env_limit = ULONG_MAX; - - if (omp_env_threads) - return MIN (omp_env_threads, omp_env_limit); - - query = NPROC_CURRENT; - } - /* Here query is one of NPROC_ALL, NPROC_CURRENT. */ - { - unsigned long nprocs = num_processors_ignoring_omp (query); - return MIN (nprocs, omp_env_limit); - } -} diff --git a/xcompile/lib/nproc.h b/xcompile/lib/nproc.h deleted file mode 100644 index 7b8b16d37cd..00000000000 --- a/xcompile/lib/nproc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Detect the number of processors. - - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Glen Lenker and Bruno Haible. */ - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* A "processor" in this context means a thread execution unit, that is either - - an execution core in a (possibly multi-core) chip, in a (possibly multi- - chip) module, in a single computer, or - - a thread execution unit inside a core - (hyper-threading, see ). - Which of the two definitions is used, is unspecified. */ - -enum nproc_query -{ - NPROC_ALL, /* total number of processors */ - NPROC_CURRENT, /* processors available to the current process */ - NPROC_CURRENT_OVERRIDABLE /* likewise, but overridable through the - OMP_NUM_THREADS environment variable */ -}; - -/* Return the total number of processors. The result is guaranteed to - be at least 1. */ -extern unsigned long int num_processors (enum nproc_query query); - -#ifdef __cplusplus -} -#endif /* C++ */ diff --git a/xcompile/lib/nstrftime.c b/xcompile/lib/nstrftime.c deleted file mode 100644 index 68bb560910d..00000000000 --- a/xcompile/lib/nstrftime.c +++ /dev/null @@ -1,1490 +0,0 @@ -/* Copyright (C) 1991-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#ifdef _LIBC -# define USE_IN_EXTENDED_LOCALE_MODEL 1 -# define HAVE_STRUCT_ERA_ENTRY 1 -# define HAVE_TM_GMTOFF 1 -# define HAVE_STRUCT_TM_TM_ZONE 1 -# define HAVE_TZNAME 1 -# include "../locale/localeinfo.h" -#else -# include -# if FPRINTFTIME -# include "fprintftime.h" -# else -# include "strftime.h" -# endif -# include "time-internal.h" -#endif - -#include -#include -#include - -#if HAVE_TZNAME && !HAVE_DECL_TZNAME -extern char *tzname[]; -#endif - -/* Do multibyte processing if multibyte encodings are supported, unless - multibyte sequences are safe in formats. Multibyte sequences are - safe if they cannot contain byte sequences that look like format - conversion specifications. The multibyte encodings used by the - C library on the various platforms (UTF-8, GB2312, GBK, CP936, - GB18030, EUC-TW, BIG5, BIG5-HKSCS, CP950, EUC-JP, EUC-KR, CP949, - SHIFT_JIS, CP932, JOHAB) are safe for formats, because the byte '%' - cannot occur in a multibyte character except in the first byte. - - The DEC-HANYU encoding used on OSF/1 is not safe for formats, but - this encoding has never been seen in real-life use, so we ignore - it. */ -#if !(defined __osf__ && 0) -# define MULTIBYTE_IS_FORMAT_SAFE 1 -#endif -#define DO_MULTIBYTE (! MULTIBYTE_IS_FORMAT_SAFE) - -#if DO_MULTIBYTE -# include - static const mbstate_t mbstate_zero; -#endif - -#include -#include -#include -#include - -#include "attribute.h" -#include - -#ifdef COMPILE_WIDE -# include -# define CHAR_T wchar_t -# define UCHAR_T unsigned int -# define L_(Str) L##Str -# define NLW(Sym) _NL_W##Sym - -# define MEMCPY(d, s, n) __wmemcpy (d, s, n) -# define STRLEN(s) __wcslen (s) - -#else -# define CHAR_T char -# define UCHAR_T unsigned char -# define L_(Str) Str -# define NLW(Sym) Sym -# define ABALTMON_1 _NL_ABALTMON_1 - -# define MEMCPY(d, s, n) memcpy (d, s, n) -# define STRLEN(s) strlen (s) - -#endif - -/* Shift A right by B bits portably, by dividing A by 2**B and - truncating towards minus infinity. A and B should be free of side - effects, and B should be in the range 0 <= B <= INT_BITS - 2, where - INT_BITS is the number of useful bits in an int. GNU code can - assume that INT_BITS is at least 32. - - ISO C99 says that A >> B is implementation-defined if A < 0. Some - implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift - right in the usual way when A < 0, so SHR falls back on division if - ordinary A >> B doesn't seem to be the usual signed shift. */ -#define SHR(a, b) \ - (-1 >> 1 == -1 \ - ? (a) >> (b) \ - : ((a) + ((a) < 0)) / (1 << (b)) - ((a) < 0)) - -#define TM_YEAR_BASE 1900 - -#ifndef __isleap -/* Nonzero if YEAR is a leap year (every 4 years, - except every 100th isn't, and every 400th is). */ -# define __isleap(year) \ - ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) -#endif - - -#ifdef _LIBC -# define mktime_z(tz, tm) mktime (tm) -# define tzname __tzname -# define tzset __tzset -#endif - -#ifndef FPRINTFTIME -# define FPRINTFTIME 0 -#endif - -#if FPRINTFTIME -# define STREAM_OR_CHAR_T FILE -# define STRFTIME_ARG(x) /* empty */ -#else -# define STREAM_OR_CHAR_T CHAR_T -# define STRFTIME_ARG(x) x, -#endif - -#if FPRINTFTIME -# define memset_byte(P, Len, Byte) \ - do { size_t _i; for (_i = 0; _i < Len; _i++) fputc (Byte, P); } while (0) -# define memset_space(P, Len) memset_byte (P, Len, ' ') -# define memset_zero(P, Len) memset_byte (P, Len, '0') -#elif defined COMPILE_WIDE -# define memset_space(P, Len) (wmemset (P, L' ', Len), (P) += (Len)) -# define memset_zero(P, Len) (wmemset (P, L'0', Len), (P) += (Len)) -#else -# define memset_space(P, Len) (memset (P, ' ', Len), (P) += (Len)) -# define memset_zero(P, Len) (memset (P, '0', Len), (P) += (Len)) -#endif - -#if FPRINTFTIME -# define advance(P, N) -#else -# define advance(P, N) ((P) += (N)) -#endif - -#define add(n, f) width_add (width, n, f) -#define width_add(width, n, f) \ - do \ - { \ - size_t _n = (n); \ - size_t _w = pad == L_('-') || width < 0 ? 0 : width; \ - size_t _incr = _n < _w ? _w : _n; \ - if (_incr >= maxsize - i) \ - { \ - errno = ERANGE; \ - return 0; \ - } \ - if (p) \ - { \ - if (_n < _w) \ - { \ - size_t _delta = _w - _n; \ - if (pad == L_('0') || pad == L_('+')) \ - memset_zero (p, _delta); \ - else \ - memset_space (p, _delta); \ - } \ - f; \ - advance (p, _n); \ - } \ - i += _incr; \ - } while (0) - -#define add1(c) width_add1 (width, c) -#if FPRINTFTIME -# define width_add1(width, c) width_add (width, 1, fputc (c, p)) -#else -# define width_add1(width, c) width_add (width, 1, *p = c) -#endif - -#define cpy(n, s) width_cpy (width, n, s) -#if FPRINTFTIME -# define width_cpy(width, n, s) \ - width_add (width, n, \ - do \ - { \ - if (to_lowcase) \ - fwrite_lowcase (p, (s), _n); \ - else if (to_uppcase) \ - fwrite_uppcase (p, (s), _n); \ - else \ - { \ - /* Ignore the value of fwrite. The caller can determine whether \ - an error occurred by inspecting ferror (P). All known fwrite \ - implementations set the stream's error indicator when they \ - fail due to ENOMEM etc., even though C11 and POSIX.1-2008 do \ - not require this. */ \ - fwrite (s, _n, 1, p); \ - } \ - } \ - while (0) \ - ) -#else -# define width_cpy(width, n, s) \ - width_add (width, n, \ - if (to_lowcase) \ - memcpy_lowcase (p, (s), _n LOCALE_ARG); \ - else if (to_uppcase) \ - memcpy_uppcase (p, (s), _n LOCALE_ARG); \ - else \ - MEMCPY ((void *) p, (void const *) (s), _n)) -#endif - -#ifdef COMPILE_WIDE -# ifndef USE_IN_EXTENDED_LOCALE_MODEL -# undef __mbsrtowcs_l -# define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st) -# endif -# define widen(os, ws, l) \ - { \ - mbstate_t __st; \ - const char *__s = os; \ - memset (&__st, '\0', sizeof (__st)); \ - l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \ - ws = (wchar_t *) alloca ((l + 1) * sizeof (wchar_t)); \ - (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \ - } -#endif - - -#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL -/* We use this code also for the extended locale handling where the - function gets as an additional argument the locale which has to be - used. To access the values we have to redefine the _NL_CURRENT - macro. */ -# define strftime __strftime_l -# define wcsftime __wcsftime_l -# undef _NL_CURRENT -# define _NL_CURRENT(category, item) \ - (current->values[_NL_ITEM_INDEX (item)].string) -# define LOCALE_PARAM , locale_t loc -# define LOCALE_ARG , loc -# define HELPER_LOCALE_ARG , current -#else -# define LOCALE_PARAM -# define LOCALE_ARG -# ifdef _LIBC -# define HELPER_LOCALE_ARG , _NL_CURRENT_DATA (LC_TIME) -# else -# define HELPER_LOCALE_ARG -# endif -#endif - -#ifdef COMPILE_WIDE -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define TOUPPER(Ch, L) __towupper_l (Ch, L) -# define TOLOWER(Ch, L) __towlower_l (Ch, L) -# else -# define TOUPPER(Ch, L) towupper (Ch) -# define TOLOWER(Ch, L) towlower (Ch) -# endif -#else -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define TOUPPER(Ch, L) __toupper_l (Ch, L) -# define TOLOWER(Ch, L) __tolower_l (Ch, L) -# else -# define TOUPPER(Ch, L) toupper (Ch) -# define TOLOWER(Ch, L) tolower (Ch) -# endif -#endif -/* We don't use 'isdigit' here since the locale dependent - interpretation is not what we want here. We only need to accept - the arabic digits in the ASCII range. One day there is perhaps a - more reliable way to accept other sets of digits. */ -#define ISDIGIT(Ch) ((unsigned int) (Ch) - L_('0') <= 9) - -#if FPRINTFTIME -static void -fwrite_lowcase (FILE *fp, const CHAR_T *src, size_t len) -{ - while (len-- > 0) - { - fputc (TOLOWER ((UCHAR_T) *src, loc), fp); - ++src; - } -} - -static void -fwrite_uppcase (FILE *fp, const CHAR_T *src, size_t len) -{ - while (len-- > 0) - { - fputc (TOUPPER ((UCHAR_T) *src, loc), fp); - ++src; - } -} -#else -static CHAR_T *memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, - size_t len LOCALE_PARAM); - -static CHAR_T * -memcpy_lowcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) -{ - while (len-- > 0) - dest[len] = TOLOWER ((UCHAR_T) src[len], loc); - return dest; -} - -static CHAR_T *memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, - size_t len LOCALE_PARAM); - -static CHAR_T * -memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) -{ - while (len-- > 0) - dest[len] = TOUPPER ((UCHAR_T) src[len], loc); - return dest; -} -#endif - - -#if ! HAVE_TM_GMTOFF -/* Yield the difference between *A and *B, - measured in seconds, ignoring leap seconds. */ -# define tm_diff ftime_tm_diff -static int tm_diff (const struct tm *, const struct tm *); -static int -tm_diff (const struct tm *a, const struct tm *b) -{ - /* Compute intervening leap days correctly even if year is negative. - Take care to avoid int overflow in leap day calculations, - but it's OK to assume that A and B are close to each other. */ - int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3); - int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3); - int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0); - int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0); - int a400 = SHR (a100, 2); - int b400 = SHR (b100, 2); - int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); - int years = a->tm_year - b->tm_year; - int days = (365 * years + intervening_leap_days - + (a->tm_yday - b->tm_yday)); - return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) - + (a->tm_min - b->tm_min)) - + (a->tm_sec - b->tm_sec)); -} -#endif /* ! HAVE_TM_GMTOFF */ - - - -/* The number of days from the first day of the first ISO week of this - year to the year day YDAY with week day WDAY. ISO weeks start on - Monday; the first ISO week has the year's first Thursday. YDAY may - be as small as YDAY_MINIMUM. */ -#define ISO_WEEK_START_WDAY 1 /* Monday */ -#define ISO_WEEK1_WDAY 4 /* Thursday */ -#define YDAY_MINIMUM (-366) -static int iso_week_days (int, int); -static __inline int -iso_week_days (int yday, int wday) -{ - /* Add enough to the first operand of % to make it nonnegative. */ - int big_enough_multiple_of_7 = (-YDAY_MINIMUM / 7 + 2) * 7; - return (yday - - (yday - wday + ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7 - + ISO_WEEK1_WDAY - ISO_WEEK_START_WDAY); -} - - -/* When compiling this file, GNU applications can #define my_strftime - to a symbol (typically nstrftime) to get an extended strftime with - extra arguments TZ and NS. */ - -#if FPRINTFTIME -# undef my_strftime -# define my_strftime fprintftime -#endif - -#ifdef my_strftime -# define extra_args , tz, ns -# define extra_args_spec , timezone_t tz, int ns -#else -# if defined COMPILE_WIDE -# define my_strftime wcsftime -# define nl_get_alt_digit _nl_get_walt_digit -# else -# define my_strftime strftime -# define nl_get_alt_digit _nl_get_alt_digit -# endif -# define extra_args -# define extra_args_spec -/* We don't have this information in general. */ -# define tz 1 -# define ns 0 -#endif - -static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t) - const CHAR_T *, const struct tm *, - bool, int, int, bool * - extra_args_spec LOCALE_PARAM); - -/* Write information from TP into S according to the format - string FORMAT, writing no more that MAXSIZE characters - (including the terminating '\0') and returning number of - characters written. If S is NULL, nothing will be written - anywhere, so to determine how many characters would be - written, use NULL for S and (size_t) -1 for MAXSIZE. */ -size_t -my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) - const CHAR_T *format, - const struct tm *tp extra_args_spec LOCALE_PARAM) -{ - bool tzset_called = false; - return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false, - 0, -1, &tzset_called extra_args LOCALE_ARG); -} -libc_hidden_def (my_strftime) - -/* Just like my_strftime, above, but with more parameters. - UPCASE indicates that the result should be converted to upper case. - YR_SPEC and WIDTH specify the padding and width for the year. - *TZSET_CALLED indicates whether tzset has been called here. */ -static size_t -__strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) - const CHAR_T *format, - const struct tm *tp, bool upcase, - int yr_spec, int width, bool *tzset_called - extra_args_spec LOCALE_PARAM) -{ -#if defined _LIBC && defined USE_IN_EXTENDED_LOCALE_MODEL - struct __locale_data *const current = loc->__locales[LC_TIME]; -#endif -#if FPRINTFTIME - size_t maxsize = (size_t) -1; -#endif - - int saved_errno = errno; - int hour12 = tp->tm_hour; -#ifdef _NL_CURRENT - /* We cannot make the following values variables since we must delay - the evaluation of these values until really needed since some - expressions might not be valid in every situation. The 'struct tm' - might be generated by a strptime() call that initialized - only a few elements. Dereference the pointers only if the format - requires this. Then it is ok to fail if the pointers are invalid. */ -# define a_wkday \ - ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))) -# define f_wkday \ - ((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))) -# define a_month \ - ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))) -# define f_month \ - ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))) -# define a_altmonth \ - ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(ABALTMON_1) + tp->tm_mon))) -# define f_altmonth \ - ((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \ - ? "?" : _NL_CURRENT (LC_TIME, NLW(ALTMON_1) + tp->tm_mon))) -# define ampm \ - ((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \ - ? NLW(PM_STR) : NLW(AM_STR))) - -# define aw_len STRLEN (a_wkday) -# define am_len STRLEN (a_month) -# define aam_len STRLEN (a_altmonth) -# define ap_len STRLEN (ampm) -#endif -#if HAVE_TZNAME - char **tzname_vec = tzname; -#endif - const char *zone; - size_t i = 0; - STREAM_OR_CHAR_T *p = s; - const CHAR_T *f; -#if DO_MULTIBYTE && !defined COMPILE_WIDE - const char *format_end = NULL; -#endif - - zone = NULL; -#if HAVE_STRUCT_TM_TM_ZONE - /* The POSIX test suite assumes that setting - the environment variable TZ to a new value before calling strftime() - will influence the result (the %Z format) even if the information in - TP is computed with a totally different time zone. - This is bogus: though POSIX allows bad behavior like this, - POSIX does not require it. Do the right thing instead. */ - zone = (const char *) tp->tm_zone; -#endif -#if HAVE_TZNAME - if (!tz) - { - if (! (zone && *zone)) - zone = "GMT"; - } - else - { -# if !HAVE_STRUCT_TM_TM_ZONE - /* Infer the zone name from *TZ instead of from TZNAME. */ - tzname_vec = tz->tzname_copy; -# endif - } - /* The tzset() call might have changed the value. */ - if (!(zone && *zone) && tp->tm_isdst >= 0) - { - /* POSIX.1 requires that local time zone information be used as - though strftime called tzset. */ -# ifndef my_strftime - if (!*tzset_called) - { - tzset (); - *tzset_called = true; - } -# endif - zone = tzname_vec[tp->tm_isdst != 0]; - } -#endif - if (! zone) - zone = ""; - - if (hour12 > 12) - hour12 -= 12; - else - if (hour12 == 0) - hour12 = 12; - - for (f = format; *f != '\0'; width = -1, f++) - { - int pad = 0; /* Padding for number ('_', '-', '+', '0', or 0). */ - int modifier; /* Field modifier ('E', 'O', or 0). */ - int digits = 0; /* Max digits for numeric format. */ - int number_value; /* Numeric value to be printed. */ - unsigned int u_number_value; /* (unsigned int) number_value. */ - bool negative_number; /* The number is negative. */ - bool always_output_a_sign; /* +/- should always be output. */ - int tz_colon_mask; /* Bitmask of where ':' should appear. */ - const CHAR_T *subfmt; - CHAR_T *bufp; - CHAR_T buf[1 - + 2 /* for the two colons in a %::z or %:::z time zone */ - + (sizeof (int) < sizeof (time_t) - ? INT_STRLEN_BOUND (time_t) - : INT_STRLEN_BOUND (int))]; - bool to_lowcase = false; - bool to_uppcase = upcase; - size_t colons; - bool change_case = false; - int format_char; - int subwidth; - -#if DO_MULTIBYTE && !defined COMPILE_WIDE - switch (*f) - { - case L_('%'): - break; - - case L_('\b'): case L_('\t'): case L_('\n'): - case L_('\v'): case L_('\f'): case L_('\r'): - case L_(' '): case L_('!'): case L_('"'): case L_('#'): case L_('&'): - case L_('\''): case L_('('): case L_(')'): case L_('*'): case L_('+'): - case L_(','): case L_('-'): case L_('.'): case L_('/'): case L_('0'): - case L_('1'): case L_('2'): case L_('3'): case L_('4'): case L_('5'): - case L_('6'): case L_('7'): case L_('8'): case L_('9'): case L_(':'): - case L_(';'): case L_('<'): case L_('='): case L_('>'): case L_('?'): - case L_('A'): case L_('B'): case L_('C'): case L_('D'): case L_('E'): - case L_('F'): case L_('G'): case L_('H'): case L_('I'): case L_('J'): - case L_('K'): case L_('L'): case L_('M'): case L_('N'): case L_('O'): - case L_('P'): case L_('Q'): case L_('R'): case L_('S'): case L_('T'): - case L_('U'): case L_('V'): case L_('W'): case L_('X'): case L_('Y'): - case L_('Z'): case L_('['): case L_('\\'): case L_(']'): case L_('^'): - case L_('_'): case L_('a'): case L_('b'): case L_('c'): case L_('d'): - case L_('e'): case L_('f'): case L_('g'): case L_('h'): case L_('i'): - case L_('j'): case L_('k'): case L_('l'): case L_('m'): case L_('n'): - case L_('o'): case L_('p'): case L_('q'): case L_('r'): case L_('s'): - case L_('t'): case L_('u'): case L_('v'): case L_('w'): case L_('x'): - case L_('y'): case L_('z'): case L_('{'): case L_('|'): case L_('}'): - case L_('~'): - /* The C Standard requires these 98 characters (plus '%') to - be in the basic execution character set. None of these - characters can start a multibyte sequence, so they need - not be analyzed further. */ - add1 (*f); - continue; - - default: - /* Copy this multibyte sequence until we reach its end, find - an error, or come back to the initial shift state. */ - { - mbstate_t mbstate = mbstate_zero; - size_t len = 0; - size_t fsize; - - if (! format_end) - format_end = f + strlen (f) + 1; - fsize = format_end - f; - - do - { - size_t bytes = mbrlen (f + len, fsize - len, &mbstate); - - if (bytes == 0) - break; - - if (bytes == (size_t) -2) - { - len += strlen (f + len); - break; - } - - if (bytes == (size_t) -1) - { - len++; - break; - } - - len += bytes; - } - while (! mbsinit (&mbstate)); - - cpy (len, f); - f += len - 1; - continue; - } - } - -#else /* ! DO_MULTIBYTE */ - - /* Either multibyte encodings are not supported, they are - safe for formats, so any non-'%' byte can be copied through, - or this is the wide character version. */ - if (*f != L_('%')) - { - add1 (*f); - continue; - } - -#endif /* ! DO_MULTIBYTE */ - - char const *percent = f; - - /* Check for flags that can modify a format. */ - while (1) - { - switch (*++f) - { - /* This influences the number formats. */ - case L_('_'): - case L_('-'): - case L_('+'): - case L_('0'): - pad = *f; - continue; - - /* This changes textual output. */ - case L_('^'): - to_uppcase = true; - continue; - case L_('#'): - change_case = true; - continue; - - default: - break; - } - break; - } - - if (ISDIGIT (*f)) - { - width = 0; - do - { - if (INT_MULTIPLY_WRAPV (width, 10, &width) - || INT_ADD_WRAPV (width, *f - L_('0'), &width)) - width = INT_MAX; - ++f; - } - while (ISDIGIT (*f)); - } - - /* Check for modifiers. */ - switch (*f) - { - case L_('E'): - case L_('O'): - modifier = *f++; - break; - - default: - modifier = 0; - break; - } - - /* Now do the specified format. */ - format_char = *f; - switch (format_char) - { -#define DO_NUMBER(d, v) \ - do \ - { \ - digits = d; \ - number_value = v; \ - goto do_number; \ - } \ - while (0) -#define DO_SIGNED_NUMBER(d, negative, v) \ - DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_signed_number) -#define DO_YEARISH(d, negative, v) \ - DO_MAYBE_SIGNED_NUMBER (d, negative, v, do_yearish) -#define DO_MAYBE_SIGNED_NUMBER(d, negative, v, label) \ - do \ - { \ - digits = d; \ - negative_number = negative; \ - u_number_value = v; \ - goto label; \ - } \ - while (0) - - /* The mask is not what you might think. - When the ordinal i'th bit is set, insert a colon - before the i'th digit of the time zone representation. */ -#define DO_TZ_OFFSET(d, mask, v) \ - do \ - { \ - digits = d; \ - tz_colon_mask = mask; \ - u_number_value = v; \ - goto do_tz_offset; \ - } \ - while (0) -#define DO_NUMBER_SPACEPAD(d, v) \ - do \ - { \ - digits = d; \ - number_value = v; \ - goto do_number_spacepad; \ - } \ - while (0) - - case L_('%'): - if (f - 1 != percent) - goto bad_percent; - add1 (*f); - break; - - case L_('a'): - if (modifier != 0) - goto bad_format; - if (change_case) - { - to_uppcase = true; - to_lowcase = false; - } -#ifdef _NL_CURRENT - cpy (aw_len, a_wkday); - break; -#else - goto underlying_strftime; -#endif - - case 'A': - if (modifier != 0) - goto bad_format; - if (change_case) - { - to_uppcase = true; - to_lowcase = false; - } -#ifdef _NL_CURRENT - cpy (STRLEN (f_wkday), f_wkday); - break; -#else - goto underlying_strftime; -#endif - - case L_('b'): - case L_('h'): - if (change_case) - { - to_uppcase = true; - to_lowcase = false; - } - if (modifier == L_('E')) - goto bad_format; -#ifdef _NL_CURRENT - if (modifier == L_('O')) - cpy (aam_len, a_altmonth); - else - cpy (am_len, a_month); - break; -#else - goto underlying_strftime; -#endif - - case L_('B'): - if (modifier == L_('E')) - goto bad_format; - if (change_case) - { - to_uppcase = true; - to_lowcase = false; - } -#ifdef _NL_CURRENT - if (modifier == L_('O')) - cpy (STRLEN (f_altmonth), f_altmonth); - else - cpy (STRLEN (f_month), f_month); - break; -#else - goto underlying_strftime; -#endif - - case L_('c'): - if (modifier == L_('O')) - goto bad_format; -#ifdef _NL_CURRENT - if (! (modifier == L_('E') - && (*(subfmt = - (const CHAR_T *) _NL_CURRENT (LC_TIME, - NLW(ERA_D_T_FMT))) - != '\0'))) - subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_T_FMT)); -#else - goto underlying_strftime; -#endif - - subformat: - subwidth = -1; - subformat_width: - { - size_t len = __strftime_internal (NULL, STRFTIME_ARG ((size_t) -1) - subfmt, tp, to_uppcase, - pad, subwidth, tzset_called - extra_args LOCALE_ARG); - add (len, __strftime_internal (p, - STRFTIME_ARG (maxsize - i) - subfmt, tp, to_uppcase, - pad, subwidth, tzset_called - extra_args LOCALE_ARG)); - } - break; - -#if !(defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) - underlying_strftime: - { - /* The relevant information is available only via the - underlying strftime implementation, so use that. */ - char ufmt[5]; - char *u = ufmt; - char ubuf[1024]; /* enough for any single format in practice */ - size_t len; - /* Make sure we're calling the actual underlying strftime. - In some cases, config.h contains something like - "#define strftime rpl_strftime". */ -# ifdef strftime -# undef strftime - size_t strftime (); -# endif - - /* The space helps distinguish strftime failure from empty - output. */ - *u++ = ' '; - *u++ = '%'; - if (modifier != 0) - *u++ = modifier; - *u++ = format_char; - *u = '\0'; - len = strftime (ubuf, sizeof ubuf, ufmt, tp); - if (len != 0) - cpy (len - 1, ubuf + 1); - } - break; -#endif - - case L_('C'): - if (modifier == L_('E')) - { -#if HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { -# ifdef COMPILE_WIDE - size_t len = __wcslen (era->era_wname); - cpy (len, era->era_wname); -# else - size_t len = strlen (era->era_name); - cpy (len, era->era_name); -# endif - break; - } -#else - goto underlying_strftime; -#endif - } - - { - bool negative_year = tp->tm_year < - TM_YEAR_BASE; - bool zero_thru_1899 = !negative_year & (tp->tm_year < 0); - int century = ((tp->tm_year - 99 * zero_thru_1899) / 100 - + TM_YEAR_BASE / 100); - DO_YEARISH (2, negative_year, century); - } - - case L_('x'): - if (modifier == L_('O')) - goto bad_format; -#ifdef _NL_CURRENT - if (! (modifier == L_('E') - && (*(subfmt = - (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_D_FMT))) - != L_('\0')))) - subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(D_FMT)); - goto subformat; -#else - goto underlying_strftime; -#endif - case L_('D'): - if (modifier != 0) - goto bad_format; - subfmt = L_("%m/%d/%y"); - goto subformat; - - case L_('d'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, tp->tm_mday); - - case L_('e'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER_SPACEPAD (2, tp->tm_mday); - - /* All numeric formats set DIGITS and NUMBER_VALUE (or U_NUMBER_VALUE) - and then jump to one of these labels. */ - - do_tz_offset: - always_output_a_sign = true; - goto do_number_body; - - do_yearish: - if (pad == 0) - pad = yr_spec; - always_output_a_sign - = (pad == L_('+') - && ((digits == 2 ? 99 : 9999) < u_number_value - || digits < width)); - goto do_maybe_signed_number; - - do_number_spacepad: - if (pad == 0) - pad = L_('_'); - - do_number: - /* Format NUMBER_VALUE according to the MODIFIER flag. */ - negative_number = number_value < 0; - u_number_value = number_value; - - do_signed_number: - always_output_a_sign = false; - - do_maybe_signed_number: - tz_colon_mask = 0; - - do_number_body: - /* Format U_NUMBER_VALUE according to the MODIFIER flag. - NEGATIVE_NUMBER is nonzero if the original number was - negative; in this case it was converted directly to - unsigned int (i.e., modulo (UINT_MAX + 1)) without - negating it. */ - if (modifier == L_('O') && !negative_number) - { -#ifdef _NL_CURRENT - /* Get the locale specific alternate representation of - the number. If none exist NULL is returned. */ - const CHAR_T *cp = nl_get_alt_digit (u_number_value - HELPER_LOCALE_ARG); - - if (cp != NULL) - { - size_t digitlen = STRLEN (cp); - if (digitlen != 0) - { - cpy (digitlen, cp); - break; - } - } -#else - goto underlying_strftime; -#endif - } - - bufp = buf + sizeof (buf) / sizeof (buf[0]); - - if (negative_number) - u_number_value = - u_number_value; - - do - { - if (tz_colon_mask & 1) - *--bufp = ':'; - tz_colon_mask >>= 1; - *--bufp = u_number_value % 10 + L_('0'); - u_number_value /= 10; - } - while (u_number_value != 0 || tz_colon_mask != 0); - - do_number_sign_and_padding: - if (pad == 0) - pad = L_('0'); - if (width < 0) - width = digits; - - { - CHAR_T sign_char = (negative_number ? L_('-') - : always_output_a_sign ? L_('+') - : 0); - int numlen = buf + sizeof buf / sizeof buf[0] - bufp; - int shortage = width - !!sign_char - numlen; - int padding = pad == L_('-') || shortage <= 0 ? 0 : shortage; - - if (sign_char) - { - if (pad == L_('_')) - { - if (p) - memset_space (p, padding); - i += padding; - width -= padding; - } - width_add1 (0, sign_char); - width--; - } - - cpy (numlen, bufp); - } - break; - - case L_('F'): - if (modifier != 0) - goto bad_format; - if (pad == 0 && width < 0) - { - pad = L_('+'); - subwidth = 4; - } - else - { - subwidth = width - 6; - if (subwidth < 0) - subwidth = 0; - } - subfmt = L_("%Y-%m-%d"); - goto subformat_width; - - case L_('H'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, tp->tm_hour); - - case L_('I'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, hour12); - - case L_('k'): /* GNU extension. */ - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER_SPACEPAD (2, tp->tm_hour); - - case L_('l'): /* GNU extension. */ - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER_SPACEPAD (2, hour12); - - case L_('j'): - if (modifier == L_('E')) - goto bad_format; - - DO_SIGNED_NUMBER (3, tp->tm_yday < -1, tp->tm_yday + 1U); - - case L_('M'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, tp->tm_min); - - case L_('m'): - if (modifier == L_('E')) - goto bad_format; - - DO_SIGNED_NUMBER (2, tp->tm_mon < -1, tp->tm_mon + 1U); - -#ifndef _LIBC - case L_('N'): /* GNU extension. */ - if (modifier == L_('E')) - goto bad_format; - { - int n = ns, ns_digits = 9; - if (width <= 0) - width = ns_digits; - int ndigs = ns_digits; - while (width < ndigs || (1 < ndigs && n % 10 == 0)) - ndigs--, n /= 10; - for (int j = ndigs; 0 < j; j--) - buf[j - 1] = n % 10 + L_('0'), n /= 10; - if (!pad) - pad = L_('0'); - width_cpy (0, ndigs, buf); - width_add (width - ndigs, 0, (void) 0); - } - break; -#endif - - case L_('n'): - add1 (L_('\n')); - break; - - case L_('P'): - to_lowcase = true; -#ifndef _NL_CURRENT - format_char = L_('p'); -#endif - FALLTHROUGH; - case L_('p'): - if (change_case) - { - to_uppcase = false; - to_lowcase = true; - } -#ifdef _NL_CURRENT - cpy (ap_len, ampm); - break; -#else - goto underlying_strftime; -#endif - - case L_('q'): /* GNU extension. */ - DO_SIGNED_NUMBER (1, false, ((tp->tm_mon * 11) >> 5) + 1); - - case L_('R'): - subfmt = L_("%H:%M"); - goto subformat; - - case L_('r'): -#ifdef _NL_CURRENT - if (*(subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, - NLW(T_FMT_AMPM))) - == L_('\0')) - subfmt = L_("%I:%M:%S %p"); - goto subformat; -#else - goto underlying_strftime; -#endif - - case L_('S'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, tp->tm_sec); - - case L_('s'): /* GNU extension. */ - { - struct tm ltm; - time_t t; - - ltm = *tp; - ltm.tm_yday = -1; - t = mktime_z (tz, <m); - if (ltm.tm_yday < 0) - { - errno = EOVERFLOW; - return 0; - } - - /* Generate string value for T using time_t arithmetic; - this works even if sizeof (long) < sizeof (time_t). */ - - bufp = buf + sizeof (buf) / sizeof (buf[0]); - negative_number = t < 0; - - do - { - int d = t % 10; - t /= 10; - *--bufp = (negative_number ? -d : d) + L_('0'); - } - while (t != 0); - - digits = 1; - always_output_a_sign = false; - goto do_number_sign_and_padding; - } - - case L_('X'): - if (modifier == L_('O')) - goto bad_format; -#ifdef _NL_CURRENT - if (! (modifier == L_('E') - && (*(subfmt = - (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ERA_T_FMT))) - != L_('\0')))) - subfmt = (const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(T_FMT)); - goto subformat; -#else - goto underlying_strftime; -#endif - case L_('T'): - subfmt = L_("%H:%M:%S"); - goto subformat; - - case L_('t'): - add1 (L_('\t')); - break; - - case L_('u'): - DO_NUMBER (1, (tp->tm_wday - 1 + 7) % 7 + 1); - - case L_('U'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, (tp->tm_yday - tp->tm_wday + 7) / 7); - - case L_('V'): - case L_('g'): - case L_('G'): - if (modifier == L_('E')) - goto bad_format; - { - /* YEAR is a leap year if and only if (tp->tm_year + TM_YEAR_BASE) - is a leap year, except that YEAR and YEAR - 1 both work - correctly even when (tp->tm_year + TM_YEAR_BASE) would - overflow. */ - int year = (tp->tm_year - + (tp->tm_year < 0 - ? TM_YEAR_BASE % 400 - : TM_YEAR_BASE % 400 - 400)); - int year_adjust = 0; - int days = iso_week_days (tp->tm_yday, tp->tm_wday); - - if (days < 0) - { - /* This ISO week belongs to the previous year. */ - year_adjust = -1; - days = iso_week_days (tp->tm_yday + (365 + __isleap (year - 1)), - tp->tm_wday); - } - else - { - int d = iso_week_days (tp->tm_yday - (365 + __isleap (year)), - tp->tm_wday); - if (0 <= d) - { - /* This ISO week belongs to the next year. */ - year_adjust = 1; - days = d; - } - } - - switch (*f) - { - case L_('g'): - { - int yy = (tp->tm_year % 100 + year_adjust) % 100; - DO_YEARISH (2, false, - (0 <= yy - ? yy - : tp->tm_year < -TM_YEAR_BASE - year_adjust - ? -yy - : yy + 100)); - } - - case L_('G'): - DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE - year_adjust, - (tp->tm_year + (unsigned int) TM_YEAR_BASE - + year_adjust)); - - default: - DO_NUMBER (2, days / 7 + 1); - } - } - - case L_('W'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (2, (tp->tm_yday - (tp->tm_wday - 1 + 7) % 7 + 7) / 7); - - case L_('w'): - if (modifier == L_('E')) - goto bad_format; - - DO_NUMBER (1, tp->tm_wday); - - case L_('Y'): - if (modifier == L_('E')) - { -#if HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { -# ifdef COMPILE_WIDE - subfmt = era->era_wformat; -# else - subfmt = era->era_format; -# endif - if (pad == 0) - pad = yr_spec; - goto subformat; - } -#else - goto underlying_strftime; -#endif - } - if (modifier == L_('O')) - goto bad_format; - - DO_YEARISH (4, tp->tm_year < -TM_YEAR_BASE, - tp->tm_year + (unsigned int) TM_YEAR_BASE); - - case L_('y'): - if (modifier == L_('E')) - { -#if HAVE_STRUCT_ERA_ENTRY - struct era_entry *era = _nl_get_era_entry (tp HELPER_LOCALE_ARG); - if (era) - { - int delta = tp->tm_year - era->start_date[0]; - if (pad == 0) - pad = yr_spec; - DO_NUMBER (2, (era->offset - + delta * era->absolute_direction)); - } -#else - goto underlying_strftime; -#endif - } - - { - int yy = tp->tm_year % 100; - if (yy < 0) - yy = tp->tm_year < - TM_YEAR_BASE ? -yy : yy + 100; - DO_YEARISH (2, false, yy); - } - - case L_('Z'): - if (change_case) - { - to_uppcase = false; - to_lowcase = true; - } - -#ifdef COMPILE_WIDE - { - /* The zone string is always given in multibyte form. We have - to transform it first. */ - wchar_t *wczone; - size_t len; - widen (zone, wczone, len); - cpy (len, wczone); - } -#else - cpy (strlen (zone), zone); -#endif - break; - - case L_(':'): - /* :, ::, and ::: are valid only just before 'z'. - :::: etc. are rejected later. */ - for (colons = 1; f[colons] == L_(':'); colons++) - continue; - if (f[colons] != L_('z')) - goto bad_format; - f += colons; - goto do_z_conversion; - - case L_('z'): - colons = 0; - - do_z_conversion: - if (tp->tm_isdst < 0) - break; - - { - int diff; - int hour_diff; - int min_diff; - int sec_diff; -#if HAVE_TM_GMTOFF - diff = tp->tm_gmtoff; -#else - if (!tz) - diff = 0; - else - { - struct tm gtm; - struct tm ltm; - time_t lt; - - /* POSIX.1 requires that local time zone information be used as - though strftime called tzset. */ -# ifndef my_strftime - if (!*tzset_called) - { - tzset (); - *tzset_called = true; - } -# endif - - ltm = *tp; - ltm.tm_wday = -1; - lt = mktime_z (tz, <m); - if (ltm.tm_wday < 0 || ! localtime_rz (0, <, >m)) - break; - diff = tm_diff (<m, >m); - } -#endif - - negative_number = diff < 0 || (diff == 0 && *zone == '-'); - hour_diff = diff / 60 / 60; - min_diff = diff / 60 % 60; - sec_diff = diff % 60; - - switch (colons) - { - case 0: /* +hhmm */ - DO_TZ_OFFSET (5, 0, hour_diff * 100 + min_diff); - - case 1: tz_hh_mm: /* +hh:mm */ - DO_TZ_OFFSET (6, 04, hour_diff * 100 + min_diff); - - case 2: tz_hh_mm_ss: /* +hh:mm:ss */ - DO_TZ_OFFSET (9, 024, - hour_diff * 10000 + min_diff * 100 + sec_diff); - - case 3: /* +hh if possible, else +hh:mm, else +hh:mm:ss */ - if (sec_diff != 0) - goto tz_hh_mm_ss; - if (min_diff != 0) - goto tz_hh_mm; - DO_TZ_OFFSET (3, 0, hour_diff); - - default: - goto bad_format; - } - } - - case L_('\0'): /* GNU extension: % at end of format. */ - bad_percent: - --f; - FALLTHROUGH; - default: - /* Unknown format; output the format, including the '%', - since this is most likely the right thing to do if a - multibyte string has been misparsed. */ - bad_format: - cpy (f - percent + 1, percent); - break; - } - } - -#if ! FPRINTFTIME - if (p && maxsize != 0) - *p = L_('\0'); -#endif - - errno = saved_errno; - return i; -} diff --git a/xcompile/lib/open.c b/xcompile/lib/open.c deleted file mode 100644 index 7ec8fdc35dc..00000000000 --- a/xcompile/lib/open.c +++ /dev/null @@ -1,209 +0,0 @@ -/* Open a descriptor to a file. - Copyright (C) 2007-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Bruno Haible , 2007. */ - -/* If the user's config.h happens to include , let it include only - the system's here, so that orig_open doesn't recurse to - rpl_open. */ -#define __need_system_fcntl_h -#include - -/* Get the original definition of open. It might be defined as a macro. */ -#include -#include -#undef __need_system_fcntl_h - -static int -orig_open (const char *filename, int flags, mode_t mode) -{ -#if defined _WIN32 && !defined __CYGWIN__ - return _open (filename, flags, mode); -#else - return open (filename, flags, mode); -#endif -} - -/* Specification. */ -/* Write "fcntl.h" here, not , otherwise OSF/1 5.1 DTK cc eliminates - this include because of the preliminary #include above. */ -#include "fcntl.h" - -#include "cloexec.h" - -#include -#include -#include -#include -#include -#include - -#ifndef REPLACE_OPEN_DIRECTORY -# define REPLACE_OPEN_DIRECTORY 0 -#endif - -int -open (const char *filename, int flags, ...) -{ - /* 0 = unknown, 1 = yes, -1 = no. */ -#if GNULIB_defined_O_CLOEXEC - int have_cloexec = -1; -#else - static int have_cloexec; -#endif - - mode_t mode; - int fd; - - mode = 0; - if (flags & O_CREAT) - { - va_list arg; - va_start (arg, flags); - - /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 - creates crashing code when 'mode_t' is smaller than 'int'. */ - mode = va_arg (arg, PROMOTED_MODE_T); - - va_end (arg); - } - -#if GNULIB_defined_O_NONBLOCK - /* The only known platform that lacks O_NONBLOCK is mingw, but it - also lacks named pipes and Unix sockets, which are the only two - file types that require non-blocking handling in open(). - Therefore, it is safe to ignore O_NONBLOCK here. It is handy - that mingw also lacks openat(), so that is also covered here. */ - flags &= ~O_NONBLOCK; -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ - if (strcmp (filename, "/dev/null") == 0) - filename = "NUL"; -#endif - -#if OPEN_TRAILING_SLASH_BUG - /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename - ends in a slash, as POSIX says such a filename must name a directory - : - "A pathname that contains at least one non- character and that - ends with one or more trailing characters shall not be resolved - successfully unless the last pathname component before the trailing - characters names an existing directory" - If the named file already exists as a directory, then - - if O_CREAT is specified, open() must fail because of the semantics - of O_CREAT, - - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX - - says that it fails with errno = EISDIR in this case. - If the named file does not exist or does not name a directory, then - - if O_CREAT is specified, open() must fail since open() cannot create - directories, - - if O_WRONLY or O_RDWR is specified, open() must fail because the - file does not contain a '.' directory. */ - if ((flags & O_CREAT) - || (flags & O_ACCMODE) == O_RDWR - || (flags & O_ACCMODE) == O_WRONLY) - { - size_t len = strlen (filename); - if (len > 0 && filename[len - 1] == '/') - { - errno = EISDIR; - return -1; - } - } -#endif - - fd = orig_open (filename, - flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); - - if (flags & O_CLOEXEC) - { - if (! have_cloexec) - { - if (0 <= fd) - have_cloexec = 1; - else if (errno == EINVAL) - { - fd = orig_open (filename, flags & ~O_CLOEXEC, mode); - have_cloexec = -1; - } - } - if (have_cloexec < 0 && 0 <= fd) - set_cloexec_flag (fd, true); - } - - -#if REPLACE_FCHDIR - /* Implementing fchdir and fdopendir requires the ability to open a - directory file descriptor. If open doesn't support that (as on - mingw), we use a dummy file that behaves the same as directories - on Linux (ie. always reports EOF on attempts to read()), and - override fstat() in fchdir.c to hide the fact that we have a - dummy. */ - if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES - && ((flags & O_ACCMODE) == O_RDONLY - || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) - { - struct stat statbuf; - if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) - { - /* Maximum recursion depth of 1. */ - fd = open ("/dev/null", flags, mode); - if (0 <= fd) - fd = _gl_register_fd (fd, filename); - } - else - errno = EACCES; - } -#endif - -#if OPEN_TRAILING_SLASH_BUG - /* If the filename ends in a slash and fd does not refer to a directory, - then fail. - Rationale: POSIX says such a filename must name a directory - : - "A pathname that contains at least one non- character and that - ends with one or more trailing characters shall not be resolved - successfully unless the last pathname component before the trailing - characters names an existing directory" - If the named file without the slash is not a directory, open() must fail - with ENOTDIR. */ - if (fd >= 0) - { - /* We know len is positive, since open did not fail with ENOENT. */ - size_t len = strlen (filename); - if (filename[len - 1] == '/') - { - struct stat statbuf; - - if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) - { - close (fd); - errno = ENOTDIR; - return -1; - } - } - } -#endif - -#if REPLACE_FCHDIR - if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) - fd = _gl_register_fd (fd, filename); -#endif - - return fd; -} diff --git a/xcompile/lib/openat-die.c b/xcompile/lib/openat-die.c deleted file mode 100644 index 8dab8b97429..00000000000 --- a/xcompile/lib/openat-die.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Respond to a save- or restore-cwd failure. - This should never happen with Emacs. */ -#include -#include "openat.h" -#include -void openat_save_fail (int errnum) { abort (); } -void openat_restore_fail (int errnum) { abort (); } diff --git a/xcompile/lib/openat-priv.h b/xcompile/lib/openat-priv.h deleted file mode 100644 index 1d31c4e83cb..00000000000 --- a/xcompile/lib/openat-priv.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Internals for openat-like functions. - - Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Jim Meyering */ - -#ifndef _GL_HEADER_OPENAT_PRIV -#define _GL_HEADER_OPENAT_PRIV - -#include -#include -#include - -/* Maximum number of bytes that it is safe to allocate as a single - array on the stack, and that is known as a compile-time constant. - The assumption is that we'll touch the array very quickly, or a - temporary very near the array, provoking an out-of-memory trap. On - some operating systems, there is only one guard page for the stack, - and a page size can be as small as 4096 bytes. Subtract 64 in the - hope that this will let the compiler touch a nearby temporary and - provoke a trap. */ -#define SAFER_ALLOCA_MAX (4096 - 64) - -#define SAFER_ALLOCA(m) ((m) < SAFER_ALLOCA_MAX ? (m) : SAFER_ALLOCA_MAX) - -#if defined PATH_MAX -# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (PATH_MAX) -#elif defined _XOPEN_PATH_MAX -# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (_XOPEN_PATH_MAX) -#else -# define OPENAT_BUFFER_SIZE SAFER_ALLOCA (1024) -#endif - -char *openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file); - -/* Trying to access a BUILD_PROC_NAME file will fail on systems without - /proc support, and even on systems *with* ProcFS support. Return - nonzero if the failure may be legitimate, e.g., because /proc is not - readable, or the particular .../fd/N directory is not present. */ -#define EXPECTED_ERRNO(Errno) \ - ((Errno) == ENOTDIR || (Errno) == ENOENT \ - || (Errno) == EPERM || (Errno) == EACCES \ - || (Errno) == ENOSYS /* Solaris 8 */ \ - || (Errno) == EOPNOTSUPP /* FreeBSD */) - -/* Wrapper function shared among linkat and renameat. */ -int at_func2 (int fd1, char const *file1, - int fd2, char const *file2, - int (*func) (char const *file1, char const *file2)); - -#endif /* _GL_HEADER_OPENAT_PRIV */ diff --git a/xcompile/lib/openat-proc.c b/xcompile/lib/openat-proc.c deleted file mode 100644 index 2a6a85f0696..00000000000 --- a/xcompile/lib/openat-proc.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Create /proc/self/fd-related names for subfiles of open directories. - - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -#include - -#include "openat-priv.h" - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef __KLIBC__ -# include -#endif - -#include "intprops.h" - -/* Set BUF to the name of the subfile of the directory identified by - FD, where the subfile is named FILE. If successful, return BUF if - the result fits in BUF, dynamically allocated memory otherwise. - Return NULL (setting errno) on error. */ -char * -openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char const *file) -{ - char *result = buf; - int dirlen; - - /* Make sure the caller gets ENOENT when appropriate. */ - if (!*file) - { - buf[0] = '\0'; - return buf; - } - -#ifndef __KLIBC__ -# define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/" - { - enum { - PROC_SELF_FD_DIR_SIZE_BOUND - = (sizeof PROC_SELF_FD_FORMAT - (sizeof "%d" - 1) - + INT_STRLEN_BOUND (int)) - }; - - static int proc_status = 0; - if (! proc_status) - { - /* Set PROC_STATUS to a positive value if /proc/self/fd is - reliable, and a negative value otherwise. Solaris 10 - /proc/self/fd mishandles "..", and any file name might expand - to ".." after symbolic link expansion, so avoid /proc/self/fd - if it mishandles "..". Solaris 10 has openat, but this - problem is exhibited on code that built on Solaris 8 and - running on Solaris 10. */ - - int proc_self_fd = - open ("/proc/self/fd", - O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | O_CLOEXEC); - if (proc_self_fd < 0) - proc_status = -1; - else - { - /* Detect whether /proc/self/fd/%i/../fd exists, where %i is the - number of a file descriptor open on /proc/self/fd. On Linux, - that name resolves to /proc/self/fd, which was opened above. - However, on Solaris, it may resolve to /proc/self/fd/fd, which - cannot exist, since all names in /proc/self/fd are numeric. */ - char dotdot_buf[PROC_SELF_FD_DIR_SIZE_BOUND + sizeof "../fd" - 1]; - sprintf (dotdot_buf, PROC_SELF_FD_FORMAT "../fd", proc_self_fd); - proc_status = access (dotdot_buf, F_OK) ? -1 : 1; - close (proc_self_fd); - } - } - - if (proc_status < 0) - return NULL; - else - { - size_t bufsize = PROC_SELF_FD_DIR_SIZE_BOUND + strlen (file); - if (OPENAT_BUFFER_SIZE < bufsize) - { - result = malloc (bufsize); - if (! result) - return NULL; - } - - dirlen = sprintf (result, PROC_SELF_FD_FORMAT, fd); - } - } -#else - /* OS/2 kLIBC provides a function to retrieve a path from a fd. */ - { - char dir[_MAX_PATH]; - size_t bufsize; - - if (__libc_Back_ioFHToPath (fd, dir, sizeof dir)) - return NULL; - - dirlen = strlen (dir); - bufsize = dirlen + 1 + strlen (file) + 1; /* 1 for '/', 1 for null */ - if (OPENAT_BUFFER_SIZE < bufsize) - { - result = malloc (bufsize); - if (! result) - return NULL; - } - - strcpy (result, dir); - result[dirlen++] = '/'; - } -#endif - - strcpy (result + dirlen, file); - return result; -} diff --git a/xcompile/lib/openat.h b/xcompile/lib/openat.h deleted file mode 100644 index 37d8eedbee4..00000000000 --- a/xcompile/lib/openat.h +++ /dev/null @@ -1,124 +0,0 @@ -/* provide a replacement openat function - Copyright (C) 2004-2006, 2008-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Jim Meyering */ - -#ifndef _GL_HEADER_OPENAT -#define _GL_HEADER_OPENAT - -#include - -#include -#include -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN - -#if !HAVE_OPENAT - -int openat_permissive (int fd, char const *file, int flags, mode_t mode, - int *cwd_errno); -bool openat_needs_fchdir (void); - -#else - -# define openat_permissive(Fd, File, Flags, Mode, Cwd_errno) \ - openat (Fd, File, Flags, Mode) -# define openat_needs_fchdir() false - -#endif - -_Noreturn void openat_restore_fail (int); -_Noreturn void openat_save_fail (int); - -/* Using these function names makes application code - slightly more readable than it would be with - fchownat (..., 0) or fchownat (..., AT_SYMLINK_NOFOLLOW). */ - -#if GNULIB_CHOWNAT - -# ifndef CHOWNAT_INLINE -# define CHOWNAT_INLINE _GL_INLINE -# endif - -CHOWNAT_INLINE int -chownat (int fd, char const *file, uid_t owner, gid_t group) -{ - return fchownat (fd, file, owner, group, 0); -} - -CHOWNAT_INLINE int -lchownat (int fd, char const *file, uid_t owner, gid_t group) -{ - return fchownat (fd, file, owner, group, AT_SYMLINK_NOFOLLOW); -} - -#endif - -#if GNULIB_CHMODAT - -# ifndef CHMODAT_INLINE -# define CHMODAT_INLINE _GL_INLINE -# endif - -CHMODAT_INLINE int -chmodat (int fd, char const *file, mode_t mode) -{ - return fchmodat (fd, file, mode, 0); -} - -CHMODAT_INLINE int -lchmodat (int fd, char const *file, mode_t mode) -{ - return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); -} - -#endif - -#if GNULIB_STATAT - -# ifndef STATAT_INLINE -# define STATAT_INLINE _GL_INLINE -# endif - -_GL_ATTRIBUTE_DEPRECATED -STATAT_INLINE int -statat (int fd, char const *name, struct stat *st) -{ - return fstatat (fd, name, st, 0); -} - -_GL_ATTRIBUTE_DEPRECATED -STATAT_INLINE int -lstatat (int fd, char const *name, struct stat *st) -{ - return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); -} - -#endif - -/* For now, there are no wrappers named laccessat or leuidaccessat, - since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and - since access rights on symlinks are of limited utility. Likewise, - wrappers are not provided for accessat or euidaccessat, so as to - avoid dragging in -lgen on some platforms. */ - -_GL_INLINE_HEADER_END - -#endif /* _GL_HEADER_OPENAT */ diff --git a/xcompile/lib/pathmax.h b/xcompile/lib/pathmax.h deleted file mode 100644 index 0dd8f3bc5ce..00000000000 --- a/xcompile/lib/pathmax.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Define PATH_MAX somehow. Requires sys/types.h. - Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _PATHMAX_H -# define _PATHMAX_H - -/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, - including the terminating NUL byte. - - PATH_MAX is not defined on systems which have no limit on filename length, - such as GNU/Hurd. - - This file does *not* define PATH_MAX always. Programs that use this file - can handle the GNU/Hurd case in several ways: - - Either with a package-wide handling, or with a per-file handling, - - Either through a - #ifdef PATH_MAX - or through a fallback like - #ifndef PATH_MAX - # define PATH_MAX 8192 - #endif - or through a fallback like - #ifndef PATH_MAX - # define PATH_MAX pathconf ("/", _PC_PATH_MAX) - #endif - */ - -# include - -# include - -# ifndef _POSIX_PATH_MAX -# define _POSIX_PATH_MAX 256 -# endif - -/* Don't include sys/param.h if it already has been. */ -# if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN -# include -# endif - -# if !defined PATH_MAX && defined MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# endif - -# ifdef __hpux -/* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, - *not* including the terminating NUL byte, and is set to 1023. - Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is - not defined at all any more. */ -# undef PATH_MAX -# define PATH_MAX 1024 -# endif - -# if defined _WIN32 && ! defined __CYGWIN__ -/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, - section "Maximum Path Length Limitation", - - explains that the maximum size of a filename, including the terminating - NUL byte, is 260 = 3 + 256 + 1. - This is the same value as - - FILENAME_MAX in , - - _MAX_PATH in , - - MAX_PATH in . - Undefine the original value, because mingw's gets it wrong. */ -# undef PATH_MAX -# define PATH_MAX 260 -# endif - -#endif /* _PATHMAX_H */ diff --git a/xcompile/lib/pipe2.c b/xcompile/lib/pipe2.c deleted file mode 100644 index 8f06575a1dd..00000000000 --- a/xcompile/lib/pipe2.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Create a pipe, with specific opening flags. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include - -#include "binary-io.h" - -#if GNULIB_defined_O_NONBLOCK -# include "nonblocking.h" -#endif - -#if defined _WIN32 && ! defined __CYGWIN__ -/* Native Windows API. */ - -# include - -#endif - -int -pipe2 (int fd[2], int flags) -{ - /* Mingw _pipe() corrupts fd on failure; also, if we succeed at - creating the pipe but later fail at changing fcntl, we want - to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */ - int tmp[2]; - tmp[0] = fd[0]; - tmp[1] = fd[1]; - -#if HAVE_PIPE2 -# undef pipe2 - /* Try the system call first, if it exists. (We may be running with a glibc - that has the function but with an older kernel that lacks it.) */ - { - /* Cache the information whether the system call really exists. */ - static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */ - if (have_pipe2_really >= 0) - { - int result = pipe2 (fd, flags); - if (!(result < 0 && errno == ENOSYS)) - { - have_pipe2_really = 1; - return result; - } - have_pipe2_really = -1; - } - } -#endif - - /* Check the supported flags. */ - if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0) - { - errno = EINVAL; - return -1; - } - -#if defined _WIN32 && ! defined __CYGWIN__ -/* Native Windows API. */ - - if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0) - { - fd[0] = tmp[0]; - fd[1] = tmp[1]; - return -1; - } - - /* O_NONBLOCK handling. - On native Windows platforms, O_NONBLOCK is defined by gnulib. Use the - functions defined by the gnulib module 'nonblocking'. */ -# if GNULIB_defined_O_NONBLOCK - if (flags & O_NONBLOCK) - { - if (set_nonblocking_flag (fd[0], true) != 0 - || set_nonblocking_flag (fd[1], true) != 0) - goto fail; - } -# else - { - static_assert (O_NONBLOCK == 0); - } -# endif - - return 0; - -#else -/* Unix API. */ - - if (pipe (fd) < 0) - return -1; - - /* POSIX - says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on - both fd[0] and fd[1]. */ - - /* O_NONBLOCK handling. - On Unix platforms, O_NONBLOCK is defined by the system. Use fcntl(). */ - if (flags & O_NONBLOCK) - { - int fcntl_flags; - - if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 - || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1 - || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 - || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1) - goto fail; - } - - if (flags & O_CLOEXEC) - { - int fcntl_flags; - - if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0 - || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1 - || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0 - || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) - goto fail; - } - -# if O_BINARY - if (flags & O_BINARY) - { - set_binary_mode (fd[1], O_BINARY); - set_binary_mode (fd[0], O_BINARY); - } - else if (flags & O_TEXT) - { - set_binary_mode (fd[1], O_TEXT); - set_binary_mode (fd[0], O_TEXT); - } -# endif - - return 0; - -#endif - -#if GNULIB_defined_O_NONBLOCK || !(defined _WIN32 && ! defined __CYGWIN__) - fail: - { - int saved_errno = errno; - close (fd[0]); - close (fd[1]); - fd[0] = tmp[0]; - fd[1] = tmp[1]; - errno = saved_errno; - return -1; - } -#endif -} diff --git a/xcompile/lib/pselect.c b/xcompile/lib/pselect.c deleted file mode 100644 index f5d21e1048a..00000000000 --- a/xcompile/lib/pselect.c +++ /dev/null @@ -1,110 +0,0 @@ -/* pselect - synchronous I/O multiplexing - - Copyright 2011-2023 Free Software Foundation, Inc. - - This file is part of gnulib. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Paul Eggert */ - -#include - -#include - -#include -#include - -/* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS - to see whether some of their descriptors are ready for reading, - ready for writing, or have exceptions pending. Wait for at most - TIMEOUT seconds, and use signal mask SIGMASK while waiting. A null - pointer parameter stands for no descriptors, an infinite timeout, - or an unaffected signal mask. */ - -#if !HAVE_PSELECT - -int -pselect (int nfds, fd_set *restrict rfds, - fd_set *restrict wfds, fd_set *restrict xfds, - struct timespec const *restrict timeout, - sigset_t const *restrict sigmask) -{ - int select_result; - sigset_t origmask; - struct timeval tv, *tvp; - - if (timeout) - { - if (! (0 <= timeout->tv_nsec && timeout->tv_nsec < 1000000000)) - { - errno = EINVAL; - return -1; - } - - tv.tv_sec = timeout->tv_sec; - tv.tv_usec = (timeout->tv_nsec + 999) / 1000; - tvp = &tv; - } - else - tvp = NULL; - - /* Signal mask munging should be atomic, but this is the best we can - do in this emulation. */ - if (sigmask) - pthread_sigmask (SIG_SETMASK, sigmask, &origmask); - - select_result = select (nfds, rfds, wfds, xfds, tvp); - - if (sigmask) - { - int select_errno = errno; - pthread_sigmask (SIG_SETMASK, &origmask, NULL); - errno = select_errno; - } - - return select_result; -} - -#else /* HAVE_PSELECT */ -# include -# undef pselect - -int -rpl_pselect (int nfds, fd_set *restrict rfds, - fd_set *restrict wfds, fd_set *restrict xfds, - struct timespec const *restrict timeout, - sigset_t const *restrict sigmask) -{ - int i; - - /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */ - if (nfds < 0 || nfds > FD_SETSIZE) - { - errno = EINVAL; - return -1; - } - for (i = 0; i < nfds; i++) - { - if (((rfds && FD_ISSET (i, rfds)) - || (wfds && FD_ISSET (i, wfds)) - || (xfds && FD_ISSET (i, xfds))) - && dup2 (i, i) != i) - return -1; - } - - return pselect (nfds, rfds, wfds, xfds, timeout, sigmask); -} - -#endif diff --git a/xcompile/lib/pthread_sigmask.c b/xcompile/lib/pthread_sigmask.c deleted file mode 100644 index 128107582a7..00000000000 --- a/xcompile/lib/pthread_sigmask.c +++ /dev/null @@ -1,92 +0,0 @@ -/* POSIX compatible signal blocking for threads. - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include - -#if PTHREAD_SIGMASK_INEFFECTIVE -# include -#endif - -#if PTHREAD_SIGMASK_UNBLOCK_BUG -# include -#endif - -int -pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) -#undef pthread_sigmask -{ -#if HAVE_PTHREAD_SIGMASK - int ret; - -# if PTHREAD_SIGMASK_INEFFECTIVE - sigset_t omask, omask_copy; - sigset_t *old_mask_ptr = &omask; - sigemptyset (&omask); - /* Add a signal unlikely to be blocked, so that OMASK_COPY - is unlikely to match the actual mask. */ - sigaddset (&omask, SIGILL); - memcpy (&omask_copy, &omask, sizeof omask); -# else - sigset_t *old_mask_ptr = old_mask; -# endif - - ret = pthread_sigmask (how, new_mask, old_mask_ptr); - -# if PTHREAD_SIGMASK_INEFFECTIVE - if (ret == 0) - { - /* Detect whether pthread_sigmask is currently ineffective. - Don't cache the information: libpthread.so could be dynamically - loaded after the program started and after pthread_sigmask was - called for the first time. */ - if (memcmp (&omask_copy, &omask, sizeof omask) == 0 - && pthread_sigmask (1729, &omask_copy, NULL) == 0) - { - /* pthread_sigmask is currently ineffective. The program is not - linked to -lpthread. So use sigprocmask instead. */ - return (sigprocmask (how, new_mask, old_mask) < 0 ? errno : 0); - } - - if (old_mask) - memcpy (old_mask, &omask, sizeof omask); - } -# endif -# if PTHREAD_SIGMASK_FAILS_WITH_ERRNO - if (ret == -1) - return errno; -# endif -# if PTHREAD_SIGMASK_UNBLOCK_BUG - if (ret == 0 - && new_mask != NULL - && (how == SIG_UNBLOCK || how == SIG_SETMASK)) - { - /* Give the OS the opportunity to raise signals that were pending before - the pthread_sigmask call and have now been unblocked. */ - usleep (1); - } -# endif - return ret; -#else - int ret = sigprocmask (how, new_mask, old_mask); - return (ret < 0 ? errno : 0); -#endif -} diff --git a/xcompile/lib/qcopy-acl.c b/xcompile/lib/qcopy-acl.c deleted file mode 100644 index 0f4159b7fd9..00000000000 --- a/xcompile/lib/qcopy-acl.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copy access control list from one file to another. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -#include - -#include "acl.h" - -#include "acl-internal.h" - -#if USE_XATTR - -# include - -/* Returns 1 if NAME is the name of an extended attribute that is related - to permissions, i.e. ACLs. Returns 0 otherwise. */ - -static int -is_attr_permissions (const char *name, struct error_context *ctx) -{ - return attr_copy_action (name, ctx) == ATTR_ACTION_PERMISSIONS; -} - -#endif /* USE_XATTR */ - -/* Copy access control lists from one file to another. If SOURCE_DESC is - a valid file descriptor, use file descriptor operations, else use - filename based operations on SRC_NAME. Likewise for DEST_DESC and - DST_NAME. - If access control lists are not available, fchmod the target file to - MODE. Also sets the non-permission bits of the destination file - (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. - Return 0 if successful. - Return -2 and set errno for an error relating to the source file. - Return -1 and set errno for an error relating to the destination file. */ - -int -qcopy_acl (const char *src_name, int source_desc, const char *dst_name, - int dest_desc, mode_t mode) -{ - int ret; - -#ifdef USE_XATTR - /* in case no ACLs present and also to set higher mode bits - we chmod before setting ACLs as doing it after could overwrite them - (especially true for NFSv4, posix ACL has that ugly "mask" hack that - nobody understands) */ - ret = chmod_or_fchmod (dst_name, dest_desc, mode); - /* Rather than fiddling with acls one by one, we just copy the whole ACL xattrs - (Posix or NFSv4). Of course, that won't address ACLs conversion - (i.e. posix <-> nfs4) but we can't do it anyway, so for now, we don't care - Functions attr_copy_* return 0 in case we copied something OR nothing - to copy */ - if (ret == 0) - ret = source_desc <= 0 || dest_desc <= 0 - ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) - : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, - is_attr_permissions, NULL); -#else - /* no XATTR, so we proceed the old dusty way */ - struct permission_context ctx; - - ret = get_permissions (src_name, source_desc, mode, &ctx); - if (ret != 0) - return -2; - ret = set_permissions (&ctx, dst_name, dest_desc); - free_permission_context (&ctx); -#endif - return ret; -} diff --git a/xcompile/lib/rawmemchr.c b/xcompile/lib/rawmemchr.c deleted file mode 100644 index 45c6cd35276..00000000000 --- a/xcompile/lib/rawmemchr.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Searching in a string. - Copyright (C) 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* A function definition is only needed if HAVE_RAWMEMCHR is not defined. */ -#if !HAVE_RAWMEMCHR - -# include -# include - - -/* Find the first occurrence of C in S. */ -void * -rawmemchr (const void *s, int c_in) -{ - /* Change this typedef to experiment with performance. */ - typedef uintptr_t longword; - /* If you change the "uintptr_t", you should change UINTPTR_WIDTH to match. - This verifies that the type does not have padding bits. */ - static_assert (UINTPTR_WIDTH == UCHAR_WIDTH * sizeof (longword)); - - const unsigned char *char_ptr; - unsigned char c = c_in; - - /* Handle the first few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - (uintptr_t) char_ptr % alignof (longword) != 0; - ++char_ptr) - if (*char_ptr == c) - return (void *) char_ptr; - - longword const *longword_ptr = s = char_ptr; - - /* Compute auxiliary longword values: - repeated_one is a value which has a 1 in every byte. - repeated_c has c in every byte. */ - longword repeated_one = (longword) -1 / UCHAR_MAX; - longword repeated_c = repeated_one * c; - longword repeated_hibit = repeated_one * (UCHAR_MAX / 2 + 1); - - /* Instead of the traditional loop which tests each byte, we will - test a longword at a time. The tricky part is testing if any of - the bytes in the longword in question are equal to - c. We first use an xor with repeated_c. This reduces the task - to testing whether any of the bytes in longword1 is zero. - - (The following comments assume 8-bit bytes, as POSIX requires; - the code's use of UCHAR_MAX should work even if bytes have more - than 8 bits.) - - We compute tmp = - ((longword1 - repeated_one) & ~longword1) & (repeated_one * 0x80). - That is, we perform the following operations: - 1. Subtract repeated_one. - 2. & ~longword1. - 3. & a mask consisting of 0x80 in every byte. - Consider what happens in each byte: - - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, - and step 3 transforms it into 0x80. A carry can also be propagated - to more significant bytes. - - If a byte of longword1 is nonzero, let its lowest 1 bit be at - position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, - the byte ends in a single bit of value 0 and k bits of value 1. - After step 2, the result is just k bits of value 1: 2^k - 1. After - step 3, the result is 0. And no carry is produced. - So, if longword1 has only non-zero bytes, tmp is zero. - Whereas if longword1 has a zero byte, call j the position of the least - significant zero byte. Then the result has a zero at positions 0, ..., - j-1 and a 0x80 at position j. We cannot predict the result at the more - significant bytes (positions j+1..3), but it does not matter since we - already have a non-zero bit at position 8*j+7. - - The test whether any byte in longword1 is zero is equivalent - to testing whether tmp is nonzero. - - This test can read beyond the end of a string, depending on where - C_IN is encountered. However, this is considered safe since the - initialization phase ensured that the read will be aligned, - therefore, the read will not cross page boundaries and will not - cause a fault. */ - - while (1) - { - longword longword1 = *longword_ptr ^ repeated_c; - - if ((((longword1 - repeated_one) & ~longword1) & repeated_hibit) != 0) - break; - longword_ptr++; - } - - char_ptr = s = longword_ptr; - - /* At this point, we know that one of the sizeof (longword) bytes - starting at char_ptr is == c. If we knew endianness, we - could determine the first such byte without any further memory - accesses, just by looking at the tmp result from the last loop - iteration. However, the following simple and portable code does - not attempt this potential optimization. */ - - while (*char_ptr != c) - char_ptr++; - return (void *) char_ptr; -} - -#endif diff --git a/xcompile/lib/rawmemchr.valgrind b/xcompile/lib/rawmemchr.valgrind deleted file mode 100644 index f3e4cb0f655..00000000000 --- a/xcompile/lib/rawmemchr.valgrind +++ /dev/null @@ -1,28 +0,0 @@ -# Suppress a valgrind message about use of uninitialized memory in rawmemchr(). - -# Copyright (C) 2008-2023 Free Software Foundation, Inc. -# -# This file 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 file is distributed in the hope that 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 program. If not, see . - -# This use is OK because it provides only a speedup. -{ - rawmemchr-value4 - Memcheck:Value4 - fun:rawmemchr -} -{ - rawmemchr-value8 - Memcheck:Value8 - fun:rawmemchr -} diff --git a/xcompile/lib/readlink.c b/xcompile/lib/readlink.c deleted file mode 100644 index 14bbb7f10ca..00000000000 --- a/xcompile/lib/readlink.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Read the contents of a symbolic link. - Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include - -#if !HAVE_READLINK - -/* readlink() substitute for systems that don't have a readlink() function, - such as DJGPP 2.03 and mingw32. */ - -ssize_t -readlink (char const *file, _GL_UNUSED char *buf, - _GL_UNUSED size_t bufsize) -{ - struct stat statbuf; - - /* In general we should use lstat() here, not stat(). But on platforms - without symbolic links, lstat() - if it exists - would be equivalent to - stat(), therefore we can use stat(). This saves us a configure check. */ - if (stat (file, &statbuf) >= 0) - errno = EINVAL; - return -1; -} - -#else /* HAVE_READLINK */ - -# undef readlink - -/* readlink() wrapper that uses correct types, for systems like cygwin - 1.5.x where readlink returns int, and which rejects trailing slash, - for Solaris 9. */ - -ssize_t -rpl_readlink (char const *file, char *buf, size_t bufsize) -{ -# if READLINK_TRAILING_SLASH_BUG - size_t file_len = strlen (file); - if (file_len && file[file_len - 1] == '/') - { - /* Even if FILE without the slash is a symlink to a directory, - both lstat() and stat() must resolve the trailing slash to - the directory rather than the symlink. We can therefore - safely use stat() to distinguish between EINVAL and - ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */ - struct stat st; - if (stat (file, &st) == 0 || errno == EOVERFLOW) - errno = EINVAL; - return -1; - } -# endif /* READLINK_TRAILING_SLASH_BUG */ - - ssize_t r = readlink (file, buf, bufsize); - -# if READLINK_TRUNCATE_BUG - if (r < 0 && errno == ERANGE) - { - /* Try again with a bigger buffer. This is just for test cases; - real code invariably discards short reads. */ - char stackbuf[4032]; - r = readlink (file, stackbuf, sizeof stackbuf); - if (r < 0) - { - if (errno == ERANGE) - { - /* Clear the buffer, which is good enough for real code. - Thankfully, no test cases try short reads of enormous - symlinks and what would be the point anyway? */ - r = bufsize; - memset (buf, 0, r); - } - } - else - { - if (bufsize < r) - r = bufsize; - memcpy (buf, stackbuf, r); - } - } -# endif - - return r; -} - -#endif /* HAVE_READLINK */ diff --git a/xcompile/lib/readlinkat.c b/xcompile/lib/readlinkat.c deleted file mode 100644 index 7738ba8bfd5..00000000000 --- a/xcompile/lib/readlinkat.c +++ /dev/null @@ -1,113 +0,0 @@ -/* Read a symlink relative to an open directory. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Eric Blake */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include - -#if HAVE_READLINKAT - -# undef fstatat -# undef readlinkat - -ssize_t -rpl_readlinkat (int fd, char const *file, char *buf, size_t bufsize) -{ -# if READLINK_TRAILING_SLASH_BUG - size_t file_len = strlen (file); - if (file_len && file[file_len - 1] == '/') - { - /* Even if FILE without the slash is a symlink to a directory, - both lstat() and stat() must resolve the trailing slash to - the directory rather than the symlink. We can therefore - safely use fstatat(..., 0) to distinguish between EINVAL and - ENOTDIR/ENOENT, avoiding extra overhead of rpl_fstatat(). */ - struct stat st; - if (fstatat (fd, file, &st, 0) == 0 || errno == EOVERFLOW) - errno = EINVAL; - return -1; - } -# endif /* READLINK_TRAILING_SLASH_BUG */ - - ssize_t r = readlinkat (fd, file, buf, bufsize); - -# if READLINK_TRUNCATE_BUG - if (r < 0 && errno == ERANGE) - { - /* Try again with a bigger buffer. This is just for test cases; - real code invariably discards short reads. */ - char stackbuf[4032]; - r = readlinkat (fd, file, stackbuf, sizeof stackbuf); - if (r < 0) - { - if (errno == ERANGE) - { - /* Clear the buffer, which is good enough for real code. - Thankfully, no test cases try short reads of enormous - symlinks and what would be the point anyway? */ - r = bufsize; - memset (buf, 0, r); - } - } - else - { - if (bufsize < r) - r = bufsize; - memcpy (buf, stackbuf, r); - } - } -# endif - - return r; -} - -#else - -/* Gnulib provides a readlink stub for mingw; use it for distinction - between EINVAL and ENOENT, rather than always failing with ENOSYS. */ - -/* POSIX 2008 says that unlike readlink, readlinkat returns 0 for - success instead of the buffer length. But this would render - readlinkat worthless since readlink does not guarantee a - NUL-terminated buffer. Assume this was a bug in POSIX. */ - -/* Read the contents of symlink FILE into buffer BUF of size BUFSIZE, in the - directory open on descriptor FD. If possible, do it without changing - the working directory. Otherwise, resort to using save_cwd/fchdir, - then readlink/restore_cwd. If either the save_cwd or the restore_cwd - fails, then give a diagnostic and exit nonzero. */ - -# define AT_FUNC_NAME readlinkat -# define AT_FUNC_F1 readlink -# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t bufsize -# define AT_FUNC_POST_FILE_ARGS , buf, bufsize -# define AT_FUNC_RESULT ssize_t -# include "at-func.c" -# undef AT_FUNC_NAME -# undef AT_FUNC_F1 -# undef AT_FUNC_POST_FILE_PARAM_DECLS -# undef AT_FUNC_POST_FILE_ARGS -# undef AT_FUNC_RESULT - -#endif diff --git a/xcompile/lib/realloc.c b/xcompile/lib/realloc.c deleted file mode 100644 index 1063eb09874..00000000000 --- a/xcompile/lib/realloc.c +++ /dev/null @@ -1,63 +0,0 @@ -/* realloc() function that is glibc compatible. - - Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* written by Jim Meyering and Bruno Haible */ - -#include - -#include - -#include - -#include "xalloc-oversized.h" - -/* Call the system's realloc below. This file does not define - _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present. */ -#undef realloc - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. If P is NULL, use malloc. Otherwise if N is zero, - free P and return NULL. */ - -void * -rpl_realloc (void *p, size_t n) -{ - if (p == NULL) - return malloc (n); - - if (n == 0) - { - free (p); - return NULL; - } - - if (xalloc_oversized (n, 1)) - { - errno = ENOMEM; - return NULL; - } - - void *result = realloc (p, n); - -#if !HAVE_MALLOC_POSIX - if (result == NULL) - errno = ENOMEM; -#endif - - return result; -} diff --git a/xcompile/lib/regcomp.c b/xcompile/lib/regcomp.c deleted file mode 100644 index 89478396855..00000000000 --- a/xcompile/lib/regcomp.c +++ /dev/null @@ -1,3788 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifdef _LIBC -# include -#endif - -static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, - size_t length, reg_syntax_t syntax); -static void re_compile_fastmap_iter (regex_t *bufp, - const re_dfastate_t *init_state, - char *fastmap); -static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -static void free_charset (re_charset_t *cset); -static void free_workarea_compile (regex_t *preg); -static reg_errcode_t create_initial_state (re_dfa_t *dfa); -static void optimize_utf8 (re_dfa_t *dfa); -static reg_errcode_t analyze (regex_t *preg); -static reg_errcode_t preorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t postorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); -static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); -static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, - bin_tree_t *node); -static reg_errcode_t calc_first (void *extra, bin_tree_t *node); -static reg_errcode_t calc_next (void *extra, bin_tree_t *node); -static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); -static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); -static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint); -static reg_errcode_t calc_eclosure (re_dfa_t *dfa); -static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, - Idx node, bool root); -static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); -static Idx fetch_number (re_string_t *input, re_token_t *token, - reg_syntax_t syntax); -static int peek_token (re_token_t *token, re_string_t *input, - reg_syntax_t syntax); -static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, - re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, - reg_errcode_t *err); -static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token, int token_len, - re_dfa_t *dfa, - reg_syntax_t syntax, - bool accept_hyphen); -static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token); -static reg_errcode_t build_equiv_class (bitset_t sbcset, - re_charset_t *mbcset, - Idx *equiv_class_alloc, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *char_class_alloc, - const char *class_name, - reg_syntax_t syntax); -static bin_tree_t *build_charclass_op (re_dfa_t *dfa, - RE_TRANSLATE_TYPE trans, - const char *class_name, - const char *extra, - bool non_match, reg_errcode_t *err); -static bin_tree_t *create_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - re_token_type_t type); -static bin_tree_t *create_token_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - const re_token_t *token); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); -static void free_token (re_token_t *node); -static reg_errcode_t free_tree (void *extra, bin_tree_t *node); -static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char __re_error_msgid[] = - { -#define REG_NOERROR_IDX 0 - gettext_noop ("Success") /* REG_NOERROR */ - "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") - gettext_noop ("No match") /* REG_NOMATCH */ - "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") - gettext_noop ("Invalid regular expression") /* REG_BADPAT */ - "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") - gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ - "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") - gettext_noop ("Invalid character class name") /* REG_ECTYPE */ - "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") - gettext_noop ("Trailing backslash") /* REG_EESCAPE */ - "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") - gettext_noop ("Invalid back reference") /* REG_ESUBREG */ - "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") - gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */ - "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=") - gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ - "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") - gettext_noop ("Unmatched \\{") /* REG_EBRACE */ - "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") - gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ - "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") - gettext_noop ("Invalid range end") /* REG_ERANGE */ - "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") - gettext_noop ("Memory exhausted") /* REG_ESPACE */ - "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") - gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ - "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") - gettext_noop ("Premature end of regular expression") /* REG_EEND */ - "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") - gettext_noop ("Regular expression too big") /* REG_ESIZE */ - "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") - gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ - }; - -static const size_t __re_error_msgid_idx[] = - { - REG_NOERROR_IDX, - REG_NOMATCH_IDX, - REG_BADPAT_IDX, - REG_ECOLLATE_IDX, - REG_ECTYPE_IDX, - REG_EESCAPE_IDX, - REG_ESUBREG_IDX, - REG_EBRACK_IDX, - REG_EPAREN_IDX, - REG_EBRACE_IDX, - REG_BADBR_IDX, - REG_ERANGE_IDX, - REG_ESPACE_IDX, - REG_BADRPT_IDX, - REG_EEND_IDX, - REG_ESIZE_IDX, - REG_ERPAREN_IDX - }; - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length LENGTH) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields - are set in BUFP on entry. */ - -const char * -re_compile_pattern (const char *pattern, size_t length, - struct re_pattern_buffer *bufp) -{ - reg_errcode_t ret; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub, unless RE_NO_SUB is set. */ - bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = re_compile_internal (bufp, pattern, length, re_syntax_options); - - if (!ret) - return NULL; - return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} -weak_alias (__re_compile_pattern, re_compile_pattern) - -/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (reg_syntax_t syntax) -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} -weak_alias (__re_set_syntax, re_set_syntax) - -int -re_compile_fastmap (struct re_pattern_buffer *bufp) -{ - re_dfa_t *dfa = bufp->buffer; - char *fastmap = bufp->fastmap; - - memset (fastmap, '\0', sizeof (char) * SBC_MAX); - re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); - if (dfa->init_state != dfa->init_state_word) - re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); - if (dfa->init_state != dfa->init_state_nl) - re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); - if (dfa->init_state != dfa->init_state_begbuf) - re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); - bufp->fastmap_accurate = 1; - return 0; -} -weak_alias (__re_compile_fastmap, re_compile_fastmap) - -static __always_inline void -re_set_fastmap (char *fastmap, bool icase, int ch) -{ - fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; -} - -/* Helper function for re_compile_fastmap. - Compile fastmap for the initial_state INIT_STATE. */ - -static void -re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, - char *fastmap) -{ - re_dfa_t *dfa = bufp->buffer; - Idx node_cnt; - bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - Idx node = init_state->nodes.elems[node_cnt]; - re_token_type_t type = dfa->nodes[node].type; - - if (type == CHARACTER) - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - unsigned char buf[MB_LEN_MAX]; - unsigned char *p; - wchar_t wc; - mbstate_t state; - - p = buf; - *p++ = dfa->nodes[node].opr.c; - while (++node < dfa->nodes_len - && dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].mb_partial) - *p++ = dfa->nodes[node].opr.c; - memset (&state, '\0', sizeof (state)); - if (__mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, __towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, false, buf[0]); - } - } - else if (type == SIMPLE_BRACKET) - { - int i, ch; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - { - int j; - bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); - } - } - else if (type == COMPLEX_BRACKET) - { - re_charset_t *cset = dfa->nodes[node].opr.mbcset; - Idx i; - -#ifdef _LIBC - /* See if we have to try all bytes which start multiple collation - elements. - e.g. In da_DK, we want to catch 'a' since "aa" is a valid - collation element, and don't catch 'b' since 'b' is - the only collation element which starts from 'b' (and - it is caught by SIMPLE_BRACKET). */ - if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0 - && (cset->ncoll_syms || cset->nranges)) - { - const int32_t *table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - for (i = 0; i < SBC_MAX; ++i) - if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); - } -#endif /* _LIBC */ - - /* See if we have to start the match at all multibyte characters, - i.e. where we would not find an invalid sequence. This only - applies to multibyte character sets; for single byte character - sets, the SIMPLE_BRACKET again suffices. */ - if (dfa->mb_cur_max > 1 - && (cset->nchar_classes || cset->non_match || cset->nranges -#ifdef _LIBC - || cset->nequiv_classes -#endif /* _LIBC */ - )) - { - unsigned char c = 0; - do - { - mbstate_t mbs; - memset (&mbs, 0, sizeof (mbs)); - if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) - re_set_fastmap (fastmap, false, (int) c); - } - while (++c != 0); - } - - else - { - /* ... Else catch all bytes which can start the mbchars. */ - for (i = 0; i < cset->nmbchars; ++i) - { - char buf[256]; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, false, *(unsigned char *) buf); - } - } - } - } - else if (type == OP_PERIOD || type == OP_UTF8_PERIOD || type == END_OF_RE) - { - memset (fastmap, '\1', sizeof (char) * SBC_MAX); - if (type == END_OF_RE) - bufp->can_be_null = 1; - return; - } - } -} - -/* Entry point for POSIX code. */ -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - 'buffer' to the compiled pattern; - 'used' to the length of the compiled pattern; - 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - 'newline_anchor' to REG_NEWLINE being set in CFLAGS; - 'fastmap' to an allocated space for the fastmap; - 'fastmap_accurate' to zero; - 're_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags) -{ - reg_errcode_t ret; - reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC); - - preg->buffer = NULL; - preg->allocated = 0; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = re_malloc (char, SBC_MAX); - if (__glibc_unlikely (preg->fastmap == NULL)) - return REG_ESPACE; - - syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - preg->no_sub = !!(cflags & REG_NOSUB); - preg->translate = NULL; - - ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) - ret = REG_EPAREN; - - /* We have already checked preg->fastmap != NULL. */ - if (__glibc_likely (ret == REG_NOERROR)) - /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. This function never fails in this implementation. */ - (void) re_compile_fastmap (preg); - else - { - /* Some error occurred while compiling the expression. */ - re_free (preg->fastmap); - preg->fastmap = NULL; - } - - return (int) ret; -} -libc_hidden_def (__regcomp) -weak_alias (__regcomp, regcomp) - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -size_t -regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, - size_t errbuf_size) -{ - const char *msg; - size_t msg_size; - int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0]; - - if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (__glibc_likely (errbuf_size != 0)) - { - size_t cpy_size = msg_size; - if (__glibc_unlikely (msg_size > errbuf_size)) - { - cpy_size = errbuf_size - 1; - errbuf[cpy_size] = '\0'; - } - memcpy (errbuf, msg, cpy_size); - } - - return msg_size; -} -weak_alias (__regerror, regerror) - - -/* This static array is used for the map to single-byte characters when - UTF-8 is used. Otherwise we would allocate memory just to initialize - it the same all the time. UTF-8 is the preferred encoding so this is - a worthwhile optimization. */ -static const bitset_t utf8_sb_map = -{ - /* Set the first 128 bits. */ -#if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__ - [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX -#else -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, -# endif - (BITSET_WORD_MAX - >> (SBC_MAX % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) -#endif -}; - - -static void -free_dfa_content (re_dfa_t *dfa) -{ - Idx i, j; - - if (dfa->nodes) - for (i = 0; i < dfa->nodes_len; ++i) - free_token (dfa->nodes + i); - re_free (dfa->nexts); - for (i = 0; i < dfa->nodes_len; ++i) - { - if (dfa->eclosures != NULL) - re_node_set_free (dfa->eclosures + i); - if (dfa->inveclosures != NULL) - re_node_set_free (dfa->inveclosures + i); - if (dfa->edests != NULL) - re_node_set_free (dfa->edests + i); - } - re_free (dfa->edests); - re_free (dfa->eclosures); - re_free (dfa->inveclosures); - re_free (dfa->nodes); - - if (dfa->state_table) - for (i = 0; i <= dfa->state_hash_mask; ++i) - { - struct re_state_table_entry *entry = dfa->state_table + i; - for (j = 0; j < entry->num; ++j) - { - re_dfastate_t *state = entry->array[j]; - free_state (state); - } - re_free (entry->array); - } - re_free (dfa->state_table); - if (dfa->sb_char != utf8_sb_map) - re_free (dfa->sb_char); - re_free (dfa->subexp_map); -#ifdef DEBUG - re_free (dfa->re_str); -#endif - - re_free (dfa); -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (regex_t *preg) -{ - re_dfa_t *dfa = preg->buffer; - if (__glibc_likely (dfa != NULL)) - { - lock_fini (dfa->lock); - free_dfa_content (dfa); - } - preg->buffer = NULL; - preg->allocated = 0; - - re_free (preg->fastmap); - preg->fastmap = NULL; - - re_free (preg->translate); - preg->translate = NULL; -} -libc_hidden_def (__regfree) -weak_alias (__regfree, regfree) - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec above without link errors. */ -weak_function -# endif -re_comp (const char *s) -{ - reg_errcode_t ret; - char *fastmap; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (re_comp_buf.buffer) - { - fastmap = re_comp_buf.fastmap; - re_comp_buf.fastmap = NULL; - __regfree (&re_comp_buf); - memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); - re_comp_buf.fastmap = fastmap; - } - - if (re_comp_buf.fastmap == NULL) - { - re_comp_buf.fastmap = re_malloc (char, SBC_MAX); - if (re_comp_buf.fastmap == NULL) - return (char *) gettext (__re_error_msgid - + __re_error_msgid_idx[(int) REG_ESPACE]); - } - - /* Since 're_exec' always passes NULL for the 'regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); - - if (!ret) - return NULL; - - /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */ - return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} - -#ifdef _LIBC -libc_freeres_fn (free_mem) -{ - __regfree (&re_comp_buf); -} -#endif - -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. - Compile the regular expression PATTERN, whose length is LENGTH. - SYNTAX indicate regular expression's syntax. */ - -static reg_errcode_t -re_compile_internal (regex_t *preg, const char * pattern, size_t length, - reg_syntax_t syntax) -{ - reg_errcode_t err = REG_NOERROR; - re_dfa_t *dfa; - re_string_t regexp; - - /* Initialize the pattern buffer. */ - preg->fastmap_accurate = 0; - preg->syntax = syntax; - preg->not_bol = preg->not_eol = 0; - preg->used = 0; - preg->re_nsub = 0; - preg->can_be_null = 0; - preg->regs_allocated = REGS_UNALLOCATED; - - /* Initialize the dfa. */ - dfa = preg->buffer; - if (__glibc_unlikely (preg->allocated < sizeof (re_dfa_t))) - { - /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. If ->buffer is NULL this - is a simple allocation. */ - dfa = re_realloc (preg->buffer, re_dfa_t, 1); - if (dfa == NULL) - return REG_ESPACE; - preg->allocated = sizeof (re_dfa_t); - preg->buffer = dfa; - } - preg->used = sizeof (re_dfa_t); - - err = init_dfa (dfa, length); - if (__glibc_unlikely (err == REG_NOERROR && lock_init (dfa->lock) != 0)) - err = REG_ESPACE; - if (__glibc_unlikely (err != REG_NOERROR)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } -#ifdef DEBUG - /* Note: length+1 will not overflow since it is checked in init_dfa. */ - dfa->re_str = re_malloc (char, length + 1); - strncpy (dfa->re_str, pattern, length + 1); -#endif - - err = re_string_construct (®exp, pattern, length, preg->translate, - (syntax & RE_ICASE) != 0, dfa); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_compile_internal_free_return: - free_workarea_compile (preg); - re_string_destruct (®exp); - lock_fini (dfa->lock); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } - - /* Parse the regular expression, and build a structure tree. */ - preg->re_nsub = 0; - dfa->str_tree = parse (®exp, preg, syntax, &err); - if (__glibc_unlikely (dfa->str_tree == NULL)) - goto re_compile_internal_free_return; - - /* Analyze the tree and create the nfa. */ - err = analyze (preg); - if (__glibc_unlikely (err != REG_NOERROR)) - goto re_compile_internal_free_return; - - /* If possible, do searching in single byte encoding to speed things up. */ - if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) - optimize_utf8 (dfa); - - /* Then create the initial state of the dfa. */ - err = create_initial_state (dfa); - - /* Release work areas. */ - free_workarea_compile (preg); - re_string_destruct (®exp); - - if (__glibc_unlikely (err != REG_NOERROR)) - { - lock_fini (dfa->lock); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - } - - return err; -} - -/* Initialize DFA. We use the length of the regular expression PAT_LEN - as the initial length of some arrays. */ - -static reg_errcode_t -init_dfa (re_dfa_t *dfa, size_t pat_len) -{ - __re_size_t table_size; -#ifndef _LIBC - const char *codeset_name; -#endif - size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); - size_t max_object_size = - MAX (sizeof (struct re_state_table_entry), - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - MAX (sizeof (regmatch_t), - max_i18n_object_size)))); - - memset (dfa, '\0', sizeof (re_dfa_t)); - - /* Force allocation of str_tree_storage the first time. */ - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - - /* Avoid overflows. The extra "/ 2" is for the table_size doubling - calculation below, and for similar doubling calculations - elsewhere. And it's <= rather than <, because some of the - doubling calculations add 1 afterwards. */ - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2 - <= pat_len)) - return REG_ESPACE; - - dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); - - /* table_size = 2 ^ ceil(log pat_len) */ - for (table_size = 1; ; table_size <<= 1) - if (table_size > pat_len) - break; - - dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); - dfa->state_hash_mask = table_size - 1; - - dfa->mb_cur_max = MB_CUR_MAX; -#ifdef _LIBC - if (dfa->mb_cur_max == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -#else - codeset_name = nl_langinfo (CODESET); - if ((codeset_name[0] == 'U' || codeset_name[0] == 'u') - && (codeset_name[1] == 'T' || codeset_name[1] == 't') - && (codeset_name[2] == 'F' || codeset_name[2] == 'f') - && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0) - dfa->is_utf8 = 1; - - /* We check exhaustively in the loop below if this charset is a - superset of ASCII. */ - dfa->map_notascii = 0; -#endif - - if (dfa->mb_cur_max > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; - else - { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (__glibc_unlikely (dfa->sb_char == NULL)) - return REG_ESPACE; - - /* Set the bits corresponding to single byte chars. */ - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - { - wint_t wch = __btowc (ch); - if (wch != WEOF) - dfa->sb_char[i] |= (bitset_word_t) 1 << j; -#ifndef _LIBC - if (isascii (ch) && wch != ch) - dfa->map_notascii = 1; -#endif - } - } - } - - if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL)) - return REG_ESPACE; - return REG_NOERROR; -} - -/* Initialize WORD_CHAR table, which indicate which character is - "word". In this case "word" means that it is the word construction - character used by some operators like "\<", "\>", etc. */ - -static void -init_word_char (re_dfa_t *dfa) -{ - int i = 0; - int j; - int ch = 0; - dfa->word_ops_used = 1; - if (__glibc_likely (dfa->map_notascii == 0)) - { - bitset_word_t bits0 = 0x00000000; - bitset_word_t bits1 = 0x03ff0000; - bitset_word_t bits2 = 0x87fffffe; - bitset_word_t bits3 = 0x07fffffe; - if (BITSET_WORD_BITS == 64) - { - /* Pacify gcc -Woverflow on 32-bit platformns. */ - dfa->word_char[0] = bits1 << 31 << 1 | bits0; - dfa->word_char[1] = bits3 << 31 << 1 | bits2; - i = 2; - } - else if (BITSET_WORD_BITS == 32) - { - dfa->word_char[0] = bits0; - dfa->word_char[1] = bits1; - dfa->word_char[2] = bits2; - dfa->word_char[3] = bits3; - i = 4; - } - else - goto general_case; - ch = 128; - - if (__glibc_likely (dfa->is_utf8)) - { - memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8); - return; - } - } - - general_case: - for (; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (isalnum (ch) || ch == '_') - dfa->word_char[i] |= (bitset_word_t) 1 << j; -} - -/* Free the work area which are only used while compiling. */ - -static void -free_workarea_compile (regex_t *preg) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_storage_t *storage, *next; - for (storage = dfa->str_tree_storage; storage; storage = next) - { - next = storage->next; - re_free (storage); - } - dfa->str_tree_storage = NULL; - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - dfa->str_tree = NULL; - re_free (dfa->org_indices); - dfa->org_indices = NULL; -} - -/* Create initial states for all contexts. */ - -static reg_errcode_t -create_initial_state (re_dfa_t *dfa) -{ - Idx first, i; - reg_errcode_t err; - re_node_set init_nodes; - - /* Initial states have the epsilon closure of the node which is - the first node of the regular expression. */ - first = dfa->str_tree->first->node_idx; - dfa->init_node = first; - err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - /* The back-references which are in initial states can epsilon transit, - since in this case all of the subexpressions can be null. - Then we add epsilon closures of the nodes which are the next nodes of - the back-references. */ - if (dfa->nbackref > 0) - for (i = 0; i < init_nodes.nelem; ++i) - { - Idx node_idx = init_nodes.elems[i]; - re_token_type_t type = dfa->nodes[node_idx].type; - - Idx clexp_idx; - if (type != OP_BACK_REF) - continue; - for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) - { - re_token_t *clexp_node; - clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; - if (clexp_node->type == OP_CLOSE_SUBEXP - && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) - break; - } - if (clexp_idx == init_nodes.nelem) - continue; - - if (type == OP_BACK_REF) - { - Idx dest_idx = dfa->edests[node_idx].elems[0]; - if (!re_node_set_contains (&init_nodes, dest_idx)) - { - reg_errcode_t merge_err - = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - if (merge_err != REG_NOERROR) - return merge_err; - i = 0; - } - } - } - - /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ - if (__glibc_unlikely (dfa->init_state == NULL)) - return err; - if (dfa->init_state->has_constraint) - { - dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_WORD); - dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_NEWLINE); - dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, - &init_nodes, - CONTEXT_NEWLINE - | CONTEXT_BEGBUF); - if (__glibc_unlikely (dfa->init_state_word == NULL - || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL)) - return err; - } - else - dfa->init_state_word = dfa->init_state_nl - = dfa->init_state_begbuf = dfa->init_state; - - re_node_set_free (&init_nodes); - return REG_NOERROR; -} - -/* If it is possible to do searching in single byte encoding instead of UTF-8 - to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change - DFA nodes where needed. */ - -static void -optimize_utf8 (re_dfa_t *dfa) -{ - Idx node; - int i; - bool mb_chars = false; - bool has_period = false; - - for (node = 0; node < dfa->nodes_len; ++node) - switch (dfa->nodes[node].type) - { - case CHARACTER: - if (dfa->nodes[node].opr.c >= ASCII_CHARS) - mb_chars = true; - break; - case ANCHOR: - switch (dfa->nodes[node].opr.ctx_type) - { - case LINE_FIRST: - case LINE_LAST: - case BUF_FIRST: - case BUF_LAST: - break; - default: - /* Word anchors etc. cannot be handled. It's okay to test - opr.ctx_type since constraints (for all DFA nodes) are - created by ORing one or more opr.ctx_type values. */ - return; - } - break; - case OP_PERIOD: - has_period = true; - break; - case OP_BACK_REF: - case OP_ALT: - case END_OF_RE: - case OP_DUP_ASTERISK: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - break; - case COMPLEX_BRACKET: - return; - case SIMPLE_BRACKET: - /* Just double check. */ - { - int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); - for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) - { - if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) - return; - rshift = 0; - } - } - break; - default: - abort (); - } - - if (mb_chars || has_period) - for (node = 0; node < dfa->nodes_len; ++node) - { - if (dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].opr.c >= ASCII_CHARS) - dfa->nodes[node].mb_partial = 0; - else if (dfa->nodes[node].type == OP_PERIOD) - dfa->nodes[node].type = OP_UTF8_PERIOD; - } - - /* The search can be in single byte locale. */ - dfa->mb_cur_max = 1; - dfa->is_utf8 = 0; - dfa->has_mb_node = dfa->nbackref > 0 || has_period; -} - -/* Analyze the structure tree, and calculate "first", "next", "edest", - "eclosure", and "inveclosure". */ - -static reg_errcode_t -analyze (regex_t *preg) -{ - re_dfa_t *dfa = preg->buffer; - reg_errcode_t ret; - - /* Allocate arrays. */ - dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); - dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); - dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); - if (__glibc_unlikely (dfa->nexts == NULL || dfa->org_indices == NULL - || dfa->edests == NULL || dfa->eclosures == NULL)) - return REG_ESPACE; - - dfa->subexp_map = re_malloc (Idx, preg->re_nsub); - if (dfa->subexp_map != NULL) - { - Idx i; - for (i = 0; i < preg->re_nsub; i++) - dfa->subexp_map[i] = i; - preorder (dfa->str_tree, optimize_subexps, dfa); - for (i = 0; i < preg->re_nsub; i++) - if (dfa->subexp_map[i] != i) - break; - if (i == preg->re_nsub) - { - re_free (dfa->subexp_map); - dfa->subexp_map = NULL; - } - } - - ret = postorder (dfa->str_tree, lower_subexps, preg); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - ret = postorder (dfa->str_tree, calc_first, dfa); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - preorder (dfa->str_tree, calc_next, dfa); - ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - ret = calc_eclosure (dfa); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - - /* We only need this during the prune_impossible_nodes pass in regexec.c; - skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ - if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) - || dfa->nbackref) - { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); - if (__glibc_unlikely (dfa->inveclosures == NULL)) - return REG_ESPACE; - ret = calc_inveclosure (dfa); - } - - return ret; -} - -/* Our parse trees are very unbalanced, so we cannot use a stack to - implement parse tree visits. Instead, we use parent pointers and - some hairy code in these two functions. */ -static reg_errcode_t -postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node, *prev; - - for (node = root; ; ) - { - /* Descend down the tree, preferably to the left (or to the right - if that's the only child). */ - while (node->left || node->right) - if (node->left) - node = node->left; - else - node = node->right; - - do - { - reg_errcode_t err = fn (extra, node); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - if (node->parent == NULL) - return REG_NOERROR; - prev = node; - node = node->parent; - } - /* Go up while we have a node that is reached from the right. */ - while (node->right == prev || node->right == NULL); - node = node->right; - } -} - -static reg_errcode_t -preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node; - - for (node = root; ; ) - { - reg_errcode_t err = fn (extra, node); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - /* Go to the left node, or up and to the right. */ - if (node->left) - node = node->left; - else - { - bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - if (!node) - return REG_NOERROR; - } - node = node->right; - } - } -} - -/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell - re_search_internal to map the inner one's opr.idx to this one's. Adjust - backreferences as well. Requires a preorder visit. */ -static reg_errcode_t -optimize_subexps (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - - if (node->token.type == OP_BACK_REF && dfa->subexp_map) - { - int idx = node->token.opr.idx; - node->token.opr.idx = dfa->subexp_map[idx]; - dfa->used_bkref_map |= 1 << node->token.opr.idx; - } - - else if (node->token.type == SUBEXP - && node->left && node->left->token.type == SUBEXP) - { - Idx other_idx = node->left->token.opr.idx; - - node->left = node->left->left; - if (node->left) - node->left->parent = node; - - dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; - if (other_idx < BITSET_WORD_BITS) - dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); - } - - return REG_NOERROR; -} - -/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation - of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ -static reg_errcode_t -lower_subexps (void *extra, bin_tree_t *node) -{ - regex_t *preg = (regex_t *) extra; - reg_errcode_t err = REG_NOERROR; - - if (node->left && node->left->token.type == SUBEXP) - { - node->left = lower_subexp (&err, preg, node->left); - if (node->left) - node->left->parent = node; - } - if (node->right && node->right->token.type == SUBEXP) - { - node->right = lower_subexp (&err, preg, node->right); - if (node->right) - node->right->parent = node; - } - - return err; -} - -static bin_tree_t * -lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_t *body = node->left; - bin_tree_t *op, *cls, *tree1, *tree; - - if (preg->no_sub - /* We do not optimize empty subexpressions, because otherwise we may - have bad CONCAT nodes with NULL children. This is obviously not - very common, so we do not lose much. An example that triggers - this case is the sed "script" /\(\)/x. */ - && node->left != NULL - && (node->token.opr.idx >= BITSET_WORD_BITS - || !(dfa->used_bkref_map - & ((bitset_word_t) 1 << node->token.opr.idx)))) - return node->left; - - /* Convert the SUBEXP node to the concatenation of an - OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ - op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); - cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); - tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; - tree = create_tree (dfa, op, tree1, CONCAT); - if (__glibc_unlikely (tree == NULL || tree1 == NULL - || op == NULL || cls == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - - op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; - op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; - return tree; -} - -/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton - nodes. Requires a postorder visit. */ -static reg_errcode_t -calc_first (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - if (node->token.type == CONCAT) - { - node->first = node->left->first; - node->node_idx = node->left->node_idx; - } - else - { - node->first = node; - node->node_idx = re_dfa_add_node (dfa, node->token); - if (__glibc_unlikely (node->node_idx == -1)) - return REG_ESPACE; - if (node->token.type == ANCHOR) - dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; - } - return REG_NOERROR; -} - -/* Pass 2: compute NEXT on the tree. Preorder visit. */ -static reg_errcode_t -calc_next (void *extra, bin_tree_t *node) -{ - switch (node->token.type) - { - case OP_DUP_ASTERISK: - node->left->next = node; - break; - case CONCAT: - node->left->next = node->right->first; - node->right->next = node->next; - break; - default: - if (node->left) - node->left->next = node->next; - if (node->right) - node->right->next = node->next; - break; - } - return REG_NOERROR; -} - -/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ -static reg_errcode_t -link_nfa_nodes (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - Idx idx = node->node_idx; - reg_errcode_t err = REG_NOERROR; - - switch (node->token.type) - { - case CONCAT: - break; - - case END_OF_RE: - DEBUG_ASSERT (node->next == NULL); - break; - - case OP_DUP_ASTERISK: - case OP_ALT: - { - Idx left, right; - dfa->has_plural_match = 1; - if (node->left != NULL) - left = node->left->first->node_idx; - else - left = node->next->node_idx; - if (node->right != NULL) - right = node->right->first->node_idx; - else - right = node->next->node_idx; - DEBUG_ASSERT (left > -1); - DEBUG_ASSERT (right > -1); - err = re_node_set_init_2 (dfa->edests + idx, left, right); - } - break; - - case ANCHOR: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); - break; - - case OP_BACK_REF: - dfa->nexts[idx] = node->next->node_idx; - if (node->token.type == OP_BACK_REF) - err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); - break; - - default: - DEBUG_ASSERT (!IS_EPSILON_NODE (node->token.type)); - dfa->nexts[idx] = node->next->node_idx; - break; - } - - return err; -} - -/* Duplicate the epsilon closure of the node ROOT_NODE. - Note that duplicated nodes have constraint INIT_CONSTRAINT in addition - to their own constraint. */ - -static reg_errcode_t -duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, - Idx root_node, unsigned int init_constraint) -{ - Idx org_node, clone_node; - bool ok; - unsigned int constraint = init_constraint; - for (org_node = top_org_node, clone_node = top_clone_node;;) - { - Idx org_dest, clone_dest; - if (dfa->nodes[org_node].type == OP_BACK_REF) - { - /* If the back reference epsilon-transit, its destination must - also have the constraint. Then duplicate the epsilon closure - of the destination of the back reference, and store it in - edests of the back reference. */ - org_dest = dfa->nexts[org_node]; - re_node_set_empty (dfa->edests + clone_node); - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (__glibc_unlikely (clone_dest == -1)) - return REG_ESPACE; - dfa->nexts[clone_node] = dfa->nexts[org_node]; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - else if (dfa->edests[org_node].nelem == 0) - { - /* In case of the node can't epsilon-transit, don't duplicate the - destination and store the original destination as the - destination of the node. */ - dfa->nexts[clone_node] = dfa->nexts[org_node]; - break; - } - else if (dfa->edests[org_node].nelem == 1) - { - /* In case of the node can epsilon-transit, and it has only one - destination. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* If the node is root_node itself, it means the epsilon closure - has a loop. Then tie it to the destination of the root_node. */ - if (org_node == root_node && clone_node != org_node) - { - ok = re_node_set_insert (dfa->edests + clone_node, org_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - break; - } - /* In case the node has another constraint, append it. */ - constraint |= dfa->nodes[org_node].constraint; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (__glibc_unlikely (clone_dest == -1)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - else /* dfa->edests[org_node].nelem == 2 */ - { - /* In case of the node can epsilon-transit, and it has two - destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* Search for a duplicated node which satisfies the constraint. */ - clone_dest = search_duplicated_node (dfa, org_dest, constraint); - if (clone_dest == -1) - { - /* There is no such duplicated node, create a new one. */ - reg_errcode_t err; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (__glibc_unlikely (clone_dest == -1)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - err = duplicate_node_closure (dfa, org_dest, clone_dest, - root_node, constraint); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - else - { - /* There is a duplicated node which satisfies the constraint, - use it to avoid infinite loop. */ - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - - org_dest = dfa->edests[org_node].elems[1]; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (__glibc_unlikely (clone_dest == -1)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - org_node = org_dest; - clone_node = clone_dest; - } - return REG_NOERROR; -} - -/* Search for a node which is duplicated from the node ORG_NODE, and - satisfies the constraint CONSTRAINT. */ - -static Idx -search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint) -{ - Idx idx; - for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) - { - if (org_node == dfa->org_indices[idx] - && constraint == dfa->nodes[idx].constraint) - return idx; /* Found. */ - } - return -1; /* Not found. */ -} - -/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. - Return the index of the new node, or -1 if insufficient storage is - available. */ - -static Idx -duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) -{ - Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); - if (__glibc_likely (dup_idx != -1)) - { - dfa->nodes[dup_idx].constraint = constraint; - dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint; - dfa->nodes[dup_idx].duplicated = 1; - - /* Store the index of the original node. */ - dfa->org_indices[dup_idx] = org_idx; - } - return dup_idx; -} - -static reg_errcode_t -calc_inveclosure (re_dfa_t *dfa) -{ - Idx src, idx; - bool ok; - for (idx = 0; idx < dfa->nodes_len; ++idx) - re_node_set_init_empty (dfa->inveclosures + idx); - - for (src = 0; src < dfa->nodes_len; ++src) - { - Idx *elems = dfa->eclosures[src].elems; - for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) - { - ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - } - - return REG_NOERROR; -} - -/* Calculate "eclosure" for all the node in DFA. */ - -static reg_errcode_t -calc_eclosure (re_dfa_t *dfa) -{ - Idx node_idx; - bool incomplete; - DEBUG_ASSERT (dfa->nodes_len > 0); - incomplete = false; - /* For each nodes, calculate epsilon closure. */ - for (node_idx = 0; ; ++node_idx) - { - reg_errcode_t err; - re_node_set eclosure_elem; - if (node_idx == dfa->nodes_len) - { - if (!incomplete) - break; - incomplete = false; - node_idx = 0; - } - - DEBUG_ASSERT (dfa->eclosures[node_idx].nelem != -1); - - /* If we have already calculated, skip it. */ - if (dfa->eclosures[node_idx].nelem != 0) - continue; - /* Calculate epsilon closure of 'node_idx'. */ - err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - if (dfa->eclosures[node_idx].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - return REG_NOERROR; -} - -/* Calculate epsilon closure of NODE. */ - -static reg_errcode_t -calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) -{ - reg_errcode_t err; - Idx i; - re_node_set eclosure; - bool incomplete = false; - err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - /* An epsilon closure includes itself. */ - eclosure.elems[eclosure.nelem++] = node; - - /* This indicates that we are calculating this node now. - We reference this value to avoid infinite loop. */ - dfa->eclosures[node].nelem = -1; - - /* If the current node has constraints, duplicate all nodes - since they must inherit the constraints. */ - if (dfa->nodes[node].constraint - && dfa->edests[node].nelem - && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) - { - err = duplicate_node_closure (dfa, node, node, node, - dfa->nodes[node].constraint); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - - /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) - for (i = 0; i < dfa->edests[node].nelem; ++i) - { - re_node_set eclosure_elem; - Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of 'edest' is in progress, - return intermediate result. */ - if (dfa->eclosures[edest].nelem == -1) - { - incomplete = true; - continue; - } - /* If we haven't calculated the epsilon closure of 'edest' yet, - calculate now. Otherwise use calculated epsilon closure. */ - if (dfa->eclosures[edest].nelem == 0) - { - err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - else - eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of 'edest'. */ - err = re_node_set_merge (&eclosure, &eclosure_elem); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - /* If the epsilon closure of 'edest' is incomplete, - the epsilon closure of this node is also incomplete. */ - if (dfa->eclosures[edest].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; - else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; -} - -/* Functions for token which are used in the parser. */ - -/* Fetch a token from INPUT. - We must not use this function inside bracket expressions. */ - -static void -fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) -{ - re_string_skip_bytes (input, peek_token (result, input, syntax)); -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function inside bracket expressions. */ - -static int -peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - token->word_char = 0; - token->mb_partial = 0; - if (input->mb_cur_max > 1 - && !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - token->mb_partial = 1; - return 1; - } - if (c == '\\') - { - unsigned char c2; - if (re_string_cur_idx (input) + 1 >= re_string_length (input)) - { - token->type = BACK_SLASH; - return 1; - } - - c2 = re_string_peek_byte_case (input, 1); - token->opr.c = c2; - token->type = CHARACTER; - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else - token->word_char = IS_WORD_CHAR (c2) != 0; - - switch (c2) - { - case '|': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (!(syntax & RE_NO_BK_REFS)) - { - token->type = OP_BACK_REF; - token->opr.idx = c2 - '1'; - } - break; - case '<': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_FIRST; - } - break; - case '>': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_LAST; - } - break; - case 'b': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_DELIM; - } - break; - case 'B': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = NOT_WORD_DELIM; - } - break; - case 'w': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_WORD; - break; - case 'W': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTWORD; - break; - case 's': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_SPACE; - break; - case 'S': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTSPACE; - break; - case '`': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_FIRST; - } - break; - case '\'': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_LAST; - } - break; - case '(': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_CLOSE_SUBEXP; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_CLOSE_DUP_NUM; - break; - default: - break; - } - return 2; - } - - token->type = CHARACTER; - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else - token->word_char = IS_WORD_CHAR (token->opr.c); - - switch (c) - { - case '\n': - if (syntax & RE_NEWLINE_ALT) - token->type = OP_ALT; - break; - case '|': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '*': - token->type = OP_DUP_ASTERISK; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_CLOSE_DUP_NUM; - break; - case '(': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_CLOSE_SUBEXP; - break; - case '[': - token->type = OP_OPEN_BRACKET; - break; - case '.': - token->type = OP_PERIOD; - break; - case '^': - if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) - && re_string_cur_idx (input) != 0) - { - char prev = re_string_peek_byte (input, -1); - if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_FIRST; - break; - case '$': - if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) - && re_string_cur_idx (input) + 1 != re_string_length (input)) - { - re_token_t next; - re_string_skip_bytes (input, 1); - peek_token (&next, input, syntax); - re_string_skip_bytes (input, -1); - if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_LAST; - break; - default: - break; - } - return 1; -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function out of bracket expressions. */ - -static int -peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - if (input->mb_cur_max > 1 - && !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - return 1; - } - - if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) - && re_string_cur_idx (input) + 1 < re_string_length (input)) - { - /* In this case, '\' escape a character. */ - unsigned char c2; - re_string_skip_bytes (input, 1); - c2 = re_string_peek_byte (input, 0); - token->opr.c = c2; - token->type = CHARACTER; - return 1; - } - if (c == '[') /* '[' is a special char in a bracket exps. */ - { - unsigned char c2; - int token_len; - if (re_string_cur_idx (input) + 1 < re_string_length (input)) - c2 = re_string_peek_byte (input, 1); - else - c2 = 0; - token->opr.c = c2; - token_len = 2; - switch (c2) - { - case '.': - token->type = OP_OPEN_COLL_ELEM; - break; - - case '=': - token->type = OP_OPEN_EQUIV_CLASS; - break; - - case ':': - if (syntax & RE_CHAR_CLASSES) - { - token->type = OP_OPEN_CHAR_CLASS; - break; - } - FALLTHROUGH; - default: - token->type = CHARACTER; - token->opr.c = c; - token_len = 1; - break; - } - return token_len; - } - switch (c) - { - case ']': - token->type = OP_CLOSE_BRACKET; - break; - case '^': - token->type = OP_NON_MATCH_LIST; - break; - case '-': - /* In V7 Unix grep and Unix awk and mawk, [...---...] - (3 adjacent minus signs) stands for a single minus sign. - Support that without breaking anything else. */ - if (! (re_string_cur_idx (input) + 2 < re_string_length (input) - && re_string_peek_byte (input, 1) == '-' - && re_string_peek_byte (input, 2) == '-')) - { - token->type = OP_CHARSET_RANGE; - break; - } - re_string_skip_bytes (input, 2); - FALLTHROUGH; - default: - token->type = CHARACTER; - } - return 1; -} - -/* Functions for parser. */ - -/* Entry point of the parser. - Parse the regular expression REGEXP and return the structure tree. - If an error occurs, ERR is set by error code, and return NULL. - This function build the following tree, from regular expression : - CAT - / \ - / \ - EOR - - CAT means concatenation. - EOR means end of regular expression. */ - -static bin_tree_t * -parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, - reg_errcode_t *err) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_t *tree, *eor, *root; - re_token_t current_token; - dfa->syntax = syntax; - fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (__glibc_unlikely (eor == NULL || root == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - return root; -} - -/* This function build the following tree, from regular expression - |: - ALT - / \ - / \ - - - ALT means alternative, which represents the operator '|'. */ - -static bin_tree_t * -parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_t *tree, *branch = NULL; - bitset_word_t initial_bkref_map = dfa->completed_bkref_map; - tree = parse_branch (regexp, preg, token, syntax, nest, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - - while (token->type == OP_ALT) - { - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - if (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map; - dfa->completed_bkref_map = initial_bkref_map; - branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (__glibc_unlikely (*err != REG_NOERROR && branch == NULL)) - { - if (tree != NULL) - postorder (tree, free_tree, NULL); - return NULL; - } - dfa->completed_bkref_map |= accumulated_bkref_map; - } - else - branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - } - return tree; -} - -/* This function build the following tree, from regular expression - : - CAT - / \ - / \ - - - CAT means concatenation. */ - -static bin_tree_t * -parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - bin_tree_t *tree, *expr; - re_dfa_t *dfa = preg->buffer; - tree = parse_expression (regexp, preg, token, syntax, nest, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - - while (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - expr = parse_expression (regexp, preg, token, syntax, nest, err); - if (__glibc_unlikely (*err != REG_NOERROR && expr == NULL)) - { - if (tree != NULL) - postorder (tree, free_tree, NULL); - return NULL; - } - if (tree != NULL && expr != NULL) - { - bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT); - if (newtree == NULL) - { - postorder (expr, free_tree, NULL); - postorder (tree, free_tree, NULL); - *err = REG_ESPACE; - return NULL; - } - tree = newtree; - } - else if (tree == NULL) - tree = expr; - /* Otherwise expr == NULL, we don't need to create new tree. */ - } - return tree; -} - -/* This function build the following tree, from regular expression a*: - * - | - a -*/ - -static bin_tree_t * -parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_t *tree; - switch (token->type) - { - case CHARACTER: - tree = create_token_tree (dfa, NULL, NULL, token); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) - { - bin_tree_t *mbc_remain; - fetch_token (token, regexp, syntax); - mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (__glibc_unlikely (mbc_remain == NULL || tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - } - } - break; - - case OP_OPEN_SUBEXP: - tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - break; - - case OP_OPEN_BRACKET: - tree = parse_bracket_exp (regexp, dfa, token, syntax, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - break; - - case OP_BACK_REF: - if (!__glibc_likely (dfa->completed_bkref_map & (1 << token->opr.idx))) - { - *err = REG_ESUBREG; - return NULL; - } - dfa->used_bkref_map |= 1 << token->opr.idx; - tree = create_token_tree (dfa, NULL, NULL, token); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - ++dfa->nbackref; - dfa->has_mb_node = 1; - break; - - case OP_OPEN_DUP_NUM: - if (syntax & RE_CONTEXT_INVALID_DUP) - { - *err = REG_BADRPT; - return NULL; - } - FALLTHROUGH; - case OP_DUP_ASTERISK: - case OP_DUP_PLUS: - case OP_DUP_QUESTION: - if (syntax & RE_CONTEXT_INVALID_OPS) - { - *err = REG_BADRPT; - return NULL; - } - else if (syntax & RE_CONTEXT_INDEP_OPS) - { - fetch_token (token, regexp, syntax); - return parse_expression (regexp, preg, token, syntax, nest, err); - } - FALLTHROUGH; - case OP_CLOSE_SUBEXP: - if ((token->type == OP_CLOSE_SUBEXP) - && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) - { - *err = REG_ERPAREN; - return NULL; - } - FALLTHROUGH; - case OP_CLOSE_DUP_NUM: - /* We treat it as a normal character. */ - - /* Then we can these characters as normal characters. */ - token->type = CHARACTER; - /* mb_partial and word_char bits should be initialized already - by peek_token. */ - tree = create_token_tree (dfa, NULL, NULL, token); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - break; - - case ANCHOR: - if ((token->opr.ctx_type - & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) - && dfa->word_ops_used == 0) - init_word_char (dfa); - if (token->opr.ctx_type == WORD_DELIM - || token->opr.ctx_type == NOT_WORD_DELIM) - { - bin_tree_t *tree_first, *tree_last; - if (token->opr.ctx_type == WORD_DELIM) - { - token->opr.ctx_type = WORD_FIRST; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = WORD_LAST; - } - else - { - token->opr.ctx_type = INSIDE_WORD; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = INSIDE_NOTWORD; - } - tree_last = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (__glibc_unlikely (tree_first == NULL || tree_last == NULL - || tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - } - else - { - tree = create_token_tree (dfa, NULL, NULL, token); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - } - /* We must return here, since ANCHORs can't be followed - by repetition operators. - eg. RE"^*" is invalid or "", - it must not be "". */ - fetch_token (token, regexp, syntax); - return tree; - - case OP_PERIOD: - tree = create_token_tree (dfa, NULL, NULL, token); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - dfa->has_mb_node = 1; - break; - - case OP_WORD: - case OP_NOTWORD: - tree = build_charclass_op (dfa, regexp->trans, - "alnum", - "_", - token->type == OP_NOTWORD, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - break; - - case OP_SPACE: - case OP_NOTSPACE: - tree = build_charclass_op (dfa, regexp->trans, - "space", - "", - token->type == OP_NOTSPACE, err); - if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL)) - return NULL; - break; - - case OP_ALT: - case END_OF_RE: - return NULL; - - case BACK_SLASH: - *err = REG_EESCAPE; - return NULL; - - default: - /* Must not happen? */ - DEBUG_ASSERT (false); - return NULL; - } - fetch_token (token, regexp, syntax); - - while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS - || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) - { - bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token, - syntax, err); - if (__glibc_unlikely (*err != REG_NOERROR && dup_tree == NULL)) - { - if (tree != NULL) - postorder (tree, free_tree, NULL); - return NULL; - } - tree = dup_tree; - /* In BRE consecutive duplications are not allowed. */ - if ((syntax & RE_CONTEXT_INVALID_DUP) - && (token->type == OP_DUP_ASTERISK - || token->type == OP_OPEN_DUP_NUM)) - { - if (tree != NULL) - postorder (tree, free_tree, NULL); - *err = REG_BADRPT; - return NULL; - } - } - - return tree; -} - -/* This function build the following tree, from regular expression - (): - SUBEXP - | - -*/ - -static bin_tree_t * -parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = preg->buffer; - bin_tree_t *tree; - size_t cur_nsub; - cur_nsub = preg->re_nsub++; - - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - - /* The subexpression may be a null string. */ - if (token->type == OP_CLOSE_SUBEXP) - tree = NULL; - else - { - tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); - if (__glibc_unlikely (*err == REG_NOERROR - && token->type != OP_CLOSE_SUBEXP)) - { - if (tree != NULL) - postorder (tree, free_tree, NULL); - *err = REG_EPAREN; - } - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - } - - if (cur_nsub <= '9' - '1') - dfa->completed_bkref_map |= 1 << cur_nsub; - - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (__glibc_unlikely (tree == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - tree->token.opr.idx = cur_nsub; - return tree; -} - -/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ - -static bin_tree_t * -parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) -{ - bin_tree_t *tree = NULL, *old_tree = NULL; - Idx i, start, end, start_idx = re_string_cur_idx (regexp); - re_token_t start_token = *token; - - if (token->type == OP_OPEN_DUP_NUM) - { - end = 0; - start = fetch_number (regexp, token, syntax); - if (start == -1) - { - if (token->type == CHARACTER && token->opr.c == ',') - start = 0; /* We treat "{,m}" as "{0,m}". */ - else - { - *err = REG_BADBR; /* {} is invalid. */ - return NULL; - } - } - if (__glibc_likely (start != -2)) - { - /* We treat "{n}" as "{n,n}". */ - end = ((token->type == OP_CLOSE_DUP_NUM) ? start - : ((token->type == CHARACTER && token->opr.c == ',') - ? fetch_number (regexp, token, syntax) : -2)); - } - if (__glibc_unlikely (start == -2 || end == -2)) - { - /* Invalid sequence. */ - if (__glibc_unlikely (!(syntax & RE_INVALID_INTERVAL_ORD))) - { - if (token->type == END_OF_RE) - *err = REG_EBRACE; - else - *err = REG_BADBR; - - return NULL; - } - - /* If the syntax bit is set, rollback. */ - re_string_set_index (regexp, start_idx); - *token = start_token; - token->type = CHARACTER; - /* mb_partial and word_char bits should be already initialized by - peek_token. */ - return elem; - } - - if (__glibc_unlikely ((end != -1 && start > end) - || token->type != OP_CLOSE_DUP_NUM)) - { - /* First number greater than second. */ - *err = REG_BADBR; - return NULL; - } - - if (__glibc_unlikely (RE_DUP_MAX < (end == -1 ? start : end))) - { - *err = REG_ESIZE; - return NULL; - } - } - else - { - start = (token->type == OP_DUP_PLUS) ? 1 : 0; - end = (token->type == OP_DUP_QUESTION) ? 1 : -1; - } - - fetch_token (token, regexp, syntax); - - if (__glibc_unlikely (elem == NULL)) - return NULL; - if (__glibc_unlikely (start == 0 && end == 0)) - { - postorder (elem, free_tree, NULL); - return NULL; - } - - /* Extract "{n,m}" to "...{0,}". */ - if (__glibc_unlikely (start > 0)) - { - tree = elem; - for (i = 2; i <= start; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (__glibc_unlikely (elem == NULL || tree == NULL)) - goto parse_dup_op_espace; - } - - if (start == end) - return tree; - - /* Duplicate ELEM before it is marked optional. */ - elem = duplicate_tree (elem, dfa); - if (__glibc_unlikely (elem == NULL)) - goto parse_dup_op_espace; - old_tree = tree; - } - else - old_tree = NULL; - - if (elem->token.type == SUBEXP) - { - uintptr_t subidx = elem->token.opr.idx; - postorder (elem, mark_opt_subexp, (void *) subidx); - } - - tree = create_tree (dfa, elem, NULL, - (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); - if (__glibc_unlikely (tree == NULL)) - goto parse_dup_op_espace; - - /* This loop is actually executed only when end != -1, - to rewrite {0,n} as ((...?)?)?... We have - already created the start+1-th copy. */ - if (TYPE_SIGNED (Idx) || end != -1) - for (i = start + 2; i <= end; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (__glibc_unlikely (elem == NULL || tree == NULL)) - goto parse_dup_op_espace; - - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (__glibc_unlikely (tree == NULL)) - goto parse_dup_op_espace; - } - - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); - - return tree; - - parse_dup_op_espace: - *err = REG_ESPACE; - return NULL; -} - -/* Size of the names for collating symbol/equivalence_class/character_class. - I'm not sure, but maybe enough. */ -#define BRACKET_NAME_BUF_SIZE 32 - -#ifndef _LIBC - -/* Convert the byte B to the corresponding wide character. In a - unibyte locale, treat B as itself. In a multibyte locale, return - WEOF if B is an encoding error. */ -static wint_t -parse_byte (unsigned char b, re_dfa_t const *dfa) -{ - return dfa->mb_cur_max > 1 ? __btowc (b) : b; -} - -/* Local function for parse_bracket_exp used in _LIBC environment. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument since we may - update it. */ - -static reg_errcode_t -build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem, - re_dfa_t *dfa, reg_syntax_t syntax, uint_fast32_t nrules, - const unsigned char *collseqmb, const char *collseqwc, - int_fast32_t table_size, const void *symb_table, - const unsigned char *extra) -{ - /* Equivalence Classes and Character Classes can't be a range start/end. */ - if (__glibc_unlikely (start_elem->type == EQUIV_CLASS - || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS - || end_elem->type == CHAR_CLASS)) - return REG_ERANGE; - - /* We can handle no multi character collating elements without libc - support. */ - if (__glibc_unlikely ((start_elem->type == COLL_SYM - && strlen ((char *) start_elem->opr.name) > 1) - || (end_elem->type == COLL_SYM - && strlen ((char *) end_elem->opr.name) > 1))) - return REG_ECOLLATE; - - unsigned int - start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)), - end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - wint_t - start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? parse_byte (start_ch, dfa) : start_elem->opr.wch), - end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? parse_byte (end_ch, dfa) : end_elem->opr.wch); - - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) - && start_wc > end_wc)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (__glibc_unlikely (*range_alloc == mbcset->nranges)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); - - if (__glibc_unlikely (new_array_start == NULL - || new_array_end == NULL)) - { - re_free (new_array_start); - re_free (new_array_end); - return REG_ESPACE; - } - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } - - /* Build the table for single byte characters. */ - for (wchar_t wc = 0; wc < SBC_MAX; ++wc) - { - if (start_wc <= wc && wc <= end_wc) - bitset_set (sbcset, wc); - } - - return REG_NOERROR; -} -#endif /* not _LIBC */ - -#ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static reg_errcode_t -build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, - Idx *coll_sym_alloc, const unsigned char *name, - uint_fast32_t nrules, int_fast32_t table_size, - const void *symb_table, const unsigned char *extra) -{ - size_t name_len = strlen ((const char *) name); - if (__glibc_unlikely (name_len != 1)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } -} -#endif /* not _LIBC */ - -#ifdef _LIBC -/* Local function for parse_bracket_exp used in _LIBC environment. - Seek the collating symbol entry corresponding to NAME. - Return the index of the symbol in the SYMB_TABLE, - or -1 if not found. */ - -static __always_inline int32_t -seek_collating_symbol_entry (const unsigned char *name, size_t name_len, - const int32_t *symb_table, - int_fast32_t table_size, - const unsigned char *extra) -{ - int_fast32_t elem; - - for (elem = 0; elem < table_size; elem++) - if (symb_table[2 * elem] != 0) - { - int32_t idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - if (/* Compare the length of the name. */ - name_len == extra[idx] - /* Compare the name. */ - && memcmp (name, &extra[idx + 1], name_len) == 0) - /* Yep, this is the entry. */ - return elem; - } - return -1; -} - -/* Local function for parse_bracket_exp used in _LIBC environment. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ - -static __always_inline unsigned int -lookup_collation_sequence_value (bracket_elem_t *br_elem, uint32_t nrules, - const unsigned char *collseqmb, - const char *collseqwc, - int_fast32_t table_size, - const int32_t *symb_table, - const unsigned char *extra) -{ - if (br_elem->type == SB_CHAR) - { - /* if (MB_CUR_MAX == 1) */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) - { - if (nrules != 0) - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) - { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len, - symb_table, table_size, - extra); - if (elem != -1) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } - } - else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; - } - return UINT_MAX; -} - -/* Local function for parse_bracket_exp used in _LIBC environment. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument since we may - update it. */ - -static __always_inline reg_errcode_t -build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem, - re_dfa_t *dfa, reg_syntax_t syntax, uint32_t nrules, - const unsigned char *collseqmb, const char *collseqwc, - int_fast32_t table_size, const int32_t *symb_table, - const unsigned char *extra) -{ - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (__glibc_unlikely (start_elem->type == EQUIV_CLASS - || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS - || end_elem->type == CHAR_CLASS)) - return REG_ERANGE; - - /* FIXME: Implement rational ranges here, too. */ - start_collseq = lookup_collation_sequence_value (start_elem, nrules, collseqmb, collseqwc, - table_size, symb_table, extra); - end_collseq = lookup_collation_sequence_value (end_elem, nrules, collseqmb, collseqwc, - table_size, symb_table, extra); - /* Check start/end collation sequence values. */ - if (__glibc_unlikely (start_collseq == UINT_MAX - || end_collseq == UINT_MAX)) - return REG_ECOLLATE; - if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) - && start_collseq > end_collseq)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (__glibc_unlikely (*range_alloc == mbcset->nranges)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - int new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (__glibc_unlikely (new_array_start == NULL - || new_array_end == NULL)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } - - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* if (MB_CUR_MAX == 1) */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); - } - return REG_NOERROR; -} - -/* Local function for parse_bracket_exp used in _LIBC environment. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static __always_inline reg_errcode_t -build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, - Idx *coll_sym_alloc, const unsigned char *name, - uint_fast32_t nrules, int_fast32_t table_size, - const int32_t *symb_table, const unsigned char *extra) -{ - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) - { - elem = seek_collating_symbol_entry (name, name_len, symb_table, - table_size, extra); - if (elem != -1) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (__glibc_unlikely (new_coll_syms == NULL)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; - return REG_NOERROR; - } - else - { - if (__glibc_unlikely (name_len != 1)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - } -} -#endif /* _LIBC */ - -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ - const unsigned char *collseqmb = NULL; - const char *collseqwc = NULL; - uint_fast32_t nrules = 0; - int_fast32_t table_size = 0; - const void *symb_table = NULL; - const unsigned char *extra = NULL; - - re_token_t br_token; - re_bitset_ptr_t sbcset; - re_charset_t *mbcset; - Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; - Idx equiv_class_alloc = 0, char_class_alloc = 0; - bool non_match = false; - bin_tree_t *work_tree; - int token_len; - bool first_round = true; -#ifdef _LIBC - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules) - { - /* - if (MB_CUR_MAX > 1) - */ - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - } -#endif - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); - if (__glibc_unlikely (sbcset == NULL || mbcset == NULL)) - { - re_free (sbcset); - re_free (mbcset); - *err = REG_ESPACE; - return NULL; - } - - token_len = peek_token_bracket (token, regexp, syntax); - if (__glibc_unlikely (token->type == END_OF_RE)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_NON_MATCH_LIST) - { - mbcset->non_match = 1; - non_match = true; - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set (sbcset, '\n'); - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - token_len = peek_token_bracket (token, regexp, syntax); - if (__glibc_unlikely (token->type == END_OF_RE)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - } - - /* We treat the first ']' as a normal character. */ - if (token->type == OP_CLOSE_BRACKET) - token->type = CHARACTER; - - while (1) - { - bracket_elem_t start_elem, end_elem; - unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; - unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; - reg_errcode_t ret; - int token_len2 = 0; - bool is_range_exp = false; - re_token_t token2; - - start_elem.opr.name = start_name_buf; - start_elem.type = COLL_SYM; - ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, - syntax, first_round); - if (__glibc_unlikely (ret != REG_NOERROR)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - first_round = false; - - /* Get information about the next token. We need it in any case. */ - token_len = peek_token_bracket (token, regexp, syntax); - - /* Do not check for ranges if we know they are not allowed. */ - if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) - { - if (__glibc_unlikely (token->type == END_OF_RE)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CHARSET_RANGE) - { - re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ - token_len2 = peek_token_bracket (&token2, regexp, syntax); - if (__glibc_unlikely (token2.type == END_OF_RE)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token2.type == OP_CLOSE_BRACKET) - { - /* We treat the last '-' as a normal character. */ - re_string_skip_bytes (regexp, -token_len); - token->type = CHARACTER; - } - else - is_range_exp = true; - } - } - - if (is_range_exp == true) - { - end_elem.opr.name = end_name_buf; - end_elem.type = COLL_SYM; - ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, - dfa, syntax, true); - if (__glibc_unlikely (ret != REG_NOERROR)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - - token_len = peek_token_bracket (token, regexp, syntax); - - *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem, - dfa, syntax, nrules, collseqmb, collseqwc, - table_size, symb_table, extra); - if (__glibc_unlikely (*err != REG_NOERROR)) - goto parse_bracket_exp_free_return; - } - else - { - switch (start_elem.type) - { - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; - case MB_CHAR: - /* Check whether the array has enough space. */ - if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars)) - { - wchar_t *new_mbchars; - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); - if (__glibc_unlikely (new_mbchars == NULL)) - goto parse_bracket_exp_espace; - mbcset->mbchars = new_mbchars; - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, - mbcset, &equiv_class_alloc, - start_elem.opr.name); - if (__glibc_unlikely (*err != REG_NOERROR)) - goto parse_bracket_exp_free_return; - break; - case COLL_SYM: - *err = build_collating_symbol (sbcset, - mbcset, &coll_sym_alloc, - start_elem.opr.name, - nrules, table_size, symb_table, extra); - if (__glibc_unlikely (*err != REG_NOERROR)) - goto parse_bracket_exp_free_return; - break; - case CHAR_CLASS: - *err = build_charclass (regexp->trans, sbcset, - mbcset, &char_class_alloc, - (const char *) start_elem.opr.name, - syntax); - if (__glibc_unlikely (*err != REG_NOERROR)) - goto parse_bracket_exp_free_return; - break; - default: - DEBUG_ASSERT (false); - break; - } - } - if (__glibc_unlikely (token->type == END_OF_RE)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CLOSE_BRACKET) - break; - } - - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; - int sbc_idx; - /* Build a tree for complex bracket. */ - dfa->has_mb_node = 1; - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (__glibc_unlikely (mbc_tree == NULL)) - goto parse_bracket_exp_espace; - for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) - if (sbcset[sbc_idx]) - break; - /* If there are no bits set in sbcset, there is no point - of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ - if (sbc_idx < BITSET_WORDS) - { - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (__glibc_unlikely (work_tree == NULL)) - goto parse_bracket_exp_espace; - - /* Then join them by ALT node. */ - work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); - if (__glibc_unlikely (work_tree == NULL)) - goto parse_bracket_exp_espace; - } - else - { - re_free (sbcset); - work_tree = mbc_tree; - } - } - else - { - free_charset (mbcset); - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (__glibc_unlikely (work_tree == NULL)) - goto parse_bracket_exp_espace; - } - return work_tree; - - parse_bracket_exp_espace: - *err = REG_ESPACE; - parse_bracket_exp_free_return: - re_free (sbcset); - free_charset (mbcset); - return NULL; -} - -/* Parse an element in the bracket expression. */ - -static reg_errcode_t -parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, bool accept_hyphen) -{ - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) - { - elem->type = MB_CHAR; - elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) - return parse_bracket_symbol (elem, regexp, token); - if (__glibc_unlikely (token->type == OP_CHARSET_RANGE) && !accept_hyphen) - { - /* A '-' must only appear as anything but a range indicator before - the closing bracket. Everything else is an error. */ - re_token_t token2; - (void) peek_token_bracket (&token2, regexp, syntax); - if (token2.type != OP_CLOSE_BRACKET) - /* The actual error value is not standardized since this whole - case is undefined. But ERANGE makes good sense. */ - return REG_ERANGE; - } - elem->type = SB_CHAR; - elem->opr.ch = token->opr.c; - return REG_NOERROR; -} - -/* Parse a bracket symbol in the bracket expression. Bracket symbols are - such as [::], [..], and - [==]. */ - -static reg_errcode_t -parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token) -{ - unsigned char ch, delim = token->opr.c; - int i = 0; - if (re_string_eoi(regexp)) - return REG_EBRACK; - for (;; ++i) - { - if (i >= BRACKET_NAME_BUF_SIZE) - return REG_EBRACK; - if (token->type == OP_OPEN_CHAR_CLASS) - ch = re_string_fetch_byte_case (regexp); - else - ch = re_string_fetch_byte (regexp); - if (re_string_eoi(regexp)) - return REG_EBRACK; - if (ch == delim && re_string_peek_byte (regexp, 0) == ']') - break; - elem->opr.name[i] = ch; - } - re_string_skip_bytes (regexp, 1); - elem->opr.name[i] = '\0'; - switch (token->type) - { - case OP_OPEN_COLL_ELEM: - elem->type = COLL_SYM; - break; - case OP_OPEN_EQUIV_CLASS: - elem->type = EQUIV_CLASS; - break; - case OP_OPEN_CHAR_CLASS: - elem->type = CHAR_CLASS; - break; - default: - break; - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the equivalence class which is represented by NAME. - The result are written to MBCSET and SBCSET. - EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument since we may update it. */ - -static reg_errcode_t -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, - Idx *equiv_class_alloc, const unsigned char *name) -{ -#ifdef _LIBC - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - const int32_t *table, *indirect; - const unsigned char *weights, *extra, *cp; - unsigned char char_buf[2]; - int32_t idx1, idx2; - unsigned int ch; - size_t len; - /* Calculate the index for equivalence class. */ - cp = name; - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - idx1 = findidx (table, indirect, extra, &cp, -1); - if (__glibc_unlikely (idx1 == 0 || *cp != '\0')) - /* This isn't a valid character. */ - return REG_ECOLLATE; - - /* Build single byte matching table for this equivalence class. */ - len = weights[idx1 & 0xffffff]; - for (ch = 0; ch < SBC_MAX; ++ch) - { - char_buf[0] = ch; - cp = char_buf; - idx2 = findidx (table, indirect, extra, &cp, 1); -/* - idx2 = table[ch]; -*/ - if (idx2 == 0) - /* This isn't a valid character. */ - continue; - /* Compare only if the length matches and the collation rule - index is the same. */ - if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24) - && memcmp (weights + (idx1 & 0xffffff) + 1, - weights + (idx2 & 0xffffff) + 1, len) == 0) - bitset_set (sbcset, ch); - } - /* Check whether the array has enough space. */ - if (__glibc_unlikely (*equiv_class_alloc == mbcset->nequiv_classes)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; - /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); - if (__glibc_unlikely (new_equiv_classes == NULL)) - return REG_ESPACE; - mbcset->equiv_classes = new_equiv_classes; - *equiv_class_alloc = new_equiv_class_alloc; - } - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else -#endif /* _LIBC */ - { - if (__glibc_unlikely (strlen ((const char *) name) != 1)) - return REG_ECOLLATE; - bitset_set (sbcset, *name); - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the character class which is represented by NAME. - The result are written to MBCSET and SBCSET. - CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument since we may update it. */ - -static reg_errcode_t -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - re_charset_t *mbcset, Idx *char_class_alloc, - const char *class_name, reg_syntax_t syntax) -{ - int i; - const char *name = class_name; - - /* In case of REG_ICASE "upper" and "lower" match the both of - upper and lower cases. */ - if ((syntax & RE_ICASE) - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - - /* Check the space of the arrays. */ - if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); - if (__glibc_unlikely (new_char_classes == NULL)) - return REG_ESPACE; - mbcset->char_classes = new_char_classes; - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); - -#define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ - if (__glibc_unlikely (trans != NULL)) \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, trans[i]); \ - } \ - else \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, i); \ - } \ - } while (0) - - if (strcmp (name, "alnum") == 0) - BUILD_CHARCLASS_LOOP (isalnum); - else if (strcmp (name, "cntrl") == 0) - BUILD_CHARCLASS_LOOP (iscntrl); - else if (strcmp (name, "lower") == 0) - BUILD_CHARCLASS_LOOP (islower); - else if (strcmp (name, "space") == 0) - BUILD_CHARCLASS_LOOP (isspace); - else if (strcmp (name, "alpha") == 0) - BUILD_CHARCLASS_LOOP (isalpha); - else if (strcmp (name, "digit") == 0) - BUILD_CHARCLASS_LOOP (isdigit); - else if (strcmp (name, "print") == 0) - BUILD_CHARCLASS_LOOP (isprint); - else if (strcmp (name, "upper") == 0) - BUILD_CHARCLASS_LOOP (isupper); - else if (strcmp (name, "blank") == 0) - BUILD_CHARCLASS_LOOP (isblank); - else if (strcmp (name, "graph") == 0) - BUILD_CHARCLASS_LOOP (isgraph); - else if (strcmp (name, "punct") == 0) - BUILD_CHARCLASS_LOOP (ispunct); - else if (strcmp (name, "xdigit") == 0) - BUILD_CHARCLASS_LOOP (isxdigit); - else - return REG_ECTYPE; - - return REG_NOERROR; -} - -static bin_tree_t * -build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const char *class_name, - const char *extra, bool non_match, - reg_errcode_t *err) -{ - re_bitset_ptr_t sbcset; - re_charset_t *mbcset; - Idx alloc = 0; - reg_errcode_t ret; - bin_tree_t *tree; - - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (__glibc_unlikely (sbcset == NULL)) - { - *err = REG_ESPACE; - return NULL; - } - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); - if (__glibc_unlikely (mbcset == NULL)) - { - re_free (sbcset); - *err = REG_ESPACE; - return NULL; - } - mbcset->non_match = non_match; - - /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, mbcset, &alloc, class_name, 0); - - if (__glibc_unlikely (ret != REG_NOERROR)) - { - re_free (sbcset); - free_charset (mbcset); - *err = ret; - return NULL; - } - /* \w match '_' also. */ - for (; *extra; extra++) - bitset_set (sbcset, *extra); - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - /* Build a tree for simple bracket. */ - re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset }; - tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (__glibc_unlikely (tree == NULL)) - goto build_word_op_espace; - - if (dfa->mb_cur_max > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - dfa->has_mb_node = 1; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (__glibc_unlikely (mbc_tree == NULL)) - goto build_word_op_espace; - /* Then join them by ALT node. */ - tree = create_tree (dfa, tree, mbc_tree, OP_ALT); - if (__glibc_likely (mbc_tree != NULL)) - return tree; - } - else - { - free_charset (mbcset); - return tree; - } - - build_word_op_espace: - re_free (sbcset); - free_charset (mbcset); - *err = REG_ESPACE; - return NULL; -} - -/* This is intended for the expressions like "a{1,3}". - Fetch a number from 'input', and return the number. - Return -1 if the number field is empty like "{,1}". - Return RE_DUP_MAX + 1 if the number field is too large. - Return -2 if an error occurred. */ - -static Idx -fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -{ - Idx num = -1; - unsigned char c; - while (1) - { - fetch_token (token, input, syntax); - c = token->opr.c; - if (__glibc_unlikely (token->type == END_OF_RE)) - return -2; - if (token->type == OP_CLOSE_DUP_NUM || c == ',') - break; - num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) - ? -2 - : num == -1 - ? c - '0' - : MIN (RE_DUP_MAX + 1, num * 10 + c - '0')); - } - return num; -} - -static void -free_charset (re_charset_t *cset) -{ - re_free (cset->mbchars); -#ifdef _LIBC - re_free (cset->coll_syms); - re_free (cset->equiv_classes); -#endif - re_free (cset->range_starts); - re_free (cset->range_ends); - re_free (cset->char_classes); - re_free (cset); -} - -/* Functions for binary tree operation. */ - -/* Create a tree node. */ - -static bin_tree_t * -create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - re_token_type_t type) -{ - re_token_t t = { .type = type }; - return create_token_tree (dfa, left, right, &t); -} - -static bin_tree_t * -create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - const re_token_t *token) -{ - bin_tree_t *tree; - if (__glibc_unlikely (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE)) - { - bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); - - if (storage == NULL) - return NULL; - storage->next = dfa->str_tree_storage; - dfa->str_tree_storage = storage; - dfa->str_tree_storage_idx = 0; - } - tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; - - tree->parent = NULL; - tree->left = left; - tree->right = right; - tree->token = *token; - tree->token.duplicated = 0; - tree->token.opt_subexp = 0; - tree->first = NULL; - tree->next = NULL; - tree->node_idx = -1; - - if (left != NULL) - left->parent = tree; - if (right != NULL) - right->parent = tree; - return tree; -} - -/* Mark the tree SRC as an optional subexpression. - To be called from preorder or postorder. */ - -static reg_errcode_t -mark_opt_subexp (void *extra, bin_tree_t *node) -{ - Idx idx = (uintptr_t) extra; - if (node->token.type == SUBEXP && node->token.opr.idx == idx) - node->token.opt_subexp = 1; - - return REG_NOERROR; -} - -/* Free the allocated memory inside NODE. */ - -static void -free_token (re_token_t *node) -{ - if (node->type == COMPLEX_BRACKET && node->duplicated == 0) - free_charset (node->opr.mbcset); - else if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); -} - -/* Worker function for tree walking. Free the allocated memory inside NODE - and its children. */ - -static reg_errcode_t -free_tree (void *extra, bin_tree_t *node) -{ - free_token (&node->token); - return REG_NOERROR; -} - - -/* Duplicate the node SRC, and return new node. This is a preorder - visit similar to the one implemented by the generic visitor, but - we need more infrastructure to maintain two parallel trees --- so, - it's easier to duplicate. */ - -static bin_tree_t * -duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) -{ - const bin_tree_t *node; - bin_tree_t *dup_root; - bin_tree_t **p_new = &dup_root, *dup_node = root->parent; - - for (node = root; ; ) - { - /* Create a new tree and link it back to the current parent. */ - *p_new = create_token_tree (dfa, NULL, NULL, &node->token); - if (*p_new == NULL) - return NULL; - (*p_new)->parent = dup_node; - (*p_new)->token.duplicated = 1; - dup_node = *p_new; - - /* Go to the left node, or up and to the right. */ - if (node->left) - { - node = node->left; - p_new = &dup_node->left; - } - else - { - const bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - dup_node = dup_node->parent; - if (!node) - return dup_root; - } - node = node->right; - p_new = &dup_node->right; - } - } -} diff --git a/xcompile/lib/regex.c b/xcompile/lib/regex.c deleted file mode 100644 index 3beb0deb987..00000000000 --- a/xcompile/lib/regex.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#define __STDC_WANT_IEC_60559_BFP_EXT__ - -#ifndef _LIBC -# include - -# if __GNUC_PREREQ (4, 6) -# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure" -# pragma GCC diagnostic ignored "-Wvla" -# endif -# if __GNUC_PREREQ (4, 3) -# pragma GCC diagnostic ignored "-Wold-style-definition" -# pragma GCC diagnostic ignored "-Wtype-limits" -# endif -#endif - -/* Make sure no one compiles this code with a C++ compiler. */ -#if defined __cplusplus && defined _LIBC -# error "This is C code, use a C compiler" -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -# include "../locale/localeinfo.h" -#endif - -/* On some systems, limits.h sets RE_DUP_MAX to a lower value than - GNU regex allows. Include it before , which correctly - #undefs RE_DUP_MAX and sets it to the right value. */ -#include - -#include -#include "regex_internal.h" - -#include "regex_internal.c" -#include "regcomp.c" -#include "regexec.c" - -/* Binary backward compatibility. */ -#if _LIBC -# include -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -int re_max_failures = 2000; -# endif -#endif diff --git a/xcompile/lib/regex.h b/xcompile/lib/regex.h deleted file mode 100644 index 9ef0252ffff..00000000000 --- a/xcompile/lib/regex.h +++ /dev/null @@ -1,699 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library. - Copyright (C) 1985, 1989-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -#include - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Define __USE_GNU to declare GNU extensions that violate the - POSIX name space rules. */ -#ifdef _GNU_SOURCE -# define __USE_GNU 1 -#endif - -#ifdef _REGEX_LARGE_OFFSETS - -/* Use types and values that are wide enough to represent signed and - unsigned byte offsets in memory. This currently works only when - the regex code is used outside of the GNU C library; it is not yet - supported within glibc itself, and glibc users should not define - _REGEX_LARGE_OFFSETS. */ - -/* The type of object sizes. */ -typedef size_t __re_size_t; - -/* The type of object sizes, in places where the traditional code - uses unsigned long int. */ -typedef size_t __re_long_size_t; - -#else - -/* The traditional GNU regex implementation mishandles strings longer - than INT_MAX. */ -typedef unsigned int __re_size_t; -typedef unsigned long int __re_long_size_t; - -#endif - -/* The following two types have to be signed and unsigned integer type - wide enough to hold a value of a pointer. For most ANSI compilers - ptrdiff_t and size_t should be likely OK. Still size of these two - types is 2 for Microsoft C. Ugh... */ -typedef long int s_reg_t; -typedef unsigned long int active_reg_t; - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings are chosen so that Emacs syntax - remains the value 0. The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -#ifdef __USE_GNU -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -# define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then '{...}' defines an interval, and \{ and \} - are literals. - If not set, then '\{...\}' defines an interval. */ -# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \ matches . - If not set, then \ is a back-reference. */ -# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -# define RE_DEBUG (RE_NO_GNU_OPS << 1) - -/* If this bit is set, a syntactically invalid interval is treated as - a string of ordinary characters. For example, the ERE 'a{1' is - treated as 'a\{1'. */ -# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) - -/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only - for ^, because it is difficult to scan the regex backwards to find - whether ^ should be special. */ -# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) - -/* If this bit is set, then \{ cannot be first in a regex or - immediately after an alternation, open-group or \} operator. */ -# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) - -/* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ -# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) -#endif - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -#ifdef __USE_GNU -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -# define RE_SYNTAX_EMACS 0 - -# define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CHAR_CLASSES \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INVALID_INTERVAL_ORD) \ - & ~(RE_DOT_NOT_NULL | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) - -# define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS \ - | RE_INVALID_INTERVAL_ORD) - -# define RE_SYNTAX_GREP \ - ((RE_SYNTAX_POSIX_BASIC | RE_NEWLINE_ALT) \ - & ~(RE_CONTEXT_INVALID_DUP | RE_DOT_NOT_NULL)) - -# define RE_SYNTAX_EGREP \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_INVALID_INTERVAL_ORD | RE_NEWLINE_ALT) \ - & ~(RE_CONTEXT_INVALID_OPS | RE_DOT_NOT_NULL)) - -/* POSIX grep -E behavior is no longer incompatible with GNU. */ -# define RE_SYNTAX_POSIX_EGREP \ - RE_SYNTAX_EGREP - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -# define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -# define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -# define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -/* Maximum number of duplicates an interval can allow. POSIX-conforming - systems might define this in , but we want our - value, so remove any previous define. */ -# ifdef _REGEX_INCLUDE_LIMITS_H -# include -# endif -# ifdef RE_DUP_MAX -# undef RE_DUP_MAX -# endif - -/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored - the counter as a 2-byte signed integer. This is no longer true, so - RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 9) / 10) if _REGEX_LARGE_OFFSETS is defined. - However, there would be a huge performance problem if someone - actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains - its historical value. */ -# define RE_DUP_MAX (0x7fff) -#endif - - -/* POSIX 'cflags' bits (i.e., information for 'regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (1 << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (1 << 2) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (1 << 3) - - -/* POSIX 'eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - -/* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ -#define REG_STARTEND (1 << 2) - - -/* If any error codes are removed, changed, or added, update the - '__re_error_msgid' table in regcomp.c. */ - -typedef enum -{ - _REG_ENOSYS = -1, /* This will never happen for this implementation. */ - _REG_NOERROR = 0, /* Success. */ - _REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - _REG_BADPAT, /* Invalid pattern. */ - _REG_ECOLLATE, /* Invalid collating element. */ - _REG_ECTYPE, /* Invalid character class name. */ - _REG_EESCAPE, /* Trailing backslash. */ - _REG_ESUBREG, /* Invalid back reference. */ - _REG_EBRACK, /* Unmatched left bracket. */ - _REG_EPAREN, /* Parenthesis imbalance. */ - _REG_EBRACE, /* Unmatched \{. */ - _REG_BADBR, /* Invalid contents of \{\}. */ - _REG_ERANGE, /* Invalid range end. */ - _REG_ESPACE, /* Ran out of memory. */ - _REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Too large (e.g., repeat count too large). */ - _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -#if defined _XOPEN_SOURCE || defined __USE_XOPEN2K -# define REG_ENOSYS _REG_ENOSYS -#endif -#define REG_NOERROR _REG_NOERROR -#define REG_NOMATCH _REG_NOMATCH -#define REG_BADPAT _REG_BADPAT -#define REG_ECOLLATE _REG_ECOLLATE -#define REG_ECTYPE _REG_ECTYPE -#define REG_EESCAPE _REG_EESCAPE -#define REG_ESUBREG _REG_ESUBREG -#define REG_EBRACK _REG_EBRACK -#define REG_EPAREN _REG_EPAREN -#define REG_EBRACE _REG_EBRACE -#define REG_BADBR _REG_BADBR -#define REG_ERANGE _REG_ERANGE -#define REG_ESPACE _REG_ESPACE -#define REG_BADRPT _REG_BADRPT -#define REG_EEND _REG_EEND -#define REG_ESIZE _REG_ESIZE -#define REG_ERPAREN _REG_ERPAREN - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields 'buffer', 'allocated', 'fastmap', - and 'translate' can be set. After the pattern has been compiled, - the fields 're_nsub', 'not_bol' and 'not_eol' are available. All - other fields are private to the regex routines. */ - -#ifndef RE_TRANSLATE_TYPE -# define __RE_TRANSLATE_TYPE unsigned char * -# ifdef __USE_GNU -# define RE_TRANSLATE_TYPE __RE_TRANSLATE_TYPE -# endif -#endif - -#ifdef __USE_GNU -# define __REPB_PREFIX(name) name -#else -# define __REPB_PREFIX(name) __##name -#endif - -struct re_pattern_buffer -{ - /* Space that holds the compiled pattern. The type - 'struct re_dfa_t' is private and is not declared here. */ - struct re_dfa_t *__REPB_PREFIX(buffer); - - /* Number of bytes to which 'buffer' points. */ - __re_long_size_t __REPB_PREFIX(allocated); - - /* Number of bytes actually used in 'buffer'. */ - __re_long_size_t __REPB_PREFIX(used); - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t __REPB_PREFIX(syntax); - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses the - fastmap, if there is one, to skip over impossible starting points - for matches. */ - char *__REPB_PREFIX(fastmap); - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation is - applied to a pattern when it is compiled and to a string when it - is matched. */ - __RE_TRANSLATE_TYPE __REPB_PREFIX(translate); - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in 're_search_2', to see whether or - not we should use the fastmap, so we don't set this absolutely - perfectly; see 're_compile_fastmap' (the "duplicate" case). */ - unsigned __REPB_PREFIX(can_be_null) : 1; - - /* If REGS_UNALLOCATED, allocate space in the 'regs' structure - for 'max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU -# define REGS_UNALLOCATED 0 -# define REGS_REALLOCATE 1 -# define REGS_FIXED 2 -#endif - unsigned __REPB_PREFIX(regs_allocated) : 2; - - /* Set to zero when 're_compile_pattern' compiles a pattern; set to - one by 're_compile_fastmap' if it updates the fastmap. */ - unsigned __REPB_PREFIX(fastmap_accurate) : 1; - - /* If set, 're_match_2' does not return information about - subexpressions. */ - unsigned __REPB_PREFIX(no_sub) : 1; - - /* If set, a beginning-of-line anchor doesn't match at the beginning - of the string. */ - unsigned __REPB_PREFIX(not_bol) : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned __REPB_PREFIX(not_eol) : 1; - - /* If true, an anchor at a newline matches. */ - unsigned __REPB_PREFIX(newline_anchor) : 1; -}; - -typedef struct re_pattern_buffer regex_t; - -/* Type for byte offsets within the string. POSIX mandates this. */ -#ifdef _REGEX_LARGE_OFFSETS -/* POSIX 1003.1-2008 requires that regoff_t be at least as wide as - ptrdiff_t and ssize_t. We don't know of any hosts where ptrdiff_t - is wider than ssize_t, so ssize_t is safe. ptrdiff_t is not - visible here, so use ssize_t. */ -typedef ssize_t regoff_t; -#else -/* The traditional GNU regex implementation mishandles strings longer - than INT_MAX. */ -typedef int regoff_t; -#endif - - -#ifdef __USE_GNU -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - __re_size_t num_regs; - regoff_t *start; - regoff_t *end; -}; - - -/* If 'regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - 're_match_2' returns information about at least this many registers - the first time a 'regs' structure is passed. */ -# ifndef RE_NREGS -# define RE_NREGS 30 -# endif -#endif - - -/* POSIX specification for registers. Aside from the different names than - 're_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -#ifndef _REGEX_NELTS -# if (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ - && !defined __STDC_NO_VLA__) -# define _REGEX_NELTS(n) n -# else -# define _REGEX_NELTS(n) -# endif -#endif - -#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wvla" -#endif - -#ifndef _Attr_access_ -# ifdef __attr_access -# define _Attr_access_(arg) __attr_access (arg) -# elif defined __GNUC__ && 10 <= __GNUC__ -# define _Attr_access_(x) __attribute__ ((__access__ x)) -# else -# define _Attr_access_(x) -# endif -#endif - -#ifdef __USE_GNU -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the 're_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global 're_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. - - To free the allocated storage, you must call 'regfree' on BUFFER. - Note that the translate table must either have been initialized by - 'regcomp', with a malloc'ed value, or set to NULL before calling - 'regfree'. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer) - _Attr_access_ ((__read_only__, 1, 2)); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern regoff_t re_search (struct re_pattern_buffer *__buffer, - const char *__String, regoff_t __length, - regoff_t __start, regoff_t __range, - struct re_registers *__regs) - _Attr_access_ ((__read_only__, 2, 3)); - - -/* Like 're_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, regoff_t __length1, - const char *__string2, regoff_t __length2, - regoff_t __start, regoff_t __range, - struct re_registers *__regs, - regoff_t __stop) - _Attr_access_ ((__read_only__, 2, 3)) - _Attr_access_ ((__read_only__, 4, 5)); - - -/* Like 're_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern regoff_t re_match (struct re_pattern_buffer *__buffer, - const char *__String, regoff_t __length, - regoff_t __start, struct re_registers *__regs) - _Attr_access_ ((__read_only__, 2, 3)); - - -/* Relates to 're_match' as 're_search_2' relates to 're_search'. */ -extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, regoff_t __length1, - const char *__string2, regoff_t __length2, - regoff_t __start, struct re_registers *__regs, - regoff_t __stop) - _Attr_access_ ((__read_only__, 2, 3)) - _Attr_access_ ((__read_only__, 4, 5)); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least 'NUM_REGS * sizeof - (regoff_t)' bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - BUFFER will allocate its own register data, without - freeing the old data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - __re_size_t __num_regs, - regoff_t *__starts, regoff_t *__ends); -#endif /* Use GNU */ - -#if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC) -/* 4.2 bsd compatibility. */ -extern char *re_comp (const char *); -extern int re_exec (const char *); -#endif - -/* For plain 'restrict', use glibc's __restrict if defined. - Otherwise, GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". - Other compilers use __restrict, __restrict__, and _Restrict, and - 'configure' might #define 'restrict' to those words, so pick a - different name. */ -#ifndef _Restrict_ -# if defined __restrict \ - || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \ - || __clang_major__ >= 3 -# define _Restrict_ __restrict -# elif 199901L <= __STDC_VERSION__ || defined restrict -# define _Restrict_ restrict -# else -# define _Restrict_ -# endif -#endif -/* For the ISO C99 syntax - array_name[restrict] - use glibc's __restrict_arr if available. - Otherwise, GCC 3.1 and clang support this syntax (but not in C++ mode). - Other ISO C99 compilers support it as well. */ -#ifndef _Restrict_arr_ -# ifdef __restrict_arr -# define _Restrict_arr_ __restrict_arr -# elif ((199901L <= __STDC_VERSION__ \ - || 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \ - || __clang_major__ >= 3) \ - && !defined __cplusplus) -# define _Restrict_arr_ _Restrict_ -# else -# define _Restrict_arr_ -# endif -#endif - -/* POSIX compatibility. */ -extern int regcomp (regex_t *_Restrict_ __preg, - const char *_Restrict_ __pattern, - int __cflags); - -extern int regexec (const regex_t *_Restrict_ __preg, - const char *_Restrict_ __String, size_t __nmatch, - regmatch_t __pmatch[_Restrict_arr_ - _REGEX_NELTS (__nmatch)], - int __eflags); - -extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, - char *_Restrict_ __errbuf, size_t __errbuf_size) - _Attr_access_ ((__write_only__, 3, 4)); - -extern void regfree (regex_t *__preg); - -#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__) -# pragma GCC diagnostic pop -#endif - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ diff --git a/xcompile/lib/regex_internal.c b/xcompile/lib/regex_internal.c deleted file mode 100644 index 998a19b7241..00000000000 --- a/xcompile/lib/regex_internal.c +++ /dev/null @@ -1,1711 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -static void re_string_construct_common (const char *str, Idx len, - re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa); -static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - re_hashval_t hash); -static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int context, - re_hashval_t hash); -static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, - Idx new_buf_len); -static void build_wcs_buffer (re_string_t *pstr); -static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr); -static void build_upper_buffer (re_string_t *pstr); -static void re_string_translate_buffer (re_string_t *pstr); -static unsigned int re_string_context_at (const re_string_t *input, Idx idx, - int eflags) __attribute__ ((pure)); - -/* Functions for string operation. */ - -/* This function allocate the buffers. It is necessary to call - re_string_reconstruct before using the object. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - Idx init_buf_len; - - /* Ensure at least one character fits into the buffers. */ - if (init_len < dfa->mb_cur_max) - init_len = dfa->mb_cur_max; - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - ret = re_string_realloc_buffers (pstr, init_buf_len); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; -} - -/* This function allocate the buffers, and initialize them. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_string_construct (re_string_t *pstr, const char *str, Idx len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - memset (pstr, '\0', sizeof (re_string_t)); - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - if (len > 0) - { - ret = re_string_realloc_buffers (pstr, len + 1); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - } - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - - if (icase) - { - if (dfa->mb_cur_max > 1) - { - while (1) - { - ret = build_wcs_upper_buffer (pstr); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - if (pstr->valid_raw_len >= len) - break; - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - } - } - else - build_upper_buffer (pstr); - } - else - { - if (dfa->mb_cur_max > 1) - build_wcs_buffer (pstr); - else - { - if (trans != NULL) - re_string_translate_buffer (pstr); - else - { - pstr->valid_len = pstr->bufs_len; - pstr->valid_raw_len = pstr->bufs_len; - } - } - } - - return REG_NOERROR; -} - -/* Helper functions for re_string_allocate, and re_string_construct. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) -{ - if (pstr->mb_cur_max > 1) - { - wint_t *new_wcs; - - /* Avoid overflow in realloc. */ - const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) - < new_buf_len)) - return REG_ESPACE; - - new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); - if (__glibc_unlikely (new_wcs == NULL)) - return REG_ESPACE; - pstr->wcs = new_wcs; - if (pstr->offsets != NULL) - { - Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); - if (__glibc_unlikely (new_offsets == NULL)) - return REG_ESPACE; - pstr->offsets = new_offsets; - } - } - if (pstr->mbs_allocated) - { - unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, - new_buf_len); - if (__glibc_unlikely (new_mbs == NULL)) - return REG_ESPACE; - pstr->mbs = new_mbs; - } - pstr->bufs_len = new_buf_len; - return REG_NOERROR; -} - - -static void -re_string_construct_common (const char *str, Idx len, re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) -{ - pstr->raw_mbs = (const unsigned char *) str; - pstr->len = len; - pstr->raw_len = len; - pstr->trans = trans; - pstr->icase = icase; - pstr->mbs_allocated = (trans != NULL || icase); - pstr->mb_cur_max = dfa->mb_cur_max; - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; - pstr->raw_stop = pstr->stop; -} - - -/* Build wide character buffer PSTR->WCS. - If the byte sequence of the string are: - (0), (1), (0), (1), - Then wide character buffer will be: - , WEOF , , WEOF , - We use WEOF for padding, they indicate that the position isn't - a first byte of a multibyte character. - - Note that this function assumes PSTR->VALID_LEN elements are already - built and starts from PSTR->VALID_LEN. */ - -static void -build_wcs_buffer (re_string_t *pstr) -{ -#ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; - DEBUG_ASSERT (MB_LEN_MAX >= pstr->mb_cur_max); -#else - unsigned char buf[64]; -#endif - mbstate_t prev_st; - Idx byte_idx, end_idx, remain_len; - size_t mbclen; - - /* Build the buffers from pstr->valid_len to either pstr->len or - pstr->bufs_len. */ - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - for (byte_idx = pstr->valid_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - /* Apply the translation if we need. */ - if (__glibc_unlikely (pstr->trans != NULL)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; - mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (__glibc_unlikely (mbclen == (size_t) -1 || mbclen == 0 - || (mbclen == (size_t) -2 - && pstr->bufs_len >= pstr->len))) - { - /* We treat these cases as a singlebyte character. */ - mbclen = 1; - wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - if (__glibc_unlikely (pstr->trans != NULL)) - wc = pstr->trans[wc]; - pstr->cur_state = prev_st; - } - else if (__glibc_unlikely (mbclen == (size_t) -2)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - - /* Write wide character and padding. */ - pstr->wcs[byte_idx++] = wc; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; -} - -/* Build wide character buffer PSTR->WCS like build_wcs_buffer, - but for REG_ICASE. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -build_wcs_upper_buffer (re_string_t *pstr) -{ - mbstate_t prev_st; - Idx src_idx, byte_idx, end_idx, remain_len; - size_t mbclen; -#ifdef _LIBC - char buf[MB_LEN_MAX]; - DEBUG_ASSERT (pstr->mb_cur_max <= MB_LEN_MAX); -#else - char buf[64]; -#endif - - byte_idx = pstr->valid_len; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - /* The following optimization assumes that ASCII characters can be - mapped to wide characters with a simple cast. */ - if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) - { - while (byte_idx < end_idx) - { - wchar_t wc; - unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - - if (isascii (ch) && mbsinit (&pstr->cur_state)) - { - /* The next step uses the assumption that wchar_t is encoded - ASCII-safe: all ASCII values can be converted like this. */ - wchar_t wcu = __towupper (ch); - if (isascii (wcu)) - { - pstr->mbs[byte_idx] = wcu; - pstr->wcs[byte_idx] = wcu; - byte_idx++; - continue; - } - } - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - mbclen = __mbrtowc (&wc, - ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx - + byte_idx), remain_len, &pstr->cur_state); - if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) - { - wchar_t wcu = __towupper (wc); - if (wcu != wc) - { - size_t mbcdlen; - - mbcdlen = __wcrtomb (buf, wcu, &prev_st); - if (__glibc_likely (mbclen == mbcdlen)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else - { - src_idx = byte_idx; - goto offsets_needed; - } - } - else - memcpy (pstr->mbs + byte_idx, - pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0 - || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) - { - /* It is an invalid character, an incomplete character - at the end of the string, or '\0'. Just use the byte. */ - pstr->mbs[byte_idx] = ch; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (__glibc_unlikely (mbclen == (size_t) -1)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; - return REG_NOERROR; - } - else - for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - offsets_needed: - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - if (__glibc_unlikely (pstr->trans != NULL)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; - mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (__glibc_likely (0 < mbclen && mbclen < (size_t) -2)) - { - wchar_t wcu = __towupper (wc); - if (wcu != wc) - { - size_t mbcdlen; - - mbcdlen = __wcrtomb ((char *) buf, wcu, &prev_st); - if (__glibc_likely (mbclen == mbcdlen)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else if (mbcdlen != (size_t) -1) - { - size_t i; - - if (byte_idx + mbcdlen > pstr->bufs_len) - { - pstr->cur_state = prev_st; - break; - } - - if (pstr->offsets == NULL) - { - pstr->offsets = re_malloc (Idx, pstr->bufs_len); - - if (pstr->offsets == NULL) - return REG_ESPACE; - } - if (!pstr->offsets_needed) - { - for (i = 0; i < (size_t) byte_idx; ++i) - pstr->offsets[i] = i; - pstr->offsets_needed = 1; - } - - memcpy (pstr->mbs + byte_idx, buf, mbcdlen); - pstr->wcs[byte_idx] = wcu; - pstr->offsets[byte_idx] = src_idx; - for (i = 1; i < mbcdlen; ++i) - { - pstr->offsets[byte_idx + i] - = src_idx + (i < mbclen ? i : mbclen - 1); - pstr->wcs[byte_idx + i] = WEOF; - } - pstr->len += mbcdlen - mbclen; - if (pstr->raw_stop > src_idx) - pstr->stop += mbcdlen - mbclen; - end_idx = (pstr->bufs_len > pstr->len) - ? pstr->len : pstr->bufs_len; - byte_idx += mbcdlen; - src_idx += mbclen; - continue; - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - - if (__glibc_unlikely (pstr->offsets_needed != 0)) - { - size_t i; - for (i = 0; i < mbclen; ++i) - pstr->offsets[byte_idx + i] = src_idx + i; - } - src_idx += mbclen; - - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0 - || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; - - if (__glibc_unlikely (pstr->trans != NULL)) - ch = pstr->trans [ch]; - pstr->mbs[byte_idx] = ch; - - if (__glibc_unlikely (pstr->offsets_needed != 0)) - pstr->offsets[byte_idx] = src_idx; - ++src_idx; - - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (__glibc_unlikely (mbclen == (size_t) -1)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = src_idx; - return REG_NOERROR; -} - -/* Skip characters until the index becomes greater than NEW_RAW_IDX. - Return the index. */ - -static Idx -re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) -{ - mbstate_t prev_st; - Idx rawbuf_idx; - size_t mbclen; - wint_t wc = WEOF; - - /* Skip the characters which are not necessary to check. */ - for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; - rawbuf_idx < new_raw_idx;) - { - wchar_t wc2; - Idx remain_len = pstr->raw_len - rawbuf_idx; - prev_st = pstr->cur_state; - mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, - remain_len, &pstr->cur_state); - if (__glibc_unlikely (mbclen == (size_t) -2 || mbclen == (size_t) -1 - || mbclen == 0)) - { - /* We treat these cases as a single byte character. */ - if (mbclen == 0 || remain_len == 0) - wc = L'\0'; - else - wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); - mbclen = 1; - pstr->cur_state = prev_st; - } - else - wc = wc2; - /* Then proceed the next character. */ - rawbuf_idx += mbclen; - } - *last_wc = wc; - return rawbuf_idx; -} - -/* Build the buffer PSTR->MBS, and apply the translation if we need. - This function is used in case of REG_ICASE. */ - -static void -build_upper_buffer (re_string_t *pstr) -{ - Idx char_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; - if (__glibc_unlikely (pstr->trans != NULL)) - ch = pstr->trans[ch]; - pstr->mbs[char_idx] = toupper (ch); - } - pstr->valid_len = char_idx; - pstr->valid_raw_len = char_idx; -} - -/* Apply TRANS to the buffer in PSTR. */ - -static void -re_string_translate_buffer (re_string_t *pstr) -{ - Idx buf_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; - pstr->mbs[buf_idx] = pstr->trans[ch]; - } - - pstr->valid_len = buf_idx; - pstr->valid_raw_len = buf_idx; -} - -/* This function re-construct the buffers. - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, - convert to upper case in case of REG_ICASE, apply translation. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -{ - Idx offset; - - if (__glibc_unlikely (pstr->raw_mbs_idx <= idx)) - offset = idx - pstr->raw_mbs_idx; - else - { - /* Reset buffer. */ - if (pstr->mb_cur_max > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - pstr->len = pstr->raw_len; - pstr->stop = pstr->raw_stop; - pstr->valid_len = 0; - pstr->raw_mbs_idx = 0; - pstr->valid_raw_len = 0; - pstr->offsets_needed = 0; - pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (!pstr->mbs_allocated) - pstr->mbs = (unsigned char *) pstr->raw_mbs; - offset = idx; - } - - if (__glibc_likely (offset != 0)) - { - /* Should the already checked characters be kept? */ - if (__glibc_likely (offset < pstr->valid_raw_len)) - { - /* Yes, move them to the front of the buffer. */ - if (__glibc_unlikely (pstr->offsets_needed)) - { - Idx low = 0, high = pstr->valid_len, mid; - do - { - mid = (high + low) / 2; - if (pstr->offsets[mid] > offset) - high = mid; - else if (pstr->offsets[mid] < offset) - low = mid + 1; - else - break; - } - while (low < high); - if (pstr->offsets[mid] < offset) - ++mid; - pstr->tip_context = re_string_context_at (pstr, mid - 1, - eflags); - /* This can be quite complicated, so handle specially - only the common and easy case where the character with - different length representation of lower and upper - case is present at or after offset. */ - if (pstr->valid_len > offset - && mid == offset && pstr->offsets[mid] == offset) - { - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - for (low = 0; low < pstr->valid_len; low++) - pstr->offsets[low] = pstr->offsets[low + offset] - offset; - } - else - { - /* Otherwise, just find out how long the partial multibyte - character at offset is and fill it with WEOF/255. */ - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - while (mid > 0 && pstr->offsets[mid - 1] == offset) - --mid; - while (mid < pstr->valid_len) - if (pstr->wcs[mid] != WEOF) - break; - else - ++mid; - if (mid == pstr->valid_len) - pstr->valid_len = 0; - else - { - pstr->valid_len = pstr->offsets[mid] - offset; - if (pstr->valid_len) - { - for (low = 0; low < pstr->valid_len; ++low) - pstr->wcs[low] = WEOF; - memset (pstr->mbs, 255, pstr->valid_len); - } - } - pstr->valid_raw_len = pstr->valid_len; - } - } - else - { - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); - if (pstr->mb_cur_max > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - if (__glibc_unlikely (pstr->mbs_allocated)) - memmove (pstr->mbs, pstr->mbs + offset, - pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - DEBUG_ASSERT (pstr->valid_len > 0); - } - } - else - { - /* No, skip all characters until IDX. */ - Idx prev_valid_len = pstr->valid_len; - - if (__glibc_unlikely (pstr->offsets_needed)) - { - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - } - pstr->valid_len = 0; - if (pstr->mb_cur_max > 1) - { - Idx wcs_idx; - wint_t wc = WEOF; - - if (pstr->is_utf8) - { - const unsigned char *raw, *p, *end; - - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; - end = raw + (offset - pstr->mb_cur_max); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -#ifdef _LIBC - /* We know the wchar_t encoding is UCS4, so for the simple - case, ASCII characters, skip the conversion step. */ - if (isascii (*p) && __glibc_likely (pstr->trans == NULL)) - { - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - /* pstr->valid_len = 0; */ - wc = (wchar_t) *p; - } - else -#endif - for (; p >= end; --p) - if ((*p & 0xc0) != 0x80) - { - mbstate_t cur_state; - wchar_t wc2; - Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; - size_t mbclen; - - const unsigned char *pp = p; - if (__glibc_unlikely (pstr->trans != NULL)) - { - int i = mlen < 6 ? mlen : 6; - while (--i >= 0) - buf[i] = pstr->trans[p[i]]; - pp = buf; - } - /* XXX Don't use mbrtowc, we know which conversion - to use (UTF-8 -> UCS4). */ - memset (&cur_state, 0, sizeof (cur_state)); - mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, - &cur_state); - if (raw + offset - p <= mbclen - && mbclen < (size_t) -2) - { - memset (&pstr->cur_state, '\0', - sizeof (mbstate_t)); - pstr->valid_len = mbclen - (raw + offset - p); - wc = wc2; - } - break; - } - } - - if (wc == WEOF) - pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; - if (wc == WEOF) - pstr->tip_context - = re_string_context_at (pstr, prev_valid_len - 1, eflags); - else - pstr->tip_context = ((__glibc_unlikely (pstr->word_ops_used != 0) - && IS_WIDE_WORD_CHAR (wc)) - ? CONTEXT_WORD - : ((IS_WIDE_NEWLINE (wc) - && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - if (__glibc_unlikely (pstr->valid_len)) - { - for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) - pstr->wcs[wcs_idx] = WEOF; - if (pstr->mbs_allocated) - memset (pstr->mbs, 255, pstr->valid_len); - } - pstr->valid_raw_len = pstr->valid_len; - } - else - { - int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; - pstr->valid_raw_len = 0; - if (pstr->trans) - c = pstr->trans[c]; - pstr->tip_context = (bitset_contain (pstr->word_char, c) - ? CONTEXT_WORD - : ((IS_NEWLINE (c) && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - } - } - if (!__glibc_unlikely (pstr->mbs_allocated)) - pstr->mbs += offset; - } - pstr->raw_mbs_idx = idx; - pstr->len -= offset; - pstr->stop -= offset; - - /* Then build the buffers. */ - if (pstr->mb_cur_max > 1) - { - if (pstr->icase) - { - reg_errcode_t ret = build_wcs_upper_buffer (pstr); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - } - else - build_wcs_buffer (pstr); - } - else - if (__glibc_unlikely (pstr->mbs_allocated)) - { - if (pstr->icase) - build_upper_buffer (pstr); - else if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - else - pstr->valid_len = pstr->len; - - pstr->cur_idx = 0; - return REG_NOERROR; -} - -static unsigned char -__attribute__ ((pure)) -re_string_peek_byte_case (const re_string_t *pstr, Idx idx) -{ - int ch; - Idx off; - - /* Handle the common (easiest) cases first. */ - if (__glibc_likely (!pstr->mbs_allocated)) - return re_string_peek_byte (pstr, idx); - - if (pstr->mb_cur_max > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); - - off = pstr->cur_idx + idx; - if (pstr->offsets_needed) - off = pstr->offsets[off]; - - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I - this function returns CAPITAL LETTER I instead of first byte of - DOTLESS SMALL LETTER I. The latter would confuse the parser, - since peek_byte_case doesn't advance cur_idx in any way. */ - if (pstr->offsets_needed && !isascii (ch)) - return re_string_peek_byte (pstr, idx); - - return ch; -} - -static unsigned char -re_string_fetch_byte_case (re_string_t *pstr) -{ - if (__glibc_likely (!pstr->mbs_allocated)) - return re_string_fetch_byte (pstr); - - if (pstr->offsets_needed) - { - Idx off; - int ch; - - /* For tr_TR.UTF-8 [[:islower:]] there is - [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip - in that case the whole multi-byte character and return - the original letter. On the other side, with - [[: DOTLESS SMALL LETTER I return [[:I, as doing - anything else would complicate things too much. */ - - if (!re_string_first_byte (pstr, pstr->cur_idx)) - return re_string_fetch_byte (pstr); - - off = pstr->offsets[pstr->cur_idx]; - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - if (! isascii (ch)) - return re_string_fetch_byte (pstr); - - re_string_skip_bytes (pstr, - re_string_char_size_at (pstr, pstr->cur_idx)); - return ch; - } - - return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; -} - -static void -re_string_destruct (re_string_t *pstr) -{ - re_free (pstr->wcs); - re_free (pstr->offsets); - if (pstr->mbs_allocated) - re_free (pstr->mbs); -} - -/* Return the context at IDX in INPUT. */ - -static unsigned int -re_string_context_at (const re_string_t *input, Idx idx, int eflags) -{ - int c; - if (__glibc_unlikely (idx < 0)) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - if (__glibc_unlikely (idx == input->len)) - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); - if (input->mb_cur_max > 1) - { - wint_t wc; - Idx wc_idx = idx; - while(input->wcs[wc_idx] == WEOF) - { - DEBUG_ASSERT (wc_idx >= 0); - --wc_idx; - if (wc_idx < 0) - return input->tip_context; - } - wc = input->wcs[wc_idx]; - if (__glibc_unlikely (input->word_ops_used != 0) - && IS_WIDE_WORD_CHAR (wc)) - return CONTEXT_WORD; - return (IS_WIDE_NEWLINE (wc) && input->newline_anchor - ? CONTEXT_NEWLINE : 0); - } - else - { - c = re_string_byte_at (input, idx); - if (bitset_contain (input->word_char, c)) - return CONTEXT_WORD; - return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; - } -} - -/* Functions for set operation. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_alloc (re_node_set *set, Idx size) -{ - set->alloc = size; - set->nelem = 0; - set->elems = re_malloc (Idx, size); - if (__glibc_unlikely (set->elems == NULL) - && (MALLOC_0_IS_NONNULL || size != 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_init_1 (re_node_set *set, Idx elem) -{ - set->alloc = 1; - set->nelem = 1; - set->elems = re_malloc (Idx, 1); - if (__glibc_unlikely (set->elems == NULL)) - { - set->alloc = set->nelem = 0; - return REG_ESPACE; - } - set->elems[0] = elem; - return REG_NOERROR; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) -{ - set->alloc = 2; - set->elems = re_malloc (Idx, 2); - if (__glibc_unlikely (set->elems == NULL)) - return REG_ESPACE; - if (elem1 == elem2) - { - set->nelem = 1; - set->elems[0] = elem1; - } - else - { - set->nelem = 2; - if (elem1 < elem2) - { - set->elems[0] = elem1; - set->elems[1] = elem2; - } - else - { - set->elems[0] = elem2; - set->elems[1] = elem1; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_init_copy (re_node_set *dest, const re_node_set *src) -{ - dest->nelem = src->nelem; - if (src->nelem > 0) - { - dest->alloc = dest->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (__glibc_unlikely (dest->elems == NULL)) - { - dest->alloc = dest->nelem = 0; - return REG_ESPACE; - } - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - } - else - re_node_set_init_empty (dest); - return REG_NOERROR; -} - -/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. - Note: We assume dest->elems is NULL, when dest->alloc is 0. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, is, id, delta, sbase; - if (src1->nelem == 0 || src2->nelem == 0) - return REG_NOERROR; - - /* We need dest->nelem + 2 * elems_in_intersection; this is a - conservative estimate. */ - if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) - { - Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; - Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); - if (__glibc_unlikely (new_elems == NULL)) - return REG_ESPACE; - dest->elems = new_elems; - dest->alloc = new_alloc; - } - - /* Find the items in the intersection of SRC1 and SRC2, and copy - into the top of DEST those that are not already in DEST itself. */ - sbase = dest->nelem + src1->nelem + src2->nelem; - i1 = src1->nelem - 1; - i2 = src2->nelem - 1; - id = dest->nelem - 1; - for (;;) - { - if (src1->elems[i1] == src2->elems[i2]) - { - /* Try to find the item in DEST. Maybe we could binary search? */ - while (id >= 0 && dest->elems[id] > src1->elems[i1]) - --id; - - if (id < 0 || dest->elems[id] != src1->elems[i1]) - dest->elems[--sbase] = src1->elems[i1]; - - if (--i1 < 0 || --i2 < 0) - break; - } - - /* Lower the highest of the two items. */ - else if (src1->elems[i1] < src2->elems[i2]) - { - if (--i2 < 0) - break; - } - else - { - if (--i1 < 0) - break; - } - } - - id = dest->nelem - 1; - is = dest->nelem + src1->nelem + src2->nelem - 1; - delta = is - sbase + 1; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place; this is more or - less the same loop that is in re_node_set_merge. */ - dest->nelem += delta; - if (delta > 0 && id >= 0) - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (--id < 0) - break; - } - } - - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); - - return REG_NOERROR; -} - -/* Calculate the union set of the sets SRC1 and SRC2. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_init_union (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, id; - if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) - { - dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (__glibc_unlikely (dest->elems == NULL)) - return REG_ESPACE; - } - else - { - if (src1 != NULL && src1->nelem > 0) - return re_node_set_init_copy (dest, src1); - else if (src2 != NULL && src2->nelem > 0) - return re_node_set_init_copy (dest, src2); - else - re_node_set_init_empty (dest); - return REG_NOERROR; - } - for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) - { - if (src1->elems[i1] > src2->elems[i2]) - { - dest->elems[id++] = src2->elems[i2++]; - continue; - } - if (src1->elems[i1] == src2->elems[i2]) - ++i2; - dest->elems[id++] = src1->elems[i1++]; - } - if (i1 < src1->nelem) - { - memcpy (dest->elems + id, src1->elems + i1, - (src1->nelem - i1) * sizeof (Idx)); - id += src1->nelem - i1; - } - else if (i2 < src2->nelem) - { - memcpy (dest->elems + id, src2->elems + i2, - (src2->nelem - i2) * sizeof (Idx)); - id += src2->nelem - i2; - } - dest->nelem = id; - return REG_NOERROR; -} - -/* Calculate the union set of the sets DEST and SRC. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_node_set_merge (re_node_set *dest, const re_node_set *src) -{ - Idx is, id, sbase, delta; - if (src == NULL || src->nelem == 0) - return REG_NOERROR; - if (dest->alloc < 2 * src->nelem + dest->nelem) - { - Idx new_alloc = 2 * (src->nelem + dest->alloc); - Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); - if (__glibc_unlikely (new_buffer == NULL)) - return REG_ESPACE; - dest->elems = new_buffer; - dest->alloc = new_alloc; - } - - if (__glibc_unlikely (dest->nelem == 0)) - { - /* Although we already guaranteed above that dest->alloc != 0 and - therefore dest->elems != NULL, add a debug assertion to pacify - GCC 11.2.1's -fanalyzer. */ - DEBUG_ASSERT (dest->elems); - dest->nelem = src->nelem; - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - return REG_NOERROR; - } - - /* Copy into the top of DEST the items of SRC that are not - found in DEST. Maybe we could binary search in DEST? */ - for (sbase = dest->nelem + 2 * src->nelem, - is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) - { - if (dest->elems[id] == src->elems[is]) - is--, id--; - else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; - else /* if (dest->elems[id] > src->elems[is]) */ - --id; - } - - if (is >= 0) - { - /* If DEST is exhausted, the remaining items of SRC must be unique. */ - sbase -= is + 1; - memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); - } - - id = dest->nelem - 1; - is = dest->nelem + 2 * src->nelem - 1; - delta = is - sbase + 1; - if (delta == 0) - return REG_NOERROR; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place. */ - dest->nelem += delta; - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (--id < 0) - { - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (Idx)); - break; - } - } - } - - return REG_NOERROR; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - Return true if successful. */ - -static bool -__attribute_warn_unused_result__ -re_node_set_insert (re_node_set *set, Idx elem) -{ - Idx idx; - /* In case the set is empty. */ - if (set->alloc == 0) - return __glibc_likely (re_node_set_init_1 (set, elem) == REG_NOERROR); - - if (__glibc_unlikely (set->nelem) == 0) - { - /* Although we already guaranteed above that set->alloc != 0 and - therefore set->elems != NULL, add a debug assertion to pacify - GCC 11.2 -fanalyzer. */ - DEBUG_ASSERT (set->elems); - set->elems[0] = elem; - ++set->nelem; - return true; - } - - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (__glibc_unlikely (new_elems == NULL)) - return false; - set->elems = new_elems; - } - - /* Move the elements which follows the new element. Test the - first element separately to skip a check in the inner loop. */ - if (elem < set->elems[0]) - { - for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - else - { - for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - DEBUG_ASSERT (set->elems[idx - 1] < elem); - } - - /* Insert the new element. */ - set->elems[idx] = elem; - ++set->nelem; - return true; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have any element greater than or equal to ELEM. - Return true if successful. */ - -static bool -__attribute_warn_unused_result__ -re_node_set_insert_last (re_node_set *set, Idx elem) -{ - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (__glibc_unlikely (new_elems == NULL)) - return false; - set->elems = new_elems; - } - - /* Insert the new element. */ - set->elems[set->nelem++] = elem; - return true; -} - -/* Compare two node sets SET1 and SET2. - Return true if SET1 and SET2 are equivalent. */ - -static bool -__attribute__ ((pure)) -re_node_set_compare (const re_node_set *set1, const re_node_set *set2) -{ - Idx i; - if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) - return false; - for (i = set1->nelem ; --i >= 0 ; ) - if (set1->elems[i] != set2->elems[i]) - return false; - return true; -} - -/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ - -static Idx -__attribute__ ((pure)) -re_node_set_contains (const re_node_set *set, Idx elem) -{ - __re_size_t idx, right, mid; - if (set->nelem <= 0) - return 0; - - /* Binary search the element. */ - idx = 0; - right = set->nelem - 1; - while (idx < right) - { - mid = (idx + right) / 2; - if (set->elems[mid] < elem) - idx = mid + 1; - else - right = mid; - } - return set->elems[idx] == elem ? idx + 1 : 0; -} - -static void -re_node_set_remove_at (re_node_set *set, Idx idx) -{ - if (idx < 0 || idx >= set->nelem) - return; - --set->nelem; - for (; idx < set->nelem; idx++) - set->elems[idx] = set->elems[idx + 1]; -} - - -/* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return -1 if an error occurred. */ - -static Idx -re_dfa_add_node (re_dfa_t *dfa, re_token_t token) -{ - if (__glibc_unlikely (dfa->nodes_len >= dfa->nodes_alloc)) - { - size_t new_nodes_alloc = dfa->nodes_alloc * 2; - Idx *new_nexts, *new_indices; - re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes; - - /* Avoid overflows in realloc. */ - const size_t max_object_size = MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) - < new_nodes_alloc)) - return -1; - - new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); - if (__glibc_unlikely (new_nodes == NULL)) - return -1; - dfa->nodes = new_nodes; - dfa->nodes_alloc = new_nodes_alloc; - new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); - if (new_nexts != NULL) - dfa->nexts = new_nexts; - new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); - if (new_indices != NULL) - dfa->org_indices = new_indices; - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); - if (new_edests != NULL) - dfa->edests = new_edests; - new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); - if (new_eclosures != NULL) - dfa->eclosures = new_eclosures; - if (__glibc_unlikely (new_nexts == NULL || new_indices == NULL - || new_edests == NULL || new_eclosures == NULL)) - return -1; - } - dfa->nodes[dfa->nodes_len] = token; - dfa->nodes[dfa->nodes_len].constraint = 0; - dfa->nodes[dfa->nodes_len].accept_mb = - ((token.type == OP_PERIOD && dfa->mb_cur_max > 1) - || token.type == COMPLEX_BRACKET); - dfa->nexts[dfa->nodes_len] = -1; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); - re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); - return dfa->nodes_len++; -} - -static re_hashval_t -calc_state_hash (const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash = nodes->nelem + context; - Idx i; - for (i = 0 ; i < nodes->nelem ; i++) - hash += nodes->elems[i]; - return hash; -} - -/* Search for the state whose node_set is equivalent to NODES. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -__attribute_warn_unused_result__ -re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#if defined GCC_LINT || defined lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (__glibc_unlikely (nodes->nelem == 0)) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, 0); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (hash != state->hash) - continue; - if (re_node_set_compare (&state->nodes, nodes)) - return state; - } - - /* There are no appropriate state in the dfa, create the new one. */ - new_state = create_ci_newstate (dfa, nodes, hash); - if (__glibc_unlikely (new_state == NULL)) - *err = REG_ESPACE; - - return new_state; -} - -/* Search for the state whose node_set is equivalent to NODES and - whose context is equivalent to CONTEXT. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -__attribute_warn_unused_result__ -re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#if defined GCC_LINT || defined lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (nodes->nelem == 0) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, context); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (state->hash == hash - && state->context == context - && re_node_set_compare (state->entrance_nodes, nodes)) - return state; - } - /* There are no appropriate state in 'dfa', create the new one. */ - new_state = create_cd_newstate (dfa, nodes, context, hash); - if (__glibc_unlikely (new_state == NULL)) - *err = REG_ESPACE; - - return new_state; -} - -/* Finish initialization of the new state NEWSTATE, and using its hash value - HASH put in the appropriate bucket of DFA's state table. Return value - indicates the error code if failed. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, - re_hashval_t hash) -{ - struct re_state_table_entry *spot; - reg_errcode_t err; - Idx i; - - newstate->hash = hash; - err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); - if (__glibc_unlikely (err != REG_NOERROR)) - return REG_ESPACE; - for (i = 0; i < newstate->nodes.nelem; i++) - { - Idx elem = newstate->nodes.elems[i]; - if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) - return REG_ESPACE; - } - - spot = dfa->state_table + (hash & dfa->state_hash_mask); - if (__glibc_unlikely (spot->alloc <= spot->num)) - { - Idx new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); - if (__glibc_unlikely (new_array == NULL)) - return REG_ESPACE; - spot->array = new_array; - spot->alloc = new_alloc; - } - spot->array[spot->num++] = newstate; - return REG_NOERROR; -} - -static void -free_state (re_dfastate_t *state) -{ - re_node_set_free (&state->non_eps_nodes); - re_node_set_free (&state->inveclosure); - if (state->entrance_nodes != &state->nodes) - { - re_node_set_free (state->entrance_nodes); - re_free (state->entrance_nodes); - } - re_node_set_free (&state->nodes); - re_free (state->word_trtable); - re_free (state->trtable); - re_free (state); -} - -/* Create the new state which is independent of contexts. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -__attribute_warn_unused_result__ -create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - re_hashval_t hash) -{ - Idx i; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (__glibc_unlikely (newstate == NULL)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_free (newstate); - return NULL; - } - - newstate->entrance_nodes = &newstate->nodes; - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (type == CHARACTER && !node->constraint) - continue; - newstate->accept_mb |= node->accept_mb; - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR || node->constraint) - newstate->has_constraint = 1; - } - err = register_state (dfa, newstate, hash); - if (__glibc_unlikely (err != REG_NOERROR)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/* Create the new state which is depend on the context CONTEXT. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -__attribute_warn_unused_result__ -create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int context, re_hashval_t hash) -{ - Idx i, nctx_nodes = 0; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (__glibc_unlikely (newstate == NULL)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_free (newstate); - return NULL; - } - - newstate->context = context; - newstate->entrance_nodes = &newstate->nodes; - - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - if (type == CHARACTER && !constraint) - continue; - newstate->accept_mb |= node->accept_mb; - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - - if (constraint) - { - if (newstate->entrance_nodes == &newstate->nodes) - { - re_node_set *entrance_nodes = re_malloc (re_node_set, 1); - if (__glibc_unlikely (entrance_nodes == NULL)) - { - free_state (newstate); - return NULL; - } - newstate->entrance_nodes = entrance_nodes; - if (re_node_set_init_copy (newstate->entrance_nodes, nodes) - != REG_NOERROR) - { - free_state (newstate); - return NULL; - } - nctx_nodes = 0; - newstate->has_constraint = 1; - } - - if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) - { - re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); - ++nctx_nodes; - } - } - } - err = register_state (dfa, newstate, hash); - if (__glibc_unlikely (err != REG_NOERROR)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} diff --git a/xcompile/lib/regex_internal.h b/xcompile/lib/regex_internal.h deleted file mode 100644 index 149ec2e868a..00000000000 --- a/xcompile/lib/regex_internal.h +++ /dev/null @@ -1,834 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _REGEX_INTERNAL_H -#define _REGEX_INTERNAL_H 1 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef _LIBC -# include -#endif - -#include -#include - -#if defined DEBUG && DEBUG != 0 -# include -# define DEBUG_ASSERT(x) assert (x) -#else -# define DEBUG_ASSERT(x) assume (x) -#endif - -#ifdef _LIBC -# include -# define lock_define(name) __libc_lock_define (, name) -# define lock_init(lock) (__libc_lock_init (lock), 0) -# define lock_fini(lock) ((void) 0) -# define lock_lock(lock) __libc_lock_lock (lock) -# define lock_unlock(lock) __libc_lock_unlock (lock) -#elif defined GNULIB_LOCK && !defined GNULIB_REGEX_SINGLE_THREAD -# include "glthread/lock.h" -# define lock_define(name) gl_lock_define (, name) -# define lock_init(lock) glthread_lock_init (&(lock)) -# define lock_fini(lock) glthread_lock_destroy (&(lock)) -# define lock_lock(lock) glthread_lock_lock (&(lock)) -# define lock_unlock(lock) glthread_lock_unlock (&(lock)) -#elif defined GNULIB_PTHREAD && !defined GNULIB_REGEX_SINGLE_THREAD -# include -# define lock_define(name) pthread_mutex_t name; -# define lock_init(lock) pthread_mutex_init (&(lock), 0) -# define lock_fini(lock) pthread_mutex_destroy (&(lock)) -# define lock_lock(lock) pthread_mutex_lock (&(lock)) -# define lock_unlock(lock) pthread_mutex_unlock (&(lock)) -#else -# define lock_define(name) -# define lock_init(lock) 0 -# define lock_fini(lock) ((void) 0) - /* The 'dfa' avoids an "unused variable 'dfa'" warning from GCC. */ -# define lock_lock(lock) ((void) dfa) -# define lock_unlock(lock) ((void) 0) -#endif - -/* In case that the system doesn't have isblank(). */ -#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) -# define isblank(ch) ((ch) == ' ' || (ch) == '\t') -#endif - -/* regex code assumes isascii has its usual numeric meaning, - even if the portable character set uses EBCDIC encoding, - and even if wint_t is wider than int. */ -#ifndef _LIBC -# undef isascii -# define isascii(c) (((c) & ~0x7f) == 0) -#endif - -#ifdef _LIBC -# ifndef _RE_DEFINE_LOCALE_FUNCTIONS -# define _RE_DEFINE_LOCALE_FUNCTIONS 1 -# include -# include -# endif -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifdef _LIBC -# undef gettext -# define gettext(msgid) \ - __dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES) -# endif -#else -# undef gettext -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* Number of ASCII characters. */ -#define ASCII_CHARS 0x80 - -/* Number of single byte characters. */ -#define SBC_MAX (UCHAR_MAX + 1) - -#define COLL_ELEM_LEN_MAX 8 - -/* The character which represents newline. */ -#define NEWLINE_CHAR '\n' -#define WIDE_NEWLINE_CHAR L'\n' - -/* Rename to standard API for using out of glibc. */ -#ifndef _LIBC -# undef __wctype -# undef __iswalnum -# undef __iswctype -# undef __towlower -# undef __towupper -# define __wctype wctype -# define __iswalnum iswalnum -# define __iswctype iswctype -# define __towlower towlower -# define __towupper towupper -# define __btowc btowc -# define __mbrtowc mbrtowc -# define __wcrtomb wcrtomb -# define __regfree regfree -#endif /* not _LIBC */ - -/* Types related to integers. Unless protected by #ifdef _LIBC, the - regex code should avoid exact-width types like int32_t and uint64_t - as some non-GCC platforms lack them, an issue when this code is - used in Gnulib. */ - -#ifndef SSIZE_MAX -# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) -#endif -#ifndef ULONG_WIDTH -# define ULONG_WIDTH REGEX_UINTEGER_WIDTH (ULONG_MAX) -/* The number of usable bits in an unsigned integer type with maximum - value MAX, as an int expression suitable in #if. Cover all known - practical hosts. This implementation exploits the fact that MAX is - 1 less than a power of 2, and merely counts the number of 1 bits in - MAX; "COBn" means "count the number of 1 bits in the low-order n bits". */ -# define REGEX_UINTEGER_WIDTH(max) REGEX_COB128 (max) -# define REGEX_COB128(n) (REGEX_COB64 ((n) >> 31 >> 31 >> 2) + REGEX_COB64 (n)) -# define REGEX_COB64(n) (REGEX_COB32 ((n) >> 31 >> 1) + REGEX_COB32 (n)) -# define REGEX_COB32(n) (REGEX_COB16 ((n) >> 16) + REGEX_COB16 (n)) -# define REGEX_COB16(n) (REGEX_COB8 ((n) >> 8) + REGEX_COB8 (n)) -# define REGEX_COB8(n) (REGEX_COB4 ((n) >> 4) + REGEX_COB4 (n)) -# define REGEX_COB4(n) (!!((n) & 8) + !!((n) & 4) + !!((n) & 2) + ((n) & 1)) -# if ULONG_MAX / 2 + 1 != 1ul << (ULONG_WIDTH - 1) -# error "ULONG_MAX out of range" -# endif -#endif - -/* The type of indexes into strings. This is signed, not size_t, - since the API requires indexes to fit in regoff_t anyway, and using - signed integers makes the code a bit smaller and presumably faster. - The traditional GNU regex implementation uses int for indexes. - The POSIX-compatible implementation uses a possibly-wider type. - The name 'Idx' is three letters to minimize the hassle of - reindenting a lot of regex code that formerly used 'int'. */ -typedef regoff_t Idx; -#ifdef _REGEX_LARGE_OFFSETS -# define IDX_MAX SSIZE_MAX -#else -# define IDX_MAX INT_MAX -#endif - -/* A hash value, suitable for computing hash tables. */ -typedef __re_size_t re_hashval_t; - -/* An integer used to represent a set of bits. It must be unsigned, - and must be at least as wide as unsigned int. */ -typedef unsigned long int bitset_word_t; -/* All bits set in a bitset_word_t. */ -#define BITSET_WORD_MAX ULONG_MAX -/* Number of bits in a bitset_word_t. */ -#define BITSET_WORD_BITS ULONG_WIDTH - -/* Number of bitset_word_t values in a bitset_t. */ -#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) - -typedef bitset_word_t bitset_t[BITSET_WORDS]; -typedef bitset_word_t *re_bitset_ptr_t; -typedef const bitset_word_t *re_const_bitset_ptr_t; - -#define PREV_WORD_CONSTRAINT 0x0001 -#define PREV_NOTWORD_CONSTRAINT 0x0002 -#define NEXT_WORD_CONSTRAINT 0x0004 -#define NEXT_NOTWORD_CONSTRAINT 0x0008 -#define PREV_NEWLINE_CONSTRAINT 0x0010 -#define NEXT_NEWLINE_CONSTRAINT 0x0020 -#define PREV_BEGBUF_CONSTRAINT 0x0040 -#define NEXT_ENDBUF_CONSTRAINT 0x0080 -#define WORD_DELIM_CONSTRAINT 0x0100 -#define NOT_WORD_DELIM_CONSTRAINT 0x0200 - -typedef enum -{ - INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - LINE_FIRST = PREV_NEWLINE_CONSTRAINT, - LINE_LAST = NEXT_NEWLINE_CONSTRAINT, - BUF_FIRST = PREV_BEGBUF_CONSTRAINT, - BUF_LAST = NEXT_ENDBUF_CONSTRAINT, - WORD_DELIM = WORD_DELIM_CONSTRAINT, - NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT -} re_context_type; - -typedef struct -{ - Idx alloc; - Idx nelem; - Idx *elems; -} re_node_set; - -typedef enum -{ - NON_TYPE = 0, - - /* Node type, These are used by token, node, tree. */ - CHARACTER = 1, - END_OF_RE = 2, - SIMPLE_BRACKET = 3, - OP_BACK_REF = 4, - OP_PERIOD = 5, - COMPLEX_BRACKET = 6, - OP_UTF8_PERIOD = 7, - - /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used - when the debugger shows values of this enum type. */ -#define EPSILON_BIT 8 - OP_OPEN_SUBEXP = EPSILON_BIT | 0, - OP_CLOSE_SUBEXP = EPSILON_BIT | 1, - OP_ALT = EPSILON_BIT | 2, - OP_DUP_ASTERISK = EPSILON_BIT | 3, - ANCHOR = EPSILON_BIT | 4, - - /* Tree type, these are used only by tree. */ - CONCAT = 16, - SUBEXP = 17, - - /* Token type, these are used only by token. */ - OP_DUP_PLUS = 18, - OP_DUP_QUESTION, - OP_OPEN_BRACKET, - OP_CLOSE_BRACKET, - OP_CHARSET_RANGE, - OP_OPEN_DUP_NUM, - OP_CLOSE_DUP_NUM, - OP_NON_MATCH_LIST, - OP_OPEN_COLL_ELEM, - OP_CLOSE_COLL_ELEM, - OP_OPEN_EQUIV_CLASS, - OP_CLOSE_EQUIV_CLASS, - OP_OPEN_CHAR_CLASS, - OP_CLOSE_CHAR_CLASS, - OP_WORD, - OP_NOTWORD, - OP_SPACE, - OP_NOTSPACE, - BACK_SLASH - -} re_token_type_t; - -typedef struct -{ - /* Multibyte characters. */ - wchar_t *mbchars; - -#ifdef _LIBC - /* Collating symbols. */ - int32_t *coll_syms; -#endif - -#ifdef _LIBC - /* Equivalence classes. */ - int32_t *equiv_classes; -#endif - - /* Range expressions. */ -#ifdef _LIBC - uint32_t *range_starts; - uint32_t *range_ends; -#else - wchar_t *range_starts; - wchar_t *range_ends; -#endif - - /* Character classes. */ - wctype_t *char_classes; - - /* If this character set is the non-matching list. */ - unsigned int non_match : 1; - - /* # of multibyte characters. */ - Idx nmbchars; - - /* # of collating symbols. */ - Idx ncoll_syms; - - /* # of equivalence classes. */ - Idx nequiv_classes; - - /* # of range expressions. */ - Idx nranges; - - /* # of character classes. */ - Idx nchar_classes; -} re_charset_t; - -typedef struct -{ - union - { - unsigned char c; /* for CHARACTER */ - re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ - re_charset_t *mbcset; /* for COMPLEX_BRACKET */ - Idx idx; /* for BACK_REF */ - re_context_type ctx_type; /* for ANCHOR */ - } opr; -#if (__GNUC__ >= 2 || defined __clang__) && !defined __STRICT_ANSI__ - re_token_type_t type : 8; -#else - re_token_type_t type; -#endif - unsigned int constraint : 10; /* context constraint */ - unsigned int duplicated : 1; - unsigned int opt_subexp : 1; - unsigned int accept_mb : 1; - /* These 2 bits can be moved into the union if needed (e.g. if running out - of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ - unsigned int mb_partial : 1; - unsigned int word_char : 1; -} re_token_t; - -#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) - -struct re_string_t -{ - /* Indicate the raw buffer which is the original string passed as an - argument of regexec(), re_search(), etc.. */ - const unsigned char *raw_mbs; - /* Store the multibyte string. In case of "case insensitive mode" like - REG_ICASE, upper cases of the string are stored, otherwise MBS points - the same address that RAW_MBS points. */ - unsigned char *mbs; - /* Store the wide character string which is corresponding to MBS. */ - wint_t *wcs; - Idx *offsets; - mbstate_t cur_state; - /* Index in RAW_MBS. Each character mbs[i] corresponds to - raw_mbs[raw_mbs_idx + i]. */ - Idx raw_mbs_idx; - /* The length of the valid characters in the buffers. */ - Idx valid_len; - /* The corresponding number of bytes in raw_mbs array. */ - Idx valid_raw_len; - /* The length of the buffers MBS and WCS. */ - Idx bufs_len; - /* The index in MBS, which is updated by re_string_fetch_byte. */ - Idx cur_idx; - /* length of RAW_MBS array. */ - Idx raw_len; - /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ - Idx len; - /* End of the buffer may be shorter than its length in the cases such - as re_match_2, re_search_2. Then, we use STOP for end of the buffer - instead of LEN. */ - Idx raw_stop; - /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ - Idx stop; - - /* The context of mbs[0]. We store the context independently, since - the context of mbs[0] may be different from raw_mbs[0], which is - the beginning of the input string. */ - unsigned int tip_context; - /* The translation passed as a part of an argument of re_compile_pattern. */ - RE_TRANSLATE_TYPE trans; - /* Copy of re_dfa_t's word_char. */ - re_const_bitset_ptr_t word_char; - /* true if REG_ICASE. */ - unsigned char icase; - unsigned char is_utf8; - unsigned char map_notascii; - unsigned char mbs_allocated; - unsigned char offsets_needed; - unsigned char newline_anchor; - unsigned char word_ops_used; - int mb_cur_max; -}; -typedef struct re_string_t re_string_t; - - -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; - -#ifndef _LIBC -# define IS_IN(libc) false -#endif - -#define re_string_peek_byte(pstr, offset) \ - ((pstr)->mbs[(pstr)->cur_idx + offset]) -#define re_string_fetch_byte(pstr) \ - ((pstr)->mbs[(pstr)->cur_idx++]) -#define re_string_first_byte(pstr, idx) \ - ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) -#define re_string_is_single_byte_char(pstr, idx) \ - ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ - || (pstr)->wcs[(idx) + 1] != WEOF)) -#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) -#define re_string_cur_idx(pstr) ((pstr)->cur_idx) -#define re_string_get_buffer(pstr) ((pstr)->mbs) -#define re_string_length(pstr) ((pstr)->len) -#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) -#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) -#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) - -#ifdef _LIBC -# define MALLOC_0_IS_NONNULL 1 -#elif !defined MALLOC_0_IS_NONNULL -# define MALLOC_0_IS_NONNULL 0 -#endif - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) -#define re_free(p) free (p) - -struct bin_tree_t -{ - struct bin_tree_t *parent; - struct bin_tree_t *left; - struct bin_tree_t *right; - struct bin_tree_t *first; - struct bin_tree_t *next; - - re_token_t token; - - /* 'node_idx' is the index in dfa->nodes, if 'type' == 0. - Otherwise 'type' indicate the type of this node. */ - Idx node_idx; -}; -typedef struct bin_tree_t bin_tree_t; - -#define BIN_TREE_STORAGE_SIZE \ - ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) - -struct bin_tree_storage_t -{ - struct bin_tree_storage_t *next; - bin_tree_t data[BIN_TREE_STORAGE_SIZE]; -}; -typedef struct bin_tree_storage_t bin_tree_storage_t; - -#define CONTEXT_WORD 1 -#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) -#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) -#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) - -#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) -#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) -#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) -#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) -#define IS_ORDINARY_CONTEXT(c) ((c) == 0) - -#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') -#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) -#define IS_WIDE_WORD_CHAR(ch) (__iswalnum (ch) || (ch) == L'_') -#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) - -#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ - ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ - || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) - -#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ - ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ - || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) - -struct re_dfastate_t -{ - re_hashval_t hash; - re_node_set nodes; - re_node_set non_eps_nodes; - re_node_set inveclosure; - re_node_set *entrance_nodes; - struct re_dfastate_t **trtable, **word_trtable; - unsigned int context : 4; - unsigned int halt : 1; - /* If this state can accept "multi byte". - Note that we refer to multibyte characters, and multi character - collating elements as "multi byte". */ - unsigned int accept_mb : 1; - /* If this state has backreference node(s). */ - unsigned int has_backref : 1; - unsigned int has_constraint : 1; -}; -typedef struct re_dfastate_t re_dfastate_t; - -struct re_state_table_entry -{ - Idx num; - Idx alloc; - re_dfastate_t **array; -}; - -/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ - -typedef struct -{ - Idx next_idx; - Idx alloc; - re_dfastate_t **array; -} state_array_t; - -/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ - -typedef struct -{ - Idx node; - Idx str_idx; /* The position NODE match at. */ - state_array_t path; -} re_sub_match_last_t; - -/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. - And information about the node, whose type is OP_CLOSE_SUBEXP, - corresponding to NODE is stored in LASTS. */ - -typedef struct -{ - Idx str_idx; - Idx node; - state_array_t *path; - Idx alasts; /* Allocation size of LASTS. */ - Idx nlasts; /* The number of LASTS. */ - re_sub_match_last_t **lasts; -} re_sub_match_top_t; - -struct re_backref_cache_entry -{ - Idx node; - Idx str_idx; - Idx subexp_from; - Idx subexp_to; - bitset_word_t eps_reachable_subexps_map; - char more; -}; - -typedef struct -{ - /* The string object corresponding to the input string. */ - re_string_t input; - const re_dfa_t *const dfa; - /* EFLAGS of the argument of regexec. */ - int eflags; - /* Where the matching ends. */ - Idx match_last; - Idx last_node; - /* The state log used by the matcher. */ - re_dfastate_t **state_log; - Idx state_log_top; - /* Back reference cache. */ - Idx nbkref_ents; - Idx abkref_ents; - struct re_backref_cache_entry *bkref_ents; - int max_mb_elem_len; - Idx nsub_tops; - Idx asub_tops; - re_sub_match_top_t **sub_tops; -} re_match_context_t; - -typedef struct -{ - re_dfastate_t **sifted_states; - re_dfastate_t **limited_states; - Idx last_node; - Idx last_str_idx; - re_node_set limits; -} re_sift_context_t; - -struct re_fail_stack_ent_t -{ - Idx idx; - Idx node; - regmatch_t *regs; - re_node_set eps_via_nodes; -}; - -struct re_fail_stack_t -{ - Idx num; - Idx alloc; - struct re_fail_stack_ent_t *stack; -}; - -struct re_dfa_t -{ - re_token_t *nodes; - size_t nodes_alloc; - size_t nodes_len; - Idx *nexts; - Idx *org_indices; - re_node_set *edests; - re_node_set *eclosures; - re_node_set *inveclosures; - struct re_state_table_entry *state_table; - re_dfastate_t *init_state; - re_dfastate_t *init_state_word; - re_dfastate_t *init_state_nl; - re_dfastate_t *init_state_begbuf; - bin_tree_t *str_tree; - bin_tree_storage_t *str_tree_storage; - re_bitset_ptr_t sb_char; - int str_tree_storage_idx; - - /* number of subexpressions 're_nsub' is in regex_t. */ - re_hashval_t state_hash_mask; - Idx init_node; - Idx nbackref; /* The number of backreference in this dfa. */ - - /* Bitmap expressing which backreference is used. */ - bitset_word_t used_bkref_map; - bitset_word_t completed_bkref_map; - - unsigned int has_plural_match : 1; - /* If this dfa has "multibyte node", which is a backreference or - a node which can accept multibyte character or multi character - collating element. */ - unsigned int has_mb_node : 1; - unsigned int is_utf8 : 1; - unsigned int map_notascii : 1; - unsigned int word_ops_used : 1; - int mb_cur_max; - bitset_t word_char; - reg_syntax_t syntax; - Idx *subexp_map; -#ifdef DEBUG - char* re_str; -#endif - lock_define (lock) -}; - -#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) -#define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -#define re_node_set_empty(p) ((p)->nelem = 0) -#define re_node_set_free(set) re_free ((set)->elems) - - -typedef enum -{ - SB_CHAR, - MB_CHAR, - EQUIV_CLASS, - COLL_SYM, - CHAR_CLASS -} bracket_elem_type; - -typedef struct -{ - bracket_elem_type type; - union - { - unsigned char ch; - unsigned char *name; - wchar_t wch; - } opr; -} bracket_elem_t; - - -/* Functions for bitset_t operation. */ - -static inline void -bitset_set (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; -} - -static inline void -bitset_clear (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); -} - -static inline bool -bitset_contain (const bitset_t set, Idx i) -{ - return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; -} - -static inline void -bitset_empty (bitset_t set) -{ - memset (set, '\0', sizeof (bitset_t)); -} - -static inline void -bitset_set_all (bitset_t set) -{ - memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; -} - -static inline void -bitset_copy (bitset_t dest, const bitset_t src) -{ - memcpy (dest, src, sizeof (bitset_t)); -} - -static inline void -bitset_not (bitset_t set) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) - set[bitset_i] = ~set[bitset_i]; - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) - & ~set[BITSET_WORDS - 1]); -} - -static inline void -bitset_merge (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] |= src[bitset_i]; -} - -static inline void -bitset_mask (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] &= src[bitset_i]; -} - -/* Functions for re_string. */ -static int -__attribute__ ((pure, unused)) -re_string_char_size_at (const re_string_t *pstr, Idx idx) -{ - int byte_idx; - if (pstr->mb_cur_max == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) - break; - return byte_idx; -} - -static wint_t -__attribute__ ((pure, unused)) -re_string_wchar_at (const re_string_t *pstr, Idx idx) -{ - if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; -} - -#ifdef _LIBC -# include -#endif - -static int -__attribute__ ((pure, unused)) -re_string_elem_size_at (const re_string_t *pstr, Idx idx) -{ -#ifdef _LIBC - const unsigned char *p, *extra; - const int32_t *table, *indirect; - uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - - if (nrules != 0) - { - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - p = pstr->mbs + idx; - findidx (table, indirect, extra, &p, pstr->len - idx); - return p - pstr->mbs - idx; - } -#endif /* _LIBC */ - - return 1; -} - -#ifdef _LIBC -# if __GNUC__ >= 7 -# define FALLTHROUGH __attribute__ ((__fallthrough__)) -# else -# define FALLTHROUGH ((void) 0) -# endif -#else -# include "attribute.h" -#endif - -#endif /* _REGEX_INTERNAL_H */ diff --git a/xcompile/lib/regexec.c b/xcompile/lib/regexec.c deleted file mode 100644 index 13e0349e727..00000000000 --- a/xcompile/lib/regexec.c +++ /dev/null @@ -1,4221 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - Idx n); -static void match_ctx_clean (re_match_context_t *mctx); -static void match_ctx_free (re_match_context_t *cache); -static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, - Idx str_idx, Idx from, Idx to); -static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx); -static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, - Idx str_idx); -static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, - Idx node, Idx str_idx); -static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, - Idx last_str_idx); -static reg_errcode_t re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags); -static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, - struct re_registers *regs, - Idx stop, bool ret_len); -static regoff_t re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, Idx start, - regoff_t range, Idx stop, - struct re_registers *regs, - bool ret_len); -static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated); -static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx); -static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first); -static Idx check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx); -static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, - Idx cur_idx, Idx nmatch); -static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, - Idx str_idx, Idx dest_node, Idx nregs, - regmatch_t *regs, regmatch_t *prevregs, - re_node_set *eps_via_nodes); -static reg_errcode_t set_regs (const regex_t *preg, - const re_match_context_t *mctx, - size_t nmatch, regmatch_t *pmatch, - bool fl_backtrack); -static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs); - -static int sift_states_iter_mb (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx); -static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, - re_sift_context_t *sctx); -static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *cur_dest); -static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, - re_node_set *dest_nodes); -static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates); -static bool check_dst_limits (const re_match_context_t *mctx, - const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, - Idx src_idx); -static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, - int boundaries, Idx subexp_idx, - Idx from_node, Idx bkref_idx); -static int check_dst_limits_calc_pos (const re_match_context_t *mctx, - Idx limit, Idx subexp_idx, - Idx node, Idx str_idx, - Idx bkref_idx); -static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates, - re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, - Idx str_idx); -static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates); -static reg_errcode_t merge_state_array (const re_dfa_t *dfa, - re_dfastate_t **dst, - re_dfastate_t **src, Idx num); -static re_dfastate_t *find_recover_state (reg_errcode_t *err, - re_match_context_t *mctx); -static re_dfastate_t *transit_state (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *state); -static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *next_state); -static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, - re_node_set *cur_nodes, - Idx str_idx); -#if 0 -static re_dfastate_t *transit_state_sb (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *pstate); -#endif -static reg_errcode_t transit_state_mb (re_match_context_t *mctx, - re_dfastate_t *pstate); -static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, - const re_node_set *nodes); -static reg_errcode_t get_subexp (re_match_context_t *mctx, - Idx bkref_node, Idx bkref_str_idx); -static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, - const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, - Idx bkref_node, Idx bkref_str); -static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type); -static reg_errcode_t check_arrival (re_match_context_t *mctx, - state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, - int type); -static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, - Idx str_idx, - re_node_set *cur_nodes, - re_node_set *next_nodes); -static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, - re_node_set *cur_nodes, - Idx ex_subexp, int type); -static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, - re_node_set *dst_nodes, - Idx target, Idx ex_subexp, - int type); -static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, - re_node_set *cur_nodes, Idx cur_str, - Idx subexp_num, int type); -static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state); -static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx idx); -#ifdef _LIBC -static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len); -#endif -static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, - re_node_set *states_node, - bitset_t *states_ch); -static bool check_node_accept (const re_match_context_t *mctx, - const re_token_t *node, Idx idx); -static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len); - -/* Entry point for POSIX code. */ - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - 'regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies "execution flags" which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if - EFLAGS is invalid. */ - -int -regexec (const regex_t *__restrict preg, const char *__restrict string, - size_t nmatch, regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) -{ - reg_errcode_t err; - Idx start, length; - re_dfa_t *dfa = preg->buffer; - - if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) - return REG_BADPAT; - - if (eflags & REG_STARTEND) - { - start = pmatch[0].rm_so; - length = pmatch[0].rm_eo; - } - else - { - start = 0; - length = strlen (string); - } - - lock_lock (dfa->lock); - if (preg->no_sub) - err = re_search_internal (preg, string, length, start, length, - length, 0, NULL, eflags); - else - err = re_search_internal (preg, string, length, start, length, - length, nmatch, pmatch, eflags); - lock_unlock (dfa->lock); - return err != REG_NOERROR; -} - -#ifdef _LIBC -libc_hidden_def (__regexec) - -# include -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -__typeof__ (__regexec) __compat_regexec; - -int -attribute_compat_text_section -__compat_regexec (const regex_t *__restrict preg, - const char *__restrict string, size_t nmatch, - regmatch_t pmatch[_REGEX_NELTS (nmatch)], int eflags) -{ - return regexec (preg, string, nmatch, pmatch, - eflags & (REG_NOTBOL | REG_NOTEOL)); -} -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -# endif -#endif - -/* Entry points for GNU code. */ - -/* re_match, re_search, re_match_2, re_search_2 - - The former two functions operate on STRING with length LENGTH, - while the later two operate on concatenation of STRING1 and STRING2 - with lengths LENGTH1 and LENGTH2, respectively. - - re_match() matches the compiled pattern in BUFP against the string, - starting at index START. - - re_search() first tries matching at index START, then it tries to match - starting from index START + 1, and so on. The last start position tried - is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same - way as re_match().) - - The parameter STOP of re_{match,search}_2 specifies that no match exceeding - the first STOP characters of the concatenation of the strings should be - concerned. - - If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stored in REGS. (For the "_2" variants, the offsets are - computed relative to the concatenation, not relative to the individual - strings.) - - On success, re_match* functions return the length of the match, re_search* - return the position of the start of the match. They return -1 on - match failure, -2 on error. */ - -regoff_t -re_match (struct re_pattern_buffer *bufp, const char *string, Idx length, - Idx start, struct re_registers *regs) -{ - return re_search_stub (bufp, string, length, start, 0, length, regs, true); -} -#ifdef _LIBC -weak_alias (__re_match, re_match) -#endif - -regoff_t -re_search (struct re_pattern_buffer *bufp, const char *string, Idx length, - Idx start, regoff_t range, struct re_registers *regs) -{ - return re_search_stub (bufp, string, length, start, range, length, regs, - false); -} -#ifdef _LIBC -weak_alias (__re_search, re_search) -#endif - -regoff_t -re_match_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, - const char *string2, Idx length2, Idx start, - struct re_registers *regs, Idx stop) -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, 0, regs, stop, true); -} -#ifdef _LIBC -weak_alias (__re_match_2, re_match_2) -#endif - -regoff_t -re_search_2 (struct re_pattern_buffer *bufp, const char *string1, Idx length1, - const char *string2, Idx length2, Idx start, regoff_t range, - struct re_registers *regs, Idx stop) -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, range, regs, stop, false); -} -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) -#endif - -static regoff_t -re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, - Idx length1, const char *string2, Idx length2, Idx start, - regoff_t range, struct re_registers *regs, - Idx stop, bool ret_len) -{ - const char *str; - regoff_t rval; - Idx len; - char *s = NULL; - - if (__glibc_unlikely ((length1 < 0 || length2 < 0 || stop < 0 - || INT_ADD_WRAPV (length1, length2, &len)))) - return -2; - - /* Concatenate the strings. */ - if (length2 > 0) - if (length1 > 0) - { - s = re_malloc (char, len); - - if (__glibc_unlikely (s == NULL)) - return -2; -#ifdef _LIBC - memcpy (__mempcpy (s, string1, length1), string2, length2); -#else - memcpy (s, string1, length1); - memcpy (s + length1, string2, length2); -#endif - str = s; - } - else - str = string2; - else - str = string1; - - rval = re_search_stub (bufp, str, len, start, range, stop, regs, - ret_len); - re_free (s); - return rval; -} - -/* The parameters have the same meaning as those of re_search. - Additional parameters: - If RET_LEN is true the length of the match is returned (re_match style); - otherwise the position of the match is returned. */ - -static regoff_t -re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length, - Idx start, regoff_t range, Idx stop, struct re_registers *regs, - bool ret_len) -{ - reg_errcode_t result; - regmatch_t *pmatch; - Idx nregs; - regoff_t rval; - int eflags = 0; - re_dfa_t *dfa = bufp->buffer; - Idx last_start = start + range; - - /* Check for out-of-range. */ - if (__glibc_unlikely (start < 0 || start > length)) - return -1; - if (__glibc_unlikely (length < last_start - || (0 <= range && last_start < start))) - last_start = length; - else if (__glibc_unlikely (last_start < 0 - || (range < 0 && start <= last_start))) - last_start = 0; - - lock_lock (dfa->lock); - - eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; - eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; - - /* Compile fastmap if we haven't yet. */ - if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - if (__glibc_unlikely (bufp->no_sub)) - regs = NULL; - - /* We need at least 1 register. */ - if (regs == NULL) - nregs = 1; - else if (__glibc_unlikely (bufp->regs_allocated == REGS_FIXED - && regs->num_regs <= bufp->re_nsub)) - { - nregs = regs->num_regs; - if (__glibc_unlikely (nregs < 1)) - { - /* Nothing can be copied to regs. */ - regs = NULL; - nregs = 1; - } - } - else - nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); - if (__glibc_unlikely (pmatch == NULL)) - { - rval = -2; - goto out; - } - - result = re_search_internal (bufp, string, length, start, last_start, stop, - nregs, pmatch, eflags); - - rval = 0; - - /* I hope we needn't fill their regs with -1's when no match was found. */ - if (result != REG_NOERROR) - rval = result == REG_NOMATCH ? -1 : -2; - else if (regs != NULL) - { - /* If caller wants register contents data back, copy them. */ - bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, - bufp->regs_allocated); - if (__glibc_unlikely (bufp->regs_allocated == REGS_UNALLOCATED)) - rval = -2; - } - - if (__glibc_likely (rval == 0)) - { - if (ret_len) - { - DEBUG_ASSERT (pmatch[0].rm_so == start); - rval = pmatch[0].rm_eo - start; - } - else - rval = pmatch[0].rm_so; - } - re_free (pmatch); - out: - lock_unlock (dfa->lock); - return rval; -} - -static unsigned -re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, - int regs_allocated) -{ - int rval = REGS_REALLOCATE; - Idx i; - Idx need_regs = nregs + 1; - /* We need one extra element beyond 'num_regs' for the '-1' marker GNU code - uses. */ - - /* Have the register data arrays been allocated? */ - if (regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. */ - regs->start = re_malloc (regoff_t, need_regs); - if (__glibc_unlikely (regs->start == NULL)) - return REGS_UNALLOCATED; - regs->end = re_malloc (regoff_t, need_regs); - if (__glibc_unlikely (regs->end == NULL)) - { - re_free (regs->start); - return REGS_UNALLOCATED; - } - regs->num_regs = need_regs; - } - else if (regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (__glibc_unlikely (need_regs > regs->num_regs)) - { - regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); - regoff_t *new_end; - if (__glibc_unlikely (new_start == NULL)) - return REGS_UNALLOCATED; - new_end = re_realloc (regs->end, regoff_t, need_regs); - if (__glibc_unlikely (new_end == NULL)) - { - re_free (new_start); - return REGS_UNALLOCATED; - } - regs->start = new_start; - regs->end = new_end; - regs->num_regs = need_regs; - } - } - else - { - DEBUG_ASSERT (regs_allocated == REGS_FIXED); - /* This function may not be called with REGS_FIXED and nregs too big. */ - DEBUG_ASSERT (nregs <= regs->num_regs); - rval = REGS_FIXED; - } - - /* Copy the regs. */ - for (i = 0; i < nregs; ++i) - { - regs->start[i] = pmatch[i].rm_so; - regs->end[i] = pmatch[i].rm_eo; - } - for ( ; i < regs->num_regs; ++i) - regs->start[i] = regs->end[i] = -1; - - return rval; -} - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, - __re_size_t num_regs, regoff_t *starts, regoff_t *ends) -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = NULL; - } -} -#ifdef _LIBC -weak_alias (__re_set_registers, re_set_registers) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC -int -# ifdef _LIBC -weak_function -# endif -re_exec (const char *s) -{ - return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); -} -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. */ - -/* Searches for a compiled pattern PREG in the string STRING, whose - length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same - meaning as with regexec. LAST_START is START + RANGE, where - START and RANGE have the same meaning as with re_search. - Return REG_NOERROR if we find a match, and REG_NOMATCH if not, - otherwise return the error code. - Note: We assume front end functions already check ranges. - (0 <= LAST_START && LAST_START <= LENGTH) */ - -static reg_errcode_t -__attribute_warn_unused_result__ -re_search_internal (const regex_t *preg, const char *string, Idx length, - Idx start, Idx last_start, Idx stop, size_t nmatch, - regmatch_t pmatch[], int eflags) -{ - reg_errcode_t err; - const re_dfa_t *dfa = preg->buffer; - Idx left_lim, right_lim; - int incr; - bool fl_longest_match; - int match_kind; - Idx match_first; - Idx match_last = -1; - Idx extra_nmatch; - bool sb; - int ch; - re_match_context_t mctx = { .dfa = dfa }; - char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate - && start != last_start && !preg->can_be_null) - ? preg->fastmap : NULL); - RE_TRANSLATE_TYPE t = preg->translate; - - extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; - nmatch -= extra_nmatch; - - /* Check if the DFA haven't been compiled. */ - if (__glibc_unlikely (preg->used == 0 || dfa->init_state == NULL - || dfa->init_state_word == NULL - || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL)) - return REG_NOMATCH; - - /* We assume front-end functions already check them. */ - DEBUG_ASSERT (0 <= last_start && last_start <= length); - - /* If initial states with non-begbuf contexts have no elements, - the regex must be anchored. If preg->newline_anchor is set, - we'll never use init_state_nl, so do not check it. */ - if (dfa->init_state->nodes.nelem == 0 - && dfa->init_state_word->nodes.nelem == 0 - && (dfa->init_state_nl->nodes.nelem == 0 - || !preg->newline_anchor)) - { - if (start != 0 && last_start != 0) - return REG_NOMATCH; - start = last_start = 0; - } - - /* We must check the longest matching, if nmatch > 0. */ - fl_longest_match = (nmatch != 0 || dfa->nbackref); - - err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, - preg->translate, (preg->syntax & RE_ICASE) != 0, - dfa); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - mctx.input.stop = stop; - mctx.input.raw_stop = stop; - mctx.input.newline_anchor = preg->newline_anchor; - - err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - - /* We will log all the DFA states through which the dfa pass, - if nmatch > 1, or this dfa has "multibyte node", which is a - back-reference or a node which can accept multibyte character or - multi character collating element. */ - if (nmatch > 1 || dfa->has_mb_node) - { - /* Avoid overflow. */ - if (__glibc_unlikely ((MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) - <= mctx.input.bufs_len))) - { - err = REG_ESPACE; - goto free_return; - } - - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); - if (__glibc_unlikely (mctx.state_log == NULL)) - { - err = REG_ESPACE; - goto free_return; - } - } - - match_first = start; - mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - - /* Check incrementally whether the input string matches. */ - incr = (last_start < start) ? -1 : 1; - left_lim = (last_start < start) ? last_start : start; - right_lim = (last_start < start) ? start : last_start; - sb = dfa->mb_cur_max == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) - | (start <= last_start ? 2 : 0) - | (t != NULL ? 1 : 0)) - : 8); - - for (;; match_first += incr) - { - err = REG_NOMATCH; - if (match_first < left_lim || right_lim < match_first) - goto free_return; - - /* Advance as rapidly as possible through the string, until we - find a plausible place to start matching. This may be done - with varying efficiency, so there are various possibilities: - only the most common of them are specialized, in order to - save on code size. We use a switch statement for speed. */ - switch (match_kind) - { - case 8: - /* No fastmap. */ - break; - - case 7: - /* Fastmap with single-byte translation, match forward. */ - while (__glibc_likely (match_first < right_lim) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - goto forward_match_found_start_or_reached_end; - - case 6: - /* Fastmap without translation, match forward. */ - while (__glibc_likely (match_first < right_lim) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - - forward_match_found_start_or_reached_end: - if (__glibc_unlikely (match_first == right_lim)) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - goto free_return; - } - break; - - case 4: - case 5: - /* Fastmap without multi-byte translation, match backwards. */ - while (match_first >= left_lim) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - goto free_return; - break; - - default: - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer instead. */ - for (;;) - { - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - __re_size_t offset = match_first - mctx.input.raw_mbs_idx; - if (__glibc_unlikely (offset - >= (__re_size_t) mctx.input.valid_raw_len)) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - - offset = match_first - mctx.input.raw_mbs_idx; - } - /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */ - ch = (offset < mctx.input.valid_len - ? re_string_byte_at (&mctx.input, offset) : 0); - if (fastmap[ch]) - break; - match_first += incr; - if (match_first < left_lim || match_first > right_lim) - { - err = REG_NOMATCH; - goto free_return; - } - } - break; - } - - /* Reconstruct the buffers so that the matcher can assume that - the matching starts from the beginning of the buffer. */ - err = re_string_reconstruct (&mctx.input, match_first, eflags); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ - if (!sb && !re_string_first_byte (&mctx.input, 0)) - continue; - - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - start <= last_start ? &match_first : NULL); - if (match_last != -1) - { - if (__glibc_unlikely (match_last == -2)) - { - err = REG_ESPACE; - goto free_return; - } - else - { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (__glibc_unlikely (err != REG_NOMATCH)) - goto free_return; - match_last = -1; - } - else - break; /* We found a match. */ - } - } - - match_ctx_clean (&mctx); - } - - DEBUG_ASSERT (match_last != -1); - DEBUG_ASSERT (err == REG_NOERROR); - - /* Set pmatch[] if we need. */ - if (nmatch > 0) - { - Idx reg_idx; - - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; - - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ - - if (!preg->no_sub && nmatch > 1) - { - err = set_regs (preg, &mctx, nmatch, pmatch, - dfa->has_plural_match && dfa->nbackref > 0); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - - /* At last, add the offset to each register, since we slid - the buffers so that we could assume that the matching starts - from 0. */ - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so != -1) - { - if (__glibc_unlikely (mctx.input.offsets_needed != 0)) - { - pmatch[reg_idx].rm_so = - (pmatch[reg_idx].rm_so == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_so]); - pmatch[reg_idx].rm_eo = - (pmatch[reg_idx].rm_eo == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_eo]); - } - pmatch[reg_idx].rm_so += match_first; - pmatch[reg_idx].rm_eo += match_first; - } - for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) - { - pmatch[nmatch + reg_idx].rm_so = -1; - pmatch[nmatch + reg_idx].rm_eo = -1; - } - - if (dfa->subexp_map) - for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) - if (dfa->subexp_map[reg_idx] != reg_idx) - { - pmatch[reg_idx + 1].rm_so - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; - pmatch[reg_idx + 1].rm_eo - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; - } - } - - free_return: - re_free (mctx.state_log); - if (dfa->nbackref) - match_ctx_free (&mctx); - re_string_destruct (&mctx.input); - return err; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -prune_impossible_nodes (re_match_context_t *mctx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx halt_node, match_last; - reg_errcode_t ret; - re_dfastate_t **sifted_states; - re_dfastate_t **lim_states = NULL; - re_sift_context_t sctx; - DEBUG_ASSERT (mctx->state_log != NULL); - match_last = mctx->match_last; - halt_node = mctx->last_node; - - /* Avoid overflow. */ - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) - <= match_last)) - return REG_ESPACE; - - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); - if (__glibc_unlikely (sifted_states == NULL)) - { - ret = REG_ESPACE; - goto free_return; - } - if (dfa->nbackref) - { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); - if (__glibc_unlikely (lim_states == NULL)) - { - ret = REG_ESPACE; - goto free_return; - } - while (1) - { - memset (lim_states, '\0', - sizeof (re_dfastate_t *) * (match_last + 1)); - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (__glibc_unlikely (ret != REG_NOERROR)) - goto free_return; - if (sifted_states[0] != NULL || lim_states[0] != NULL) - break; - do - { - --match_last; - if (match_last < 0) - { - ret = REG_NOMATCH; - goto free_return; - } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); - } - ret = merge_state_array (dfa, sifted_states, lim_states, - match_last + 1); - re_free (lim_states); - lim_states = NULL; - if (__glibc_unlikely (ret != REG_NOERROR)) - goto free_return; - } - else - { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (__glibc_unlikely (ret != REG_NOERROR)) - goto free_return; - if (sifted_states[0] == NULL) - { - ret = REG_NOMATCH; - goto free_return; - } - } - re_free (mctx->state_log); - mctx->state_log = sifted_states; - sifted_states = NULL; - mctx->last_node = halt_node; - mctx->match_last = match_last; - ret = REG_NOERROR; - free_return: - re_free (sifted_states); - re_free (lim_states); - return ret; -} - -/* Acquire an initial state and return it. - We must select appropriate initial state depending on the context, - since initial states may have constraints like "\<", "^", etc.. */ - -static __always_inline re_dfastate_t * -acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, - Idx idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (dfa->init_state->has_constraint) - { - unsigned int context; - context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return dfa->init_state_word; - else if (IS_ORDINARY_CONTEXT (context)) - return dfa->init_state; - else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_begbuf; - else if (IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_nl; - else if (IS_BEGBUF_CONTEXT (context)) - { - /* It is relatively rare case, then calculate on demand. */ - return re_acquire_state_context (err, dfa, - dfa->init_state->entrance_nodes, - context); - } - else - /* Must not happen? */ - return dfa->init_state; - } - else - return dfa->init_state; -} - -/* Check whether the regular expression match input string INPUT or not, - and return the index where the matching end. Return -1 if - there is no match, and return -2 in case of an error. - FL_LONGEST_MATCH means we want the POSIX longest matching. - If P_MATCH_FIRST is not NULL, and the match fails, it is set to the - next place where we may want to try matching. - Note that the matcher assumes that the matching starts from the current - index of the buffer. */ - -static Idx -__attribute_warn_unused_result__ -check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx match = 0; - Idx match_last = -1; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - re_dfastate_t *cur_state; - bool at_init_state = p_match_first != NULL; - Idx next_start_idx = cur_str_idx; - - err = REG_NOERROR; - cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); - /* An initial state must not be NULL (invalid). */ - if (__glibc_unlikely (cur_state == NULL)) - { - DEBUG_ASSERT (err == REG_ESPACE); - return -2; - } - - if (mctx->state_log != NULL) - { - mctx->state_log[cur_str_idx] = cur_state; - - /* Check OP_OPEN_SUBEXP in the initial state in case that we use them - later. E.g. Processing back references. */ - if (__glibc_unlikely (dfa->nbackref)) - { - at_init_state = false; - err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - if (cur_state->has_backref) - { - err = transit_state_bkref (mctx, &cur_state->nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - } - - /* If the RE accepts NULL string. */ - if (__glibc_unlikely (cur_state->halt)) - { - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, cur_str_idx)) - { - if (!fl_longest_match) - return cur_str_idx; - else - { - match_last = cur_str_idx; - match = 1; - } - } - } - - while (!re_string_eoi (&mctx->input)) - { - re_dfastate_t *old_state = cur_state; - Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - - if ((__glibc_unlikely (next_char_idx >= mctx->input.bufs_len) - && mctx->input.bufs_len < mctx->input.len) - || (__glibc_unlikely (next_char_idx >= mctx->input.valid_len) - && mctx->input.valid_len < mctx->input.len)) - { - err = extend_buffers (mctx, next_char_idx + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - { - DEBUG_ASSERT (err == REG_ESPACE); - return -2; - } - } - - cur_state = transit_state (&err, mctx, cur_state); - if (mctx->state_log != NULL) - cur_state = merge_state_with_log (&err, mctx, cur_state); - - if (cur_state == NULL) - { - /* Reached the invalid state or an error. Try to recover a valid - state using the state log, if available and if we have not - already found a valid (even if not the longest) match. */ - if (__glibc_unlikely (err != REG_NOERROR)) - return -2; - - if (mctx->state_log == NULL - || (match && !fl_longest_match) - || (cur_state = find_recover_state (&err, mctx)) == NULL) - break; - } - - if (__glibc_unlikely (at_init_state)) - { - if (old_state == cur_state) - next_start_idx = next_char_idx; - else - at_init_state = false; - } - - if (cur_state->halt) - { - /* Reached a halt state. - Check the halt state can satisfy the current context. */ - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, - re_string_cur_idx (&mctx->input))) - { - /* We found an appropriate halt state. */ - match_last = re_string_cur_idx (&mctx->input); - match = 1; - - /* We found a match, do not modify match_first below. */ - p_match_first = NULL; - if (!fl_longest_match) - break; - } - } - } - - if (p_match_first) - *p_match_first += next_start_idx; - - return match_last; -} - -/* Check NODE match the current context. */ - -static bool -check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) -{ - re_token_type_t type = dfa->nodes[node].type; - unsigned int constraint = dfa->nodes[node].constraint; - if (type != END_OF_RE) - return false; - if (!constraint) - return true; - if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) - return false; - return true; -} - -/* Check the halt state STATE match the current context. - Return 0 if not match, if the node, STATE has, is a halt node and - match the context, return the node. */ - -static Idx -check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) -{ - Idx i; - unsigned int context; - DEBUG_ASSERT (state->halt); - context = re_string_context_at (&mctx->input, idx, mctx->eflags); - for (i = 0; i < state->nodes.nelem; ++i) - if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) - return state->nodes.elems[i]; - return 0; -} - -/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA - corresponding to the DFA). - Return the destination node, and update EPS_VIA_NODES; - return -1 on match failure, -2 on error. */ - -static Idx -proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, - regmatch_t *prevregs, - Idx *pidx, Idx node, re_node_set *eps_via_nodes, - struct re_fail_stack_t *fs) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (IS_EPSILON_NODE (dfa->nodes[node].type)) - { - re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; - re_node_set *edests = &dfa->edests[node]; - - if (! re_node_set_contains (eps_via_nodes, node)) - { - bool ok = re_node_set_insert (eps_via_nodes, node); - if (__glibc_unlikely (! ok)) - return -2; - } - - /* Pick a valid destination, or return -1 if none is found. */ - Idx dest_node = -1; - for (Idx i = 0; i < edests->nelem; i++) - { - Idx candidate = edests->elems[i]; - if (!re_node_set_contains (cur_nodes, candidate)) - continue; - if (dest_node == -1) - dest_node = candidate; - - else - { - /* In order to avoid infinite loop like "(a*)*", return the second - epsilon-transition if the first was already considered. */ - if (re_node_set_contains (eps_via_nodes, dest_node)) - return candidate; - - /* Otherwise, push the second epsilon-transition on the fail stack. */ - else if (fs != NULL - && push_fail_stack (fs, *pidx, candidate, nregs, regs, - prevregs, eps_via_nodes)) - return -2; - - /* We know we are going to exit. */ - break; - } - } - return dest_node; - } - else - { - Idx naccepted = 0; - re_token_type_t type = dfa->nodes[node].type; - - if (dfa->nodes[node].accept_mb) - naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else if (type == OP_BACK_REF) - { - Idx subexp_idx = dfa->nodes[node].opr.idx + 1; - if (subexp_idx < nregs) - naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; - if (fs != NULL) - { - if (subexp_idx >= nregs - || regs[subexp_idx].rm_so == -1 - || regs[subexp_idx].rm_eo == -1) - return -1; - else if (naccepted) - { - char *buf = (char *) re_string_get_buffer (&mctx->input); - if (mctx->input.valid_len - *pidx < naccepted - || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, - naccepted) - != 0)) - return -1; - } - } - - if (naccepted == 0) - { - Idx dest_node; - bool ok = re_node_set_insert (eps_via_nodes, node); - if (__glibc_unlikely (! ok)) - return -2; - dest_node = dfa->edests[node].elems[0]; - if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node)) - return dest_node; - } - } - - if (naccepted != 0 - || check_node_accept (mctx, dfa->nodes + node, *pidx)) - { - Idx dest_node = dfa->nexts[node]; - *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; - if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL - || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node))) - return -1; - re_node_set_empty (eps_via_nodes); - return dest_node; - } - } - return -1; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, - Idx nregs, regmatch_t *regs, regmatch_t *prevregs, - re_node_set *eps_via_nodes) -{ - reg_errcode_t err; - Idx num = fs->num; - if (num == fs->alloc) - { - struct re_fail_stack_ent_t *new_array; - new_array = re_realloc (fs->stack, struct re_fail_stack_ent_t, - fs->alloc * 2); - if (new_array == NULL) - return REG_ESPACE; - fs->alloc *= 2; - fs->stack = new_array; - } - fs->stack[num].idx = str_idx; - fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs); - if (fs->stack[num].regs == NULL) - return REG_ESPACE; - fs->num = num + 1; - memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); - memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs); - err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); - return err; -} - -static Idx -pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, - regmatch_t *regs, regmatch_t *prevregs, - re_node_set *eps_via_nodes) -{ - if (fs == NULL || fs->num == 0) - return -1; - Idx num = --fs->num; - *pidx = fs->stack[num].idx; - memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); - memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs); - re_node_set_free (eps_via_nodes); - re_free (fs->stack[num].regs); - *eps_via_nodes = fs->stack[num].eps_via_nodes; - DEBUG_ASSERT (0 <= fs->stack[num].node); - return fs->stack[num].node; -} - - -#define DYNARRAY_STRUCT regmatch_list -#define DYNARRAY_ELEMENT regmatch_t -#define DYNARRAY_PREFIX regmatch_list_ -#include - -/* Set the positions where the subexpressions are starts/ends to registers - PMATCH. - Note: We assume that pmatch[0] is already set, and - pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, - regmatch_t *pmatch, bool fl_backtrack) -{ - const re_dfa_t *dfa = preg->buffer; - Idx idx, cur_node; - re_node_set eps_via_nodes; - struct re_fail_stack_t *fs; - struct re_fail_stack_t fs_body = { 0, 2, NULL }; - struct regmatch_list prev_match; - regmatch_list_init (&prev_match); - - DEBUG_ASSERT (nmatch > 1); - DEBUG_ASSERT (mctx->state_log != NULL); - if (fl_backtrack) - { - fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); - if (fs->stack == NULL) - return REG_ESPACE; - } - else - fs = NULL; - - cur_node = dfa->init_node; - re_node_set_init_empty (&eps_via_nodes); - - if (!regmatch_list_resize (&prev_match, nmatch)) - { - regmatch_list_free (&prev_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match); - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - - for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) - { - update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); - - if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node) - || (fs && re_node_set_contains (&eps_via_nodes, cur_node))) - { - Idx reg_idx; - cur_node = -1; - if (fs) - { - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) - { - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - prev_idx_match, &eps_via_nodes); - break; - } - } - if (cur_node < 0) - { - re_node_set_free (&eps_via_nodes); - regmatch_list_free (&prev_match); - return free_fail_stack_return (fs); - } - } - - /* Proceed to next node. */ - cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match, - &idx, cur_node, - &eps_via_nodes, fs); - - if (__glibc_unlikely (cur_node < 0)) - { - if (__glibc_unlikely (cur_node == -2)) - { - re_node_set_free (&eps_via_nodes); - regmatch_list_free (&prev_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - prev_idx_match, &eps_via_nodes); - if (cur_node < 0) - { - re_node_set_free (&eps_via_nodes); - regmatch_list_free (&prev_match); - free_fail_stack_return (fs); - return REG_NOMATCH; - } - } - } - re_node_set_free (&eps_via_nodes); - regmatch_list_free (&prev_match); - return free_fail_stack_return (fs); -} - -static reg_errcode_t -free_fail_stack_return (struct re_fail_stack_t *fs) -{ - if (fs) - { - Idx fs_idx; - for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) - { - re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); - re_free (fs->stack[fs_idx].regs); - } - re_free (fs->stack); - } - return REG_NOERROR; -} - -static void -update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) -{ - int type = dfa->nodes[cur_node].type; - if (type == OP_OPEN_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - - /* We are at the first node of this sub expression. */ - if (reg_num < nmatch) - { - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; - } - } - else if (type == OP_CLOSE_SUBEXP) - { - /* We are at the last node of this sub expression. */ - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - if (reg_num < nmatch) - { - if (pmatch[reg_num].rm_so < cur_idx) - { - pmatch[reg_num].rm_eo = cur_idx; - /* This is a non-empty match or we are not inside an optional - subexpression. Accept this right away. */ - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - } - else - { - if (dfa->nodes[cur_node].opt_subexp - && prev_idx_match[reg_num].rm_so != -1) - /* We transited through an empty match for an optional - subexpression, like (a?)*, and this is not the subexp's - first match. Copy back the old content of the registers - so that matches of an inner subexpression are undone as - well, like in ((a?))*. */ - memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); - else - /* We completed a subexpression, but it may be part of - an optional one, so do not update PREV_IDX_MATCH. */ - pmatch[reg_num].rm_eo = cur_idx; - } - } - } -} - -/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 - and sift the nodes in each states according to the following rules. - Updated state_log will be wrote to STATE_LOG. - - Rules: We throw away the Node 'a' in the STATE_LOG[STR_IDX] if... - 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If 'a' isn't the LAST_NODE and 'a' can't epsilon transit to - the LAST_NODE, we throw away the node 'a'. - 2. When 0 <= STR_IDX < MATCH_LAST and 'a' accepts - string 's' and transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node 'a'. - ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node 'a'. - 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node 'a'. - ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node 'a'. */ - -#define STATE_NODE_CONTAINS(state,node) \ - ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) - -static reg_errcode_t -sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) -{ - reg_errcode_t err; - int null_cnt = 0; - Idx str_idx = sctx->last_str_idx; - re_node_set cur_dest; - - DEBUG_ASSERT (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); - - /* Build sifted state_log[str_idx]. It has the nodes which can epsilon - transit to the last_node and the last_node itself. */ - err = re_node_set_init_1 (&cur_dest, sctx->last_node); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - - /* Then check each states in the state_log. */ - while (str_idx > 0) - { - /* Update counters. */ - null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; - if (null_cnt > mctx->max_mb_elem_len) - { - memset (sctx->sifted_states, '\0', - sizeof (re_dfastate_t *) * str_idx); - re_node_set_free (&cur_dest); - return REG_NOERROR; - } - re_node_set_empty (&cur_dest); - --str_idx; - - if (mctx->state_log[str_idx]) - { - err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - - /* Add all the nodes which satisfy the following conditions: - - It can epsilon transit to a node in CUR_DEST. - - It is in CUR_SRC. - And update state_log. */ - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - err = REG_NOERROR; - free_return: - re_node_set_free (&cur_dest); - return err; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, re_node_set *cur_dest) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; - Idx i; - - /* Then build the next sifted state. - We build the next sifted state on 'cur_dest', and update - 'sifted_states[str_idx]' with 'cur_dest'. - Note: - 'cur_dest' is the sifted state from 'state_log[str_idx + 1]'. - 'cur_src' points the node_set of the old 'state_log[str_idx]' - (with the epsilon nodes pre-filtered out). */ - for (i = 0; i < cur_src->nelem; i++) - { - Idx prev_node = cur_src->elems[i]; - int naccepted = 0; - bool ok; - DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type)); - - /* If the node may accept "multi byte". */ - if (dfa->nodes[prev_node].accept_mb) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); - - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - - if (sctx->limits.nelem) - { - Idx to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ok = re_node_set_insert (cur_dest, prev_node); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - - return REG_NOERROR; -} - -/* Helper functions. */ - -static reg_errcode_t -clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) -{ - Idx top = mctx->state_log_top; - - if ((next_state_log_idx >= mctx->input.bufs_len - && mctx->input.bufs_len < mctx->input.len) - || (next_state_log_idx >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) - { - reg_errcode_t err; - err = extend_buffers (mctx, next_state_log_idx + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - - if (top < next_state_log_idx) - { - DEBUG_ASSERT (mctx->state_log != NULL); - memset (mctx->state_log + top + 1, '\0', - sizeof (re_dfastate_t *) * (next_state_log_idx - top)); - mctx->state_log_top = next_state_log_idx; - } - return REG_NOERROR; -} - -static reg_errcode_t -merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, - re_dfastate_t **src, Idx num) -{ - Idx st_idx; - reg_errcode_t err; - for (st_idx = 0; st_idx < num; ++st_idx) - { - if (dst[st_idx] == NULL) - dst[st_idx] = src[st_idx]; - else if (src[st_idx] != NULL) - { - re_node_set merged_set; - err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, - &src[st_idx]->nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); - re_node_set_free (&merged_set); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *dest_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? NULL - : &mctx->state_log[str_idx]->nodes); - - if (dest_nodes->nelem == 0) - sctx->sifted_states[str_idx] = NULL; - else - { - if (candidates) - { - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - /* Then, check the limitations in the current sift_context. */ - if (sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - - if (candidates && mctx->state_log[str_idx]->has_backref) - { - err = sift_states_bkref (mctx, sctx, str_idx, candidates); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - reg_errcode_t err = REG_NOERROR; - Idx i; - - re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - if (!state->inveclosure.alloc) - { - err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); - if (__glibc_unlikely (err != REG_NOERROR)) - return REG_ESPACE; - for (i = 0; i < dest_nodes->nelem; i++) - { - err = re_node_set_merge (&state->inveclosure, - dfa->inveclosures + dest_nodes->elems[i]); - if (__glibc_unlikely (err != REG_NOERROR)) - return REG_ESPACE; - } - } - return re_node_set_add_intersect (dest_nodes, candidates, - &state->inveclosure); -} - -static reg_errcode_t -sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - Idx ecl_idx; - reg_errcode_t err; - re_node_set *inv_eclosure = dfa->inveclosures + node; - re_node_set except_nodes; - re_node_set_init_empty (&except_nodes); - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (cur_node == node) - continue; - if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) - { - Idx edst1 = dfa->edests[cur_node].elems[0]; - Idx edst2 = ((dfa->edests[cur_node].nelem > 1) - ? dfa->edests[cur_node].elems[1] : -1); - if ((!re_node_set_contains (inv_eclosure, edst1) - && re_node_set_contains (dest_nodes, edst1)) - || (edst2 > 0 - && !re_node_set_contains (inv_eclosure, edst2) - && re_node_set_contains (dest_nodes, edst2))) - { - err = re_node_set_add_intersect (&except_nodes, candidates, - dfa->inveclosures + cur_node); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&except_nodes); - return err; - } - } - } - } - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (!re_node_set_contains (&except_nodes, cur_node)) - { - Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; - re_node_set_remove_at (dest_nodes, idx); - } - } - re_node_set_free (&except_nodes); - return REG_NOERROR; -} - -static bool -check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx lim_idx, src_pos, dst_pos; - - Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); - Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = mctx->bkref_ents + limits->elems[lim_idx]; - subexp_idx = dfa->nodes[ent->node].opr.idx; - - dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, dst_node, dst_idx, - dst_bkref_idx); - src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, src_node, src_idx, - src_bkref_idx); - - /* In case of: - ( ) - ( ) - ( ) */ - if (src_pos == dst_pos) - continue; /* This is unrelated limitation. */ - else - return true; - } - return false; -} - -static int -check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, - Idx subexp_idx, Idx from_node, Idx bkref_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *eclosures = dfa->eclosures + from_node; - Idx node_idx; - - /* Else, we are on the boundary: examine the nodes on the epsilon - closure. */ - for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) - { - Idx node = eclosures->elems[node_idx]; - switch (dfa->nodes[node].type) - { - case OP_BACK_REF: - if (bkref_idx != -1) - { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; - do - { - Idx dst; - int cpos; - - if (ent->node != node) - continue; - - if (subexp_idx < BITSET_WORD_BITS - && !(ent->eps_reachable_subexps_map - & ((bitset_word_t) 1 << subexp_idx))) - continue; - - /* Recurse trying to reach the OP_OPEN_SUBEXP and - OP_CLOSE_SUBEXP cases below. But, if the - destination node is the same node as the source - node, don't recurse because it would cause an - infinite loop: a regex that exhibits this behavior - is ()\1*\1* */ - dst = dfa->edests[node].elems[0]; - if (dst == from_node) - { - if (boundaries & 1) - return -1; - else /* if (boundaries & 2) */ - return 0; - } - - cpos = - check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - dst, bkref_idx); - if (cpos == -1 /* && (boundaries & 1) */) - return -1; - if (cpos == 0 && (boundaries & 2)) - return 0; - - if (subexp_idx < BITSET_WORD_BITS) - ent->eps_reachable_subexps_map - &= ~((bitset_word_t) 1 << subexp_idx); - } - while (ent++->more); - } - break; - - case OP_OPEN_SUBEXP: - if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) - return -1; - break; - - case OP_CLOSE_SUBEXP: - if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) - return 0; - break; - - default: - break; - } - } - - return (boundaries & 2) ? 1 : 0; -} - -static int -check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, - Idx subexp_idx, Idx from_node, Idx str_idx, - Idx bkref_idx) -{ - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; - int boundaries; - - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - boundaries = (str_idx == lim->subexp_from); - boundaries |= (str_idx == lim->subexp_to) << 1; - if (boundaries == 0) - return 0; - - /* Else, examine epsilon closure. */ - return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - from_node, bkref_idx); -} - -/* Check the limitations of sub expressions LIMITS, and remove the nodes - which are against limitations from DEST_NODES. */ - -static reg_errcode_t -check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates, re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, Idx str_idx) -{ - reg_errcode_t err; - Idx node_idx, lim_idx; - - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = bkref_ents + limits->elems[lim_idx]; - - if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) - continue; /* This is unrelated limitation. */ - - subexp_idx = dfa->nodes[ent->node].opr.idx; - if (ent->subexp_to == str_idx) - { - Idx ops_node = -1; - Idx cls_node = -1; - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_OPEN_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - ops_node = node; - else if (type == OP_CLOSE_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - cls_node = node; - } - - /* Check the limitation of the open subexpression. */ - /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ - if (ops_node >= 0) - { - err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, - candidates); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - - /* Check the limitation of the close subexpression. */ - if (cls_node >= 0) - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - if (!re_node_set_contains (dfa->inveclosures + node, - cls_node) - && !re_node_set_contains (dfa->eclosures + node, - cls_node)) - { - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - --node_idx; - } - } - } - else /* (ent->subexp_to != str_idx) */ - { - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) - { - if (subexp_idx != dfa->nodes[node].opr.idx) - continue; - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - } - } - return REG_NOERROR; -} - -static reg_errcode_t -__attribute_warn_unused_result__ -sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx node_idx, node; - re_sift_context_t local_sctx; - Idx first_idx = search_cur_bkref_entry (mctx, str_idx); - - if (first_idx == -1) - return REG_NOERROR; - - local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ - - for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) - { - Idx enabled_idx; - re_token_type_t type; - struct re_backref_cache_entry *entry; - node = candidates->elems[node_idx]; - type = dfa->nodes[node].type; - /* Avoid infinite loop for the REs like "()\1+". */ - if (node == sctx->last_node && str_idx == sctx->last_str_idx) - continue; - if (type != OP_BACK_REF) - continue; - - entry = mctx->bkref_ents + first_idx; - enabled_idx = first_idx; - do - { - Idx subexp_len; - Idx to_idx; - Idx dst_node; - bool ok; - re_dfastate_t *cur_state; - - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - ok = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (__glibc_unlikely (! ok)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - - /* mctx->bkref_ents may have changed, reload the pointer. */ - entry = mctx->bkref_ents + enabled_idx; - } - while (enabled_idx++, entry++->more); - } - err = REG_NOERROR; - free_return: - if (local_sctx.sifted_states != NULL) - { - re_node_set_free (&local_sctx.limits); - } - - return err; -} - - -static int -sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int naccepted; - /* Check the node can accept "multi byte". */ - naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); - if (naccepted > 0 && str_idx + naccepted <= max_str_idx - && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], - dfa->nexts[node_idx])) - /* The node can't accept the "multi byte", or the - destination was already thrown away, then the node - couldn't accept the current input "multi byte". */ - naccepted = 0; - /* Otherwise, it is sure that the node could accept - 'naccepted' bytes input. */ - return naccepted; -} - -/* Functions for state transition. */ - -/* Return the next state to which the current state STATE will transit by - accepting the current input byte, and update STATE_LOG if necessary. - Return NULL on failure. - If STATE can accept a multibyte char/collating element/back reference - update the destination of STATE_LOG. */ - -static re_dfastate_t * -__attribute_warn_unused_result__ -transit_state (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - re_dfastate_t **trtable; - unsigned char ch; - - /* If the current state can accept multibyte. */ - if (__glibc_unlikely (state->accept_mb)) - { - *err = transit_state_mb (mctx, state); - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - } - - /* Then decide the next state with the single byte. */ -#if 0 - if (0) - /* don't use transition table */ - return transit_state_sb (err, mctx, state); -#endif - - /* Use transition table */ - ch = re_string_fetch_byte (&mctx->input); - for (;;) - { - trtable = state->trtable; - if (__glibc_likely (trtable != NULL)) - return trtable[ch]; - - trtable = state->word_trtable; - if (__glibc_likely (trtable != NULL)) - { - unsigned int context; - context - = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return trtable[ch + SBC_MAX]; - else - return trtable[ch]; - } - - if (!build_trtable (mctx->dfa, state)) - { - *err = REG_ESPACE; - return NULL; - } - - /* Retry, we now have a transition table. */ - } -} - -/* Update the state_log if we need */ -static re_dfastate_t * -merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *next_state) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx cur_idx = re_string_cur_idx (&mctx->input); - - if (cur_idx > mctx->state_log_top) - { - mctx->state_log[cur_idx] = next_state; - mctx->state_log_top = cur_idx; - } - else if (mctx->state_log[cur_idx] == 0) - { - mctx->state_log[cur_idx] = next_state; - } - else - { - re_dfastate_t *pstate; - unsigned int context; - re_node_set next_nodes, *log_nodes, *table_nodes = NULL; - /* If (state_log[cur_idx] != 0), it implies that cur_idx is - the destination of a multibyte char/collating element/ - back reference. Then the next state is the union set of - these destinations and the results of the transition table. */ - pstate = mctx->state_log[cur_idx]; - log_nodes = pstate->entrance_nodes; - if (next_state != NULL) - { - table_nodes = next_state->entrance_nodes; - *err = re_node_set_init_union (&next_nodes, table_nodes, - log_nodes); - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - } - else - next_nodes = *log_nodes; - /* Note: We already add the nodes of the initial state, - then we don't need to add them here. */ - - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - next_state = mctx->state_log[cur_idx] - = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - if (table_nodes != NULL) - re_node_set_free (&next_nodes); - } - - if (__glibc_unlikely (dfa->nbackref) && next_state != NULL) - { - /* Check OP_OPEN_SUBEXP in the current state in case that we use them - later. We must check them here, since the back references in the - next state might use them. */ - *err = check_subexp_matching_top (mctx, &next_state->nodes, - cur_idx); - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - - /* If the next state has back references. */ - if (next_state->has_backref) - { - *err = transit_state_bkref (mctx, &next_state->nodes); - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - next_state = mctx->state_log[cur_idx]; - } - } - - return next_state; -} - -/* Skip bytes in the input that correspond to part of a - multi-byte match, then look in the log for a state - from which to restart matching. */ -static re_dfastate_t * -find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) -{ - re_dfastate_t *cur_state; - do - { - Idx max = mctx->state_log_top; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - do - { - if (++cur_str_idx > max) - return NULL; - re_string_skip_bytes (&mctx->input, 1); - } - while (mctx->state_log[cur_str_idx] == NULL); - - cur_state = merge_state_with_log (err, mctx, NULL); - } - while (*err == REG_NOERROR && cur_state == NULL); - return cur_state; -} - -/* Helper functions for transit_state. */ - -/* From the node set CUR_NODES, pick up the nodes whose types are - OP_OPEN_SUBEXP and which have corresponding back references in the regular - expression. And register them to use them later for evaluating the - corresponding back references. */ - -static reg_errcode_t -check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx node_idx; - reg_errcode_t err; - - /* TODO: This isn't efficient. - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) - { - Idx node = cur_nodes->elems[node_idx]; - if (dfa->nodes[node].type == OP_OPEN_SUBEXP - && dfa->nodes[node].opr.idx < BITSET_WORD_BITS - && (dfa->used_bkref_map - & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) - { - err = match_ctx_add_subtop (mctx, node, str_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - return REG_NOERROR; -} - -#if 0 -/* Return the next state to which the current state STATE will transit by - accepting the current input byte. Return NULL on failure. */ - -static re_dfastate_t * -transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - const re_dfa_t *const dfa = mctx->dfa; - re_node_set next_nodes; - re_dfastate_t *next_state; - Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); - unsigned int context; - - *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); - if (__glibc_unlikely (*err != REG_NOERROR)) - return NULL; - for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) - { - Idx cur_node = state->nodes.elems[node_cnt]; - if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) - { - *err = re_node_set_merge (&next_nodes, - dfa->eclosures + dfa->nexts[cur_node]); - if (__glibc_unlikely (*err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return NULL; - } - } - } - context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); - next_state = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - re_node_set_free (&next_nodes); - re_string_skip_bytes (&mctx->input, 1); - return next_state; -} -#endif - -static reg_errcode_t -transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - - for (i = 0; i < pstate->nodes.nelem; ++i) - { - re_node_set dest_nodes, *new_nodes; - Idx cur_node_idx = pstate->nodes.elems[i]; - int naccepted; - Idx dest_idx; - unsigned int context; - re_dfastate_t *dest_state; - - if (!dfa->nodes[cur_node_idx].accept_mb) - continue; - - if (dfa->nodes[cur_node_idx].constraint) - { - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input), - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, - context)) - continue; - } - - /* How many bytes the node can accept? */ - naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, - re_string_cur_idx (&mctx->input)); - if (naccepted == 0) - continue; - - /* The node can accepts 'naccepted' bytes. */ - dest_idx = re_string_cur_idx (&mctx->input) + naccepted; - mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted - : mctx->max_mb_elem_len); - err = clean_state_log_if_needed (mctx, dest_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - DEBUG_ASSERT (dfa->nexts[cur_node_idx] != -1); - new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; - - dest_state = mctx->state_log[dest_idx]; - if (dest_state == NULL) - dest_nodes = *new_nodes; - else - { - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, new_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - context = re_string_context_at (&mctx->input, dest_idx - 1, - mctx->eflags); - mctx->state_log[dest_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - if (dest_state != NULL) - re_node_set_free (&dest_nodes); - if (__glibc_unlikely (mctx->state_log[dest_idx] == NULL - && err != REG_NOERROR)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - for (i = 0; i < nodes->nelem; ++i) - { - Idx dest_str_idx, prev_nelem, bkc_idx; - Idx node_idx = nodes->elems[i]; - unsigned int context; - const re_token_t *node = dfa->nodes + node_idx; - re_node_set *new_dest_nodes; - - /* Check whether 'node' is a backreference or not. */ - if (node->type != OP_BACK_REF) - continue; - - if (node->constraint) - { - context = re_string_context_at (&mctx->input, cur_str_idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - continue; - } - - /* 'node' is a backreference. - Check the substring which the substring matched. */ - bkc_idx = mctx->nbkref_ents; - err = get_subexp (mctx, node_idx, cur_str_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - - /* And add the epsilon closures (which is 'new_dest_nodes') of - the backreference to appropriate state_log. */ - DEBUG_ASSERT (dfa->nexts[node_idx] != -1); - for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) - { - Idx subexp_len; - re_dfastate_t *dest_state; - struct re_backref_cache_entry *bkref_ent; - bkref_ent = mctx->bkref_ents + bkc_idx; - if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) - continue; - subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; - new_dest_nodes = (subexp_len == 0 - ? dfa->eclosures + dfa->edests[node_idx].elems[0] - : dfa->eclosures + dfa->nexts[node_idx]); - dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - - bkref_ent->subexp_from); - context = re_string_context_at (&mctx->input, dest_str_idx - 1, - mctx->eflags); - dest_state = mctx->state_log[dest_str_idx]; - prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 - : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add 'new_dest_node' to state_log. */ - if (dest_state == NULL) - { - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, new_dest_nodes, - context); - if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR)) - goto free_return; - } - else - { - re_node_set dest_nodes; - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, - new_dest_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&dest_nodes); - goto free_return; - } - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - re_node_set_free (&dest_nodes); - if (__glibc_unlikely (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR)) - goto free_return; - } - /* We need to check recursively if the backreference can epsilon - transit. */ - if (subexp_len == 0 - && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) - { - err = check_subexp_matching_top (mctx, new_dest_nodes, - cur_str_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - err = transit_state_bkref (mctx, new_dest_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - goto free_return; - } - } - } - err = REG_NOERROR; - free_return: - return err; -} - -/* Enumerate all the candidates which the backreference BKREF_NODE can match - at BKREF_STR_IDX, and register them by match_ctx_add_entry(). - Note that we might collect inappropriate candidates here. - However, the cost of checking them strictly here is too high, then we - delay these checking for prune_impossible_nodes(). */ - -static reg_errcode_t -__attribute_warn_unused_result__ -get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx subexp_num, sub_top_idx; - const char *buf = (const char *) re_string_get_buffer (&mctx->input); - /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ - Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - if (cache_idx != -1) - { - const struct re_backref_cache_entry *entry - = mctx->bkref_ents + cache_idx; - do - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ - while (entry++->more); - } - - subexp_num = dfa->nodes[bkref_node].opr.idx; - - /* For each sub expression */ - for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) - { - reg_errcode_t err; - re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; - re_sub_match_last_t *sub_last; - Idx sub_last_idx, sl_str, bkref_str_off; - - if (dfa->nodes[sub_top->node].opr.idx != subexp_num) - continue; /* It isn't related. */ - - sl_str = sub_top->str_idx; - bkref_str_off = bkref_str_idx; - /* At first, check the last node of sub expressions we already - evaluated. */ - for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) - { - regoff_t sl_str_diff; - sub_last = sub_top->lasts[sub_last_idx]; - sl_str_diff = sub_last->str_idx - sl_str; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_diff > 0) - { - if (__glibc_unlikely (bkref_str_off + sl_str_diff - > mctx->input.valid_len)) - { - /* Not enough chars for a successful match. */ - if (bkref_str_off + sl_str_diff > mctx->input.len) - break; - - err = clean_state_log_if_needed (mctx, - bkref_str_off - + sl_str_diff); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - /* We don't need to search this sub expression any more. */ - break; - } - bkref_str_off += sl_str_diff; - sl_str += sl_str_diff; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - - /* Reload buf, since the preceding call might have reallocated - the buffer. */ - buf = (const char *) re_string_get_buffer (&mctx->input); - - if (err == REG_NOMATCH) - continue; - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - - if (sub_last_idx < sub_top->nlasts) - continue; - if (sub_last_idx > 0) - ++sl_str; - /* Then, search for the other last nodes of the sub expression. */ - for (; sl_str <= bkref_str_idx; ++sl_str) - { - Idx cls_node; - regoff_t sl_str_off; - const re_node_set *nodes; - sl_str_off = sl_str - sub_top->str_idx; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_off > 0) - { - if (__glibc_unlikely (bkref_str_off >= mctx->input.valid_len)) - { - /* If we are at the end of the input, we cannot match. */ - if (bkref_str_off >= mctx->input.len) - break; - - err = extend_buffers (mctx, bkref_str_off + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (buf [bkref_str_off++] != buf[sl_str - 1]) - break; /* We don't need to search this sub expression - any more. */ - } - if (mctx->state_log[sl_str] == NULL) - continue; - /* Does this state have a ')' of the sub expression? */ - nodes = &mctx->state_log[sl_str]->nodes; - cls_node = find_subexp_node (dfa, nodes, subexp_num, - OP_CLOSE_SUBEXP); - if (cls_node == -1) - continue; /* No. */ - if (sub_top->path == NULL) - { - sub_top->path = calloc (sizeof (state_array_t), - sl_str - sub_top->str_idx + 1); - if (sub_top->path == NULL) - return REG_ESPACE; - } - /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node - in the current context? */ - err = check_arrival (mctx, sub_top->path, sub_top->node, - sub_top->str_idx, cls_node, sl_str, - OP_CLOSE_SUBEXP); - if (err == REG_NOMATCH) - continue; - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); - if (__glibc_unlikely (sub_last == NULL)) - return REG_ESPACE; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - buf = (const char *) re_string_get_buffer (&mctx->input); - if (err == REG_NOMATCH) - continue; - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - } - return REG_NOERROR; -} - -/* Helper functions for get_subexp(). */ - -/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. - If it can arrive, register the sub expression expressed with SUB_TOP - and SUB_LAST. */ - -static reg_errcode_t -get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) -{ - reg_errcode_t err; - Idx to_idx; - /* Can the subexpression arrive the back reference? */ - err = check_arrival (mctx, &sub_last->path, sub_last->node, - sub_last->str_idx, bkref_node, bkref_str, - OP_OPEN_SUBEXP); - if (err != REG_NOERROR) - return err; - err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, - sub_last->str_idx); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - return clean_state_log_if_needed (mctx, to_idx); -} - -/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. - Search '(' if FL_OPEN, or search ')' otherwise. - TODO: This function isn't efficient... - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - -static Idx -find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) -{ - Idx cls_idx; - for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) - { - Idx cls_node = nodes->elems[cls_idx]; - const re_token_t *node = dfa->nodes + cls_node; - if (node->type == type - && node->opr.idx == subexp_idx) - return cls_node; - } - return -1; -} - -/* Check whether the node TOP_NODE at TOP_STR can arrive to the node - LAST_NODE at LAST_STR. We record the path onto PATH since it will be - heavily reused. - Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot, - REG_ESPACE if memory is exhausted. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - Idx subexp_num, backup_cur_idx, str_idx, null_cnt; - re_dfastate_t *cur_state = NULL; - re_node_set *cur_nodes, next_nodes; - re_dfastate_t **backup_state_log; - unsigned int context; - - subexp_num = dfa->nodes[top_node].opr.idx; - /* Extend the buffer if we need. */ - if (__glibc_unlikely (path->alloc < last_str + mctx->max_mb_elem_len + 1)) - { - re_dfastate_t **new_array; - Idx old_alloc = path->alloc; - Idx incr_alloc = last_str + mctx->max_mb_elem_len + 1; - Idx new_alloc; - if (__glibc_unlikely (IDX_MAX - old_alloc < incr_alloc)) - return REG_ESPACE; - new_alloc = old_alloc + incr_alloc; - if (__glibc_unlikely (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc)) - return REG_ESPACE; - new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); - if (__glibc_unlikely (new_array == NULL)) - return REG_ESPACE; - path->array = new_array; - path->alloc = new_alloc; - memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); - } - - str_idx = path->next_idx ? path->next_idx : top_str; - - /* Temporary modify MCTX. */ - backup_state_log = mctx->state_log; - backup_cur_idx = mctx->input.cur_idx; - mctx->state_log = path->array; - mctx->input.cur_idx = str_idx; - - /* Setup initial node set. */ - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - if (str_idx == top_str) - { - err = re_node_set_init_1 (&next_nodes, top_node); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - } - else - { - cur_state = mctx->state_log[str_idx]; - if (cur_state && cur_state->has_backref) - { - err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - else - re_node_set_init_empty (&next_nodes); - } - if (str_idx == top_str || (cur_state && cur_state->has_backref)) - { - if (next_nodes.nelem) - { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - } - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - } - - for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) - { - re_node_set_empty (&next_nodes); - if (mctx->state_log[str_idx + 1]) - { - err = re_node_set_merge (&next_nodes, - &mctx->state_log[str_idx + 1]->nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - } - if (cur_state) - { - err = check_arrival_add_next_nodes (mctx, str_idx, - &cur_state->non_eps_nodes, - &next_nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - } - ++str_idx; - if (next_nodes.nelem) - { - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - } - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (__glibc_unlikely (cur_state == NULL && err != REG_NOERROR)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - null_cnt = cur_state == NULL ? null_cnt + 1 : 0; - } - re_node_set_free (&next_nodes); - cur_nodes = (mctx->state_log[last_str] == NULL ? NULL - : &mctx->state_log[last_str]->nodes); - path->next_idx = str_idx; - - /* Fix MCTX. */ - mctx->state_log = backup_state_log; - mctx->input.cur_idx = backup_cur_idx; - - /* Then check the current node set has the node LAST_NODE. */ - if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) - return REG_NOERROR; - - return REG_NOMATCH; -} - -/* Helper functions for check_arrival. */ - -/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them - to NEXT_NODES. - TODO: This function is similar to the functions transit_state*(), - however this function has many additional works. - Can't we unify them? */ - -static reg_errcode_t -__attribute_warn_unused_result__ -check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, - re_node_set *cur_nodes, re_node_set *next_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - bool ok; - Idx cur_idx; - reg_errcode_t err = REG_NOERROR; - re_node_set union_set; - re_node_set_init_empty (&union_set); - for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) - { - int naccepted = 0; - Idx cur_node = cur_nodes->elems[cur_idx]; - DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type)); - - /* If the node may accept "multi byte". */ - if (dfa->nodes[cur_node].accept_mb) - { - naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, - str_idx); - if (naccepted > 1) - { - re_dfastate_t *dest_state; - Idx next_node = dfa->nexts[cur_node]; - Idx next_idx = str_idx + naccepted; - dest_state = mctx->state_log[next_idx]; - re_node_set_empty (&union_set); - if (dest_state) - { - err = re_node_set_merge (&union_set, &dest_state->nodes); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&union_set); - return err; - } - } - ok = re_node_set_insert (&union_set, next_node); - if (__glibc_unlikely (! ok)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - mctx->state_log[next_idx] = re_acquire_state (&err, dfa, - &union_set); - if (__glibc_unlikely (mctx->state_log[next_idx] == NULL - && err != REG_NOERROR)) - { - re_node_set_free (&union_set); - return err; - } - } - } - - if (naccepted - || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) - { - ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (__glibc_unlikely (! ok)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - } - } - re_node_set_free (&union_set); - return REG_NOERROR; -} - -/* For all the nodes in CUR_NODES, add the epsilon closures of them to - CUR_NODES, however exclude the nodes which are: - - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. -*/ - -static reg_errcode_t -check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, - Idx ex_subexp, int type) -{ - reg_errcode_t err; - Idx idx, outside_node; - re_node_set new_nodes; - DEBUG_ASSERT (cur_nodes->nelem); - err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - /* Create a new node set NEW_NODES with the nodes which are epsilon - closures of the node in CUR_NODES. */ - - for (idx = 0; idx < cur_nodes->nelem; ++idx) - { - Idx cur_node = cur_nodes->elems[idx]; - const re_node_set *eclosure = dfa->eclosures + cur_node; - outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); - if (outside_node == -1) - { - /* There are no problematic nodes, just merge them. */ - err = re_node_set_merge (&new_nodes, eclosure); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&new_nodes); - return err; - } - } - else - { - /* There are problematic nodes, re-calculate incrementally. */ - err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, - ex_subexp, type); - if (__glibc_unlikely (err != REG_NOERROR)) - { - re_node_set_free (&new_nodes); - return err; - } - } - } - re_node_set_free (cur_nodes); - *cur_nodes = new_nodes; - return REG_NOERROR; -} - -/* Helper function for check_arrival_expand_ecl. - Check incrementally the epsilon closure of TARGET, and if it isn't - problematic append it to DST_NODES. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, - Idx target, Idx ex_subexp, int type) -{ - Idx cur_node; - for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) - { - bool ok; - - if (dfa->nodes[cur_node].type == type - && dfa->nodes[cur_node].opr.idx == ex_subexp) - { - if (type == OP_CLOSE_SUBEXP) - { - ok = re_node_set_insert (dst_nodes, cur_node); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - } - break; - } - ok = re_node_set_insert (dst_nodes, cur_node); - if (__glibc_unlikely (! ok)) - return REG_ESPACE; - if (dfa->edests[cur_node].nelem == 0) - break; - if (dfa->edests[cur_node].nelem == 2) - { - reg_errcode_t err; - err = check_arrival_expand_ecl_sub (dfa, dst_nodes, - dfa->edests[cur_node].elems[1], - ex_subexp, type); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - cur_node = dfa->edests[cur_node].elems[0]; - } - return REG_NOERROR; -} - - -/* For all the back references in the current state, calculate the - destination of the back references by the appropriate entry - in MCTX->BKREF_ENTS. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx cur_str, Idx subexp_num, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - struct re_backref_cache_entry *ent; - - if (cache_idx_start == -1) - return REG_NOERROR; - - restart: - ent = mctx->bkref_ents + cache_idx_start; - do - { - Idx to_idx, next_node; - - /* Is this entry ENT is appropriate? */ - if (!re_node_set_contains (cur_nodes, ent->node)) - continue; /* No. */ - - to_idx = cur_str + ent->subexp_to - ent->subexp_from; - /* Calculate the destination of the back reference, and append it - to MCTX->STATE_LOG. */ - if (to_idx == cur_str) - { - /* The backreference did epsilon transit, we must re-check all the - node in the current state. */ - re_node_set new_dests; - reg_errcode_t err2, err3; - next_node = dfa->edests[ent->node].elems[0]; - if (re_node_set_contains (cur_nodes, next_node)) - continue; - err = re_node_set_init_1 (&new_dests, next_node); - err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); - err3 = re_node_set_merge (cur_nodes, &new_dests); - re_node_set_free (&new_dests); - if (__glibc_unlikely (err != REG_NOERROR || err2 != REG_NOERROR - || err3 != REG_NOERROR)) - { - err = (err != REG_NOERROR ? err - : (err2 != REG_NOERROR ? err2 : err3)); - return err; - } - /* TODO: It is still inefficient... */ - goto restart; - } - else - { - re_node_set union_set; - next_node = dfa->nexts[ent->node]; - if (mctx->state_log[to_idx]) - { - bool ok; - if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, - next_node)) - continue; - err = re_node_set_init_copy (&union_set, - &mctx->state_log[to_idx]->nodes); - ok = re_node_set_insert (&union_set, next_node); - if (__glibc_unlikely (err != REG_NOERROR || ! ok)) - { - re_node_set_free (&union_set); - err = err != REG_NOERROR ? err : REG_ESPACE; - return err; - } - } - else - { - err = re_node_set_init_1 (&union_set, next_node); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; - } - mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); - re_node_set_free (&union_set); - if (__glibc_unlikely (mctx->state_log[to_idx] == NULL - && err != REG_NOERROR)) - return err; - } - } - while (ent++->more); - return REG_NOERROR; -} - -/* Build transition table for the state. - Return true if successful. */ - -static bool __attribute_noinline__ -build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) -{ - reg_errcode_t err; - Idx i, j; - int ch; - bool need_word_trtable = false; - bitset_word_t elem, mask; - Idx ndests; /* Number of the destination states from 'state'. */ - re_dfastate_t **trtable; - re_dfastate_t *dest_states[SBC_MAX]; - re_dfastate_t *dest_states_word[SBC_MAX]; - re_dfastate_t *dest_states_nl[SBC_MAX]; - re_node_set follows; - bitset_t acceptable; - - /* We build DFA states which corresponds to the destination nodes - from 'state'. 'dests_node[i]' represents the nodes which i-th - destination state contains, and 'dests_ch[i]' represents the - characters which i-th destination state accepts. */ - re_node_set dests_node[SBC_MAX]; - bitset_t dests_ch[SBC_MAX]; - - /* Initialize transition table. */ - state->word_trtable = state->trtable = NULL; - - /* At first, group all nodes belonging to 'state' into several - destinations. */ - ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); - if (__glibc_unlikely (ndests <= 0)) - { - /* Return false in case of an error, true otherwise. */ - if (ndests == 0) - { - state->trtable = (re_dfastate_t **) - calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (__glibc_unlikely (state->trtable == NULL)) - return false; - return true; - } - return false; - } - - err = re_node_set_alloc (&follows, ndests + 1); - if (__glibc_unlikely (err != REG_NOERROR)) - { - out_free: - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - return false; - } - - bitset_empty (acceptable); - - /* Then build the states for all destinations. */ - for (i = 0; i < ndests; ++i) - { - Idx next_node; - re_node_set_empty (&follows); - /* Merge the follows of this destination states. */ - for (j = 0; j < dests_node[i].nelem; ++j) - { - next_node = dfa->nexts[dests_node[i].elems[j]]; - if (next_node != -1) - { - err = re_node_set_merge (&follows, dfa->eclosures + next_node); - if (__glibc_unlikely (err != REG_NOERROR)) - goto out_free; - } - } - dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); - if (__glibc_unlikely (dest_states[i] == NULL && err != REG_NOERROR)) - goto out_free; - /* If the new state has context constraint, - build appropriate states for these contexts. */ - if (dest_states[i]->has_constraint) - { - dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_WORD); - if (__glibc_unlikely (dest_states_word[i] == NULL - && err != REG_NOERROR)) - goto out_free; - - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) - need_word_trtable = true; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_NEWLINE); - if (__glibc_unlikely (dest_states_nl[i] == NULL && err != REG_NOERROR)) - goto out_free; - } - else - { - dest_states_word[i] = dest_states[i]; - dest_states_nl[i] = dest_states[i]; - } - bitset_merge (acceptable, dests_ch[i]); - } - - if (!__glibc_unlikely (need_word_trtable)) - { - /* We don't care about whether the following character is a word - character, or we are in a single-byte character set so we can - discern by looking at the character code: allocate a - 256-entry transition table. */ - trtable = state->trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (__glibc_unlikely (trtable == NULL)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (__glibc_unlikely (elem & 1)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - if (dfa->word_char[i] & mask) - trtable[ch] = dest_states_word[j]; - else - trtable[ch] = dest_states[j]; - } - } - else - { - /* We care about whether the following character is a word - character, and we are in a multi-byte character set: discern - by looking at the character code: build two 256-entry - transition tables, one starting at trtable[0] and one - starting at trtable[SBC_MAX]. */ - trtable = state->word_trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); - if (__glibc_unlikely (trtable == NULL)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (__glibc_unlikely (elem & 1)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - trtable[ch] = dest_states[j]; - trtable[ch + SBC_MAX] = dest_states_word[j]; - } - } - - /* new line */ - if (bitset_contain (acceptable, NEWLINE_CHAR)) - { - /* The current state accepts newline character. */ - for (j = 0; j < ndests; ++j) - if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) - { - /* k-th destination accepts newline character. */ - trtable[NEWLINE_CHAR] = dest_states_nl[j]; - if (need_word_trtable) - trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; - /* There must be only one destination which accepts - newline. See group_nodes_into_DFAstates. */ - break; - } - } - - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - return true; -} - -/* Group all nodes belonging to STATE into several destinations. - Then for all destinations, set the nodes belonging to the destination - to DESTS_NODE[i] and set the characters accepted by the destination - to DEST_CH[i]. Return the number of destinations if successful, - -1 on internal error. */ - -static Idx -group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, - re_node_set *dests_node, bitset_t *dests_ch) -{ - reg_errcode_t err; - bool ok; - Idx i, j, k; - Idx ndests; /* Number of the destinations from 'state'. */ - bitset_t accepts; /* Characters a node can accept. */ - const re_node_set *cur_nodes = &state->nodes; - bitset_empty (accepts); - ndests = 0; - - /* For all the nodes belonging to 'state', */ - for (i = 0; i < cur_nodes->nelem; ++i) - { - re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - /* Enumerate all single byte character this node can accept. */ - if (type == CHARACTER) - bitset_set (accepts, node->opr.c); - else if (type == SIMPLE_BRACKET) - { - bitset_merge (accepts, node->opr.sbcset); - } - else if (type == OP_PERIOD) - { - if (dfa->mb_cur_max > 1) - bitset_merge (accepts, dfa->sb_char); - else - bitset_set_all (accepts); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } - else if (type == OP_UTF8_PERIOD) - { - if (ASCII_CHARS % BITSET_WORD_BITS == 0) - memset (accepts, -1, ASCII_CHARS / CHAR_BIT); - else - bitset_merge (accepts, utf8_sb_map); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } - else - continue; - - /* Check the 'accepts' and sift the characters which are not - match it the context. */ - if (constraint) - { - if (constraint & NEXT_NEWLINE_CONSTRAINT) - { - bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); - bitset_empty (accepts); - if (accepts_newline) - bitset_set (accepts, NEWLINE_CHAR); - else - continue; - } - if (constraint & NEXT_ENDBUF_CONSTRAINT) - { - bitset_empty (accepts); - continue; - } - - if (constraint & NEXT_WORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && !node->word_char) - { - bitset_empty (accepts); - continue; - } - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= dfa->word_char[j]); - if (!any_set) - continue; - } - if (constraint & NEXT_NOTWORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && node->word_char) - { - bitset_empty (accepts); - continue; - } - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~dfa->word_char[j]); - if (!any_set) - continue; - } - } - - /* Then divide 'accepts' into DFA states, or create a new - state. Above, we make sure that accepts is not empty. */ - for (j = 0; j < ndests; ++j) - { - bitset_t intersec; /* Intersection sets, see below. */ - bitset_t remains; - /* Flags, see below. */ - bitset_word_t has_intersec, not_subset, not_consumed; - - /* Optimization, skip if this state doesn't accept the character. */ - if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) - continue; - - /* Enumerate the intersection set of this state and 'accepts'. */ - has_intersec = 0; - for (k = 0; k < BITSET_WORDS; ++k) - has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; - /* And skip if the intersection set is empty. */ - if (!has_intersec) - continue; - - /* Then check if this state is a subset of 'accepts'. */ - not_subset = not_consumed = 0; - for (k = 0; k < BITSET_WORDS; ++k) - { - not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; - not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; - } - - /* If this state isn't a subset of 'accepts', create a - new group state, which has the 'remains'. */ - if (not_subset) - { - bitset_copy (dests_ch[ndests], remains); - bitset_copy (dests_ch[j], intersec); - err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); - if (__glibc_unlikely (err != REG_NOERROR)) - goto error_return; - ++ndests; - } - - /* Put the position in the current group. */ - ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (__glibc_unlikely (! ok)) - goto error_return; - - /* If all characters are consumed, go to next node. */ - if (!not_consumed) - break; - } - /* Some characters remain, create a new group. */ - if (j == ndests) - { - bitset_copy (dests_ch[ndests], accepts); - err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); - if (__glibc_unlikely (err != REG_NOERROR)) - goto error_return; - ++ndests; - bitset_empty (accepts); - } - } - assume (ndests <= SBC_MAX); - return ndests; - error_return: - for (j = 0; j < ndests; ++j) - re_node_set_free (dests_node + j); - return -1; -} - -/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. - Return the number of the bytes the node accepts. - STR_IDX is the current index of the input string. - - This function handles the nodes which can accept one character, or - one collating element like '.', '[a-z]', opposite to the other nodes - can only accept one byte. */ - -#ifdef _LIBC -# include -#endif - -static int -check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx str_idx) -{ - const re_token_t *node = dfa->nodes + node_idx; - int char_len, elem_len; - Idx i; - - if (__glibc_unlikely (node->type == OP_UTF8_PERIOD)) - { - unsigned char c = re_string_byte_at (input, str_idx), d; - if (__glibc_likely (c < 0xc2)) - return 0; - - if (str_idx + 2 > input->len) - return 0; - - d = re_string_byte_at (input, str_idx + 1); - if (c < 0xe0) - return (d < 0x80 || d > 0xbf) ? 0 : 2; - else if (c < 0xf0) - { - char_len = 3; - if (c == 0xe0 && d < 0xa0) - return 0; - } - else if (c < 0xf8) - { - char_len = 4; - if (c == 0xf0 && d < 0x90) - return 0; - } - else if (c < 0xfc) - { - char_len = 5; - if (c == 0xf8 && d < 0x88) - return 0; - } - else if (c < 0xfe) - { - char_len = 6; - if (c == 0xfc && d < 0x84) - return 0; - } - else - return 0; - - if (str_idx + char_len > input->len) - return 0; - - for (i = 1; i < char_len; ++i) - { - d = re_string_byte_at (input, str_idx + i); - if (d < 0x80 || d > 0xbf) - return 0; - } - return char_len; - } - - char_len = re_string_char_size_at (input, str_idx); - if (node->type == OP_PERIOD) - { - if (char_len <= 1) - return 0; - /* FIXME: I don't think this if is needed, as both '\n' - and '\0' are char_len == 1. */ - /* '.' accepts any one character except the following two cases. */ - if ((!(dfa->syntax & RE_DOT_NEWLINE) - && re_string_byte_at (input, str_idx) == '\n') - || ((dfa->syntax & RE_DOT_NOT_NULL) - && re_string_byte_at (input, str_idx) == '\0')) - return 0; - return char_len; - } - - elem_len = re_string_elem_size_at (input, str_idx); - if ((elem_len <= 1 && char_len <= 1) || char_len == 0) - return 0; - - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; -#ifdef _LIBC - const unsigned char *pin - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); - Idx j; - uint32_t nrules; -#endif - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); - - /* match with multibyte character? */ - for (i = 0; i < cset->nmbchars; ++i) - if (wc == cset->mbchars[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { - wctype_t wt = cset->char_classes[i]; - if (__iswctype (wc, wt)) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - -#ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; - const unsigned char *weights, *extra; - const char *collseqwc; - - /* match with collating_symbol? */ - if (cset->ncoll_syms) - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - for (i = 0; i < cset->ncoll_syms; ++i) - { - const unsigned char *coll_sym = extra + cset->coll_syms[i]; - /* Compare the length of input collating element and - the length of current collating element. */ - if (*coll_sym != elem_len) - continue; - /* Compare each bytes. */ - for (j = 0; j < *coll_sym; j++) - if (pin[j] != coll_sym[1 + j]) - break; - if (j == *coll_sym) - { - /* Match if every bytes is equal. */ - match_len = j; - goto check_node_accept_bytes_match; - } - } - - if (cset->nranges) - { - if (elem_len <= char_len) - { - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - in_collseq = __collseq_table_lookup (collseqwc, wc); - } - else - in_collseq = find_collation_sequence_value (pin, elem_len); - } - /* match with range expression? */ - /* FIXME: Implement rational ranges here, too. */ - for (i = 0; i < cset->nranges; ++i) - if (cset->range_starts[i] <= in_collseq - && in_collseq <= cset->range_ends[i]) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - - /* match with equivalence_class? */ - if (cset->nequiv_classes) - { - const unsigned char *cp = pin; - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - int32_t idx = findidx (table, indirect, extra, &cp, elem_len); - int32_t rule = idx >> 24; - idx &= 0xffffff; - if (idx > 0) - { - size_t weight_len = weights[idx]; - for (i = 0; i < cset->nequiv_classes; ++i) - { - int32_t equiv_class_idx = cset->equiv_classes[i]; - int32_t equiv_class_rule = equiv_class_idx >> 24; - equiv_class_idx &= 0xffffff; - if (weights[equiv_class_idx] == weight_len - && equiv_class_rule == rule - && memcmp (weights + idx + 1, - weights + equiv_class_idx + 1, - weight_len) == 0) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - } - } - } - } - else -#endif /* _LIBC */ - { - /* match with range expression? */ - for (i = 0; i < cset->nranges; ++i) - { - if (cset->range_starts[i] <= wc && wc <= cset->range_ends[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - } - check_node_accept_bytes_match: - if (!cset->non_match) - return match_len; - else - { - if (match_len > 0) - return 0; - else - return (elem_len > char_len) ? elem_len : char_len; - } - } - return 0; -} - -#ifdef _LIBC -static unsigned int -find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -{ - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules == 0) - { - if (mbs_len == 1) - { - /* No valid character. Match it as a single byte character. */ - const unsigned char *collseq = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - return collseq[mbs[0]]; - } - return UINT_MAX; - } - else - { - int32_t idx; - const unsigned char *extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - int32_t extrasize = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; - - for (idx = 0; idx < extrasize;) - { - int mbs_cnt; - bool found = false; - int32_t elem_mbs_len; - /* Skip the name of collating element name. */ - idx = idx + extra[idx] + 1; - elem_mbs_len = extra[idx++]; - if (mbs_len == elem_mbs_len) - { - for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) - if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) - break; - if (mbs_cnt == elem_mbs_len) - /* Found the entry. */ - found = true; - } - /* Skip the byte sequence of the collating element. */ - idx += elem_mbs_len; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (*(int32_t *) (extra + idx) + 1); - /* If we found the entry, return the sequence value. */ - if (found) - return *(uint32_t *) (extra + idx); - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - } - return UINT_MAX; - } -} -#endif /* _LIBC */ - -/* Check whether the node accepts the byte which is IDX-th - byte of the INPUT. */ - -static bool -check_node_accept (const re_match_context_t *mctx, const re_token_t *node, - Idx idx) -{ - unsigned char ch; - ch = re_string_byte_at (&mctx->input, idx); - switch (node->type) - { - case CHARACTER: - if (node->opr.c != ch) - return false; - break; - - case SIMPLE_BRACKET: - if (!bitset_contain (node->opr.sbcset, ch)) - return false; - break; - - case OP_UTF8_PERIOD: - if (ch >= ASCII_CHARS) - return false; - FALLTHROUGH; - case OP_PERIOD: - if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) - || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) - return false; - break; - - default: - return false; - } - - if (node->constraint) - { - /* The node has constraints. Check whether the current context - satisfies the constraints. */ - unsigned int context = re_string_context_at (&mctx->input, idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - return false; - } - - return true; -} - -/* Extend the buffers, if the buffers have run out. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -extend_buffers (re_match_context_t *mctx, int min_len) -{ - reg_errcode_t ret; - re_string_t *pstr = &mctx->input; - - /* Avoid overflow. */ - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / sizeof (re_dfastate_t *)) / 2 - <= pstr->bufs_len)) - return REG_ESPACE; - - /* Double the lengths of the buffers, but allocate at least MIN_LEN. */ - ret = re_string_realloc_buffers (pstr, - MAX (min_len, - MIN (pstr->len, pstr->bufs_len * 2))); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - - if (mctx->state_log != NULL) - { - /* And double the length of state_log. */ - /* XXX We have no indication of the size of this buffer. If this - allocation fail we have no indication that the state_log array - does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); - if (__glibc_unlikely (new_array == NULL)) - return REG_ESPACE; - mctx->state_log = new_array; - } - - /* Then reconstruct the buffers. */ - if (pstr->icase) - { - if (pstr->mb_cur_max > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (__glibc_unlikely (ret != REG_NOERROR)) - return ret; - } - else - build_upper_buffer (pstr); - } - else - { - if (pstr->mb_cur_max > 1) - build_wcs_buffer (pstr); - else - { - if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - } - return REG_NOERROR; -} - - -/* Functions for matching context. */ - -/* Initialize MCTX. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) -{ - mctx->eflags = eflags; - mctx->match_last = -1; - if (n > 0) - { - /* Avoid overflow. */ - size_t max_object_size = - MAX (sizeof (struct re_backref_cache_entry), - sizeof (re_sub_match_top_t *)); - if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) < n)) - return REG_ESPACE; - - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); - if (__glibc_unlikely (mctx->bkref_ents == NULL || mctx->sub_tops == NULL)) - return REG_ESPACE; - } - /* Already zero-ed by the caller. - else - mctx->bkref_ents = NULL; - mctx->nbkref_ents = 0; - mctx->nsub_tops = 0; */ - mctx->abkref_ents = n; - mctx->max_mb_elem_len = 1; - mctx->asub_tops = n; - return REG_NOERROR; -} - -/* Clean the entries which depend on the current input in MCTX. - This function must be invoked when the matcher changes the start index - of the input, or changes the input string. */ - -static void -match_ctx_clean (re_match_context_t *mctx) -{ - Idx st_idx; - for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) - { - Idx sl_idx; - re_sub_match_top_t *top = mctx->sub_tops[st_idx]; - for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) - { - re_sub_match_last_t *last = top->lasts[sl_idx]; - re_free (last->path.array); - re_free (last); - } - re_free (top->lasts); - if (top->path) - { - re_free (top->path->array); - re_free (top->path); - } - re_free (top); - } - - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -match_ctx_free (re_match_context_t *mctx) -{ - /* First, free all the memory associated with MCTX->SUB_TOPS. */ - match_ctx_clean (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Add a new backreference entry to MCTX. - Note that we assume that caller never call this function with duplicate - entry, and call with STR_IDX which isn't smaller than any existing entry. -*/ - -static reg_errcode_t -__attribute_warn_unused_result__ -match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, - Idx to) -{ - if (mctx->nbkref_ents >= mctx->abkref_ents) - { - struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); - if (__glibc_unlikely (new_entry == NULL)) - { - re_free (mctx->bkref_ents); - return REG_ESPACE; - } - mctx->bkref_ents = new_entry; - memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; - } - if (mctx->nbkref_ents > 0 - && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) - mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; - - mctx->bkref_ents[mctx->nbkref_ents].node = node; - mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; - mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; - mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; - - /* This is a cache that saves negative results of check_dst_limits_calc_pos. - If bit N is clear, means that this entry won't epsilon-transition to - an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If - it is set, check_dst_limits_calc_pos_1 will recurse and try to find one - such node. - - A backreference does not epsilon-transition unless it is empty, so set - to all zeros if FROM != TO. */ - mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map - = (from == to ? -1 : 0); - - mctx->bkref_ents[mctx->nbkref_ents++].more = 0; - if (mctx->max_mb_elem_len < to - from) - mctx->max_mb_elem_len = to - from; - return REG_NOERROR; -} - -/* Return the first entry with the same str_idx, or -1 if none is - found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ - -static Idx -search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) -{ - Idx left, right, mid, last; - last = right = mctx->nbkref_ents; - for (left = 0; left < right;) - { - mid = (left + right) / 2; - if (mctx->bkref_ents[mid].str_idx < str_idx) - left = mid + 1; - else - right = mid; - } - if (left < last && mctx->bkref_ents[left].str_idx == str_idx) - return left; - else - return -1; -} - -/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches - at STR_IDX. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) -{ - DEBUG_ASSERT (mctx->sub_tops != NULL); - DEBUG_ASSERT (mctx->asub_tops > 0); - if (__glibc_unlikely (mctx->nsub_tops == mctx->asub_tops)) - { - Idx new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); - if (__glibc_unlikely (new_array == NULL)) - return REG_ESPACE; - mctx->sub_tops = new_array; - mctx->asub_tops = new_asub_tops; - } - mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); - if (__glibc_unlikely (mctx->sub_tops[mctx->nsub_tops] == NULL)) - return REG_ESPACE; - mctx->sub_tops[mctx->nsub_tops]->node = node; - mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; - return REG_NOERROR; -} - -/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches - at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. - Return the new entry if successful, NULL if memory is exhausted. */ - -static re_sub_match_last_t * -match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) -{ - re_sub_match_last_t *new_entry; - if (__glibc_unlikely (subtop->nlasts == subtop->alasts)) - { - Idx new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); - if (__glibc_unlikely (new_array == NULL)) - return NULL; - subtop->lasts = new_array; - subtop->alasts = new_alasts; - } - new_entry = calloc (1, sizeof (re_sub_match_last_t)); - if (__glibc_likely (new_entry != NULL)) - { - subtop->lasts[subtop->nlasts] = new_entry; - new_entry->node = node; - new_entry->str_idx = str_idx; - ++subtop->nlasts; - } - return new_entry; -} - -static void -sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) -{ - sctx->sifted_states = sifted_sts; - sctx->limited_states = limited_sts; - sctx->last_node = last_node; - sctx->last_str_idx = last_str_idx; - re_node_set_init_empty (&sctx->limits); -} diff --git a/xcompile/lib/root-uid.h b/xcompile/lib/root-uid.h deleted file mode 100644 index 1905575e47b..00000000000 --- a/xcompile/lib/root-uid.h +++ /dev/null @@ -1,30 +0,0 @@ -/* The user ID that always has appropriate privileges in the POSIX sense. - - Copyright 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef ROOT_UID_H_ -#define ROOT_UID_H_ - -/* The user ID that always has appropriate privileges in the POSIX sense. */ -#ifdef __TANDEM -# define ROOT_UID 65535 -#else -# define ROOT_UID 0 -#endif - -#endif diff --git a/xcompile/lib/save-cwd.c b/xcompile/lib/save-cwd.c deleted file mode 100644 index 7c517d1c819..00000000000 --- a/xcompile/lib/save-cwd.c +++ /dev/null @@ -1,89 +0,0 @@ -/* save-cwd.c -- Save and restore current working directory. - - Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2023 Free Software - Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Gnulib needs to save and restore the current working directory to - fully emulate functions like fstatat. But Emacs doesn't care what - the current working directory is; it always uses absolute file - names. This module replaces the Gnulib module by omitting the code - that Emacs does not need. */ - -#include - -#include "save-cwd.h" - -#include -#include - -/* Record the location of the current working directory in CWD so that - the program may change to other directories and later use restore_cwd - to return to the recorded location. This function may allocate - space using malloc (via getcwd) or leave a file descriptor open; - use free_cwd to perform the necessary free or close. Upon failure, - no memory is allocated, any locally opened file descriptors are - closed; return non-zero -- in that case, free_cwd need not be - called, but doing so is ok. Otherwise, return zero. - - The _raison d'etre_ for this interface is that the working directory - is sometimes inaccessible, and getcwd is not robust or as efficient. - So, we prefer to use the open/fchdir approach, but fall back on - getcwd if necessary. This module works for most cases with just - the getcwd-lgpl module, but to be truly robust, use the getcwd module. - - Some systems lack fchdir altogether: e.g., OS/2, pre-2001 Cygwin, - SCO Xenix. Also, SunOS 4 and Irix 5.3 provide the function, yet it - doesn't work for partitions on which auditing is enabled. If - you're still using an obsolete system with these problems, please - send email to the maintainer of this code. */ - -#if !defined HAVE_FCHDIR && !defined fchdir -# define fchdir(fd) (-1) -#endif - -int -save_cwd (struct saved_cwd *cwd) -{ - cwd->desc = open (".", O_SEARCH | O_CLOEXEC); - /* The 'name' member is present only to minimize differences from - gnulib. Initialize it to zero, if only to simplify debugging. */ - cwd->name = 0; - return 0; -} - -/* Change to recorded location, CWD, in directory hierarchy. - Upon failure, return -1 (errno is set by chdir or fchdir). - Upon success, return zero. */ - -int -restore_cwd (const struct saved_cwd *cwd) -{ - /* Restore the previous directory if possible, to avoid tying down - the file system of the new directory (Bug#18232). - Don't worry if fchdir fails, as Emacs doesn't care what the - working directory is. The fchdir call is inside an 'if' merely to - pacify compilers that complain if fchdir's return value is ignored. */ - if (fchdir (cwd->desc) == 0) - return 0; - - return 0; -} - -void -free_cwd (struct saved_cwd *cwd) -{ - close (cwd->desc); -} diff --git a/xcompile/lib/save-cwd.h b/xcompile/lib/save-cwd.h deleted file mode 100644 index d089b0e2145..00000000000 --- a/xcompile/lib/save-cwd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Save and restore current working directory. - - Copyright (C) 1995, 1997-1998, 2003, 2009-2023 Free Software Foundation, - Inc. - - This program is free software: you can 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 . */ - -/* Written by Jim Meyering. */ - -#ifndef SAVE_CWD_H -# define SAVE_CWD_H 1 - -struct saved_cwd - { - int desc; - char *name; - }; - -int save_cwd (struct saved_cwd *cwd); -int restore_cwd (const struct saved_cwd *cwd); -void free_cwd (struct saved_cwd *cwd); - -#endif /* SAVE_CWD_H */ diff --git a/xcompile/lib/scratch_buffer.h b/xcompile/lib/scratch_buffer.h deleted file mode 100644 index 4cf60d232b7..00000000000 --- a/xcompile/lib/scratch_buffer.h +++ /dev/null @@ -1,117 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert, 2017. */ - -#ifndef _GL_SCRATCH_BUFFER_H -#define _GL_SCRATCH_BUFFER_H - -/* Scratch buffers with a default stack allocation and fallback to - heap allocation. It is expected that this function is used in this - way: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - return -1; - - scratch_buffer_free (&tmpbuf); - return 0; - - The allocation functions (scratch_buffer_grow, - scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make - sure that the heap allocation, if any, is freed, so that the code - above does not have a memory leak. The buffer still remains in a - state that can be deallocated using scratch_buffer_free, so a loop - like this is valid as well: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - break; - - scratch_buffer_free (&tmpbuf); - - scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed - to grow the buffer by at least 512 bytes. This means that when - using the scratch buffer as a backing store for a non-character - array whose element size, in bytes, is 512 or smaller, the scratch - buffer only has to grow once to make room for at least one more - element. -*/ - -/* Scratch buffer. Must be initialized with scratch_buffer_init - before its use. */ -struct scratch_buffer; - -/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space - and BUFFER->length reflects the available space. */ -#if 0 -extern void scratch_buffer_init (struct scratch_buffer *buffer); -#endif - -/* Deallocates *BUFFER (if it was heap-allocated). */ -#if 0 -extern void scratch_buffer_free (struct scratch_buffer *buffer); -#endif - -/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT - preserved. Return true on success, false on allocation failure (in - which case the old buffer is freed). On success, the new buffer is - larger than the previous size. On failure, *BUFFER is deallocated, - but remains in a free-able state, and errno is set. */ -#if 0 -extern bool scratch_buffer_grow (struct scratch_buffer *buffer); -#endif - -/* Like scratch_buffer_grow, but preserve the old buffer - contents on success, as a prefix of the new buffer. */ -#if 0 -extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer); -#endif - -/* Grow *BUFFER so that it can store at least NELEM elements of SIZE - bytes. The buffer contents are NOT preserved. Both NELEM and SIZE - can be zero. Return true on success, false on allocation failure - (in which case the old buffer is freed, but *BUFFER remains in a - free-able state, and errno is set). It is unspecified whether this - function can reduce the array size. */ -#if 0 -extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size); -#endif - - -/* The implementation is imported from glibc. */ - -/* Avoid possible conflicts with symbols exported by the GNU libc. */ -#define __libc_scratch_buffer_grow gl_scratch_buffer_grow -#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve -#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size - -#ifndef _GL_LIKELY -/* Rely on __builtin_expect, as provided by the module 'builtin-expect'. */ -# define _GL_LIKELY(cond) __builtin_expect ((cond), 1) -# define _GL_UNLIKELY(cond) __builtin_expect ((cond), 0) -#endif - -#include - -#endif /* _GL_SCRATCH_BUFFER_H */ diff --git a/xcompile/lib/set-permissions.c b/xcompile/lib/set-permissions.c deleted file mode 100644 index 1d6732cc78f..00000000000 --- a/xcompile/lib/set-permissions.c +++ /dev/null @@ -1,847 +0,0 @@ -/* Set permissions of a file. -*- coding: utf-8 -*- - - Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ - -#include - -#include "acl.h" - -#include "acl-internal.h" - -#if USE_ACL -# if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ -# if HAVE_ACL_GET_FILE && !HAVE_ACL_TYPE_EXTENDED - -static acl_t -acl_from_mode (mode_t mode) -{ -# if HAVE_ACL_FREE_TEXT /* Tru64 */ - char acl_text[] = "u::---,g::---,o::---,"; -# else /* FreeBSD, IRIX, Cygwin >= 2.5 */ - char acl_text[] = "u::---,g::---,o::---"; -# endif - - if (mode & S_IRUSR) acl_text[ 3] = 'r'; - if (mode & S_IWUSR) acl_text[ 4] = 'w'; - if (mode & S_IXUSR) acl_text[ 5] = 'x'; - if (mode & S_IRGRP) acl_text[10] = 'r'; - if (mode & S_IWGRP) acl_text[11] = 'w'; - if (mode & S_IXGRP) acl_text[12] = 'x'; - if (mode & S_IROTH) acl_text[17] = 'r'; - if (mode & S_IWOTH) acl_text[18] = 'w'; - if (mode & S_IXOTH) acl_text[19] = 'x'; - - return acl_from_text (acl_text); -} -# endif -# endif - -# if HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */ -static int -set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) -{ -# ifdef ACE_GETACL - /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 - file systems (whereas the other ones are used in UFS file systems). */ - - /* The flags in the ace_t structure changed in a binary incompatible way - when ACL_NO_TRIVIAL etc. were introduced in version 1.15. - How to distinguish the two conventions at runtime? - We fetch the existing ACL. In the old convention, usually three ACEs have - a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. - In the new convention, these values are not used. */ - int convention; - - { - /* Initially, try to read the entries into a stack-allocated buffer. - Use malloc if it does not fit. */ - enum - { - alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ - alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) - }; - ace_t buf[alloc_init]; - size_t alloc = alloc_init; - ace_t *entries = buf; - ace_t *malloced = NULL; - int count; - - for (;;) - { - count = (desc != -1 - ? facl (desc, ACE_GETACL, alloc, entries) - : acl (name, ACE_GETACL, alloc, entries)); - if (count < 0 && errno == ENOSPC) - { - /* Increase the size of the buffer. */ - free (malloced); - if (alloc > alloc_max / 2) - { - errno = ENOMEM; - return -1; - } - alloc = 2 * alloc; /* <= alloc_max */ - entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); - if (entries == NULL) - { - errno = ENOMEM; - return -1; - } - continue; - } - break; - } - - if (count <= 0) - convention = -1; - else - { - int i; - - convention = 0; - for (i = 0; i < count; i++) - if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) - { - convention = 1; - break; - } - } - free (malloced); - } - - if (convention >= 0) - { - ace_t entries[6]; - int count; - int ret; - - if (convention) - { - /* Running on Solaris 10. */ - entries[0].a_type = OLD_ALLOW; - entries[0].a_flags = OLD_ACE_OWNER; - entries[0].a_who = 0; /* irrelevant */ - entries[0].a_access_mask = (mode >> 6) & 7; - entries[1].a_type = OLD_ALLOW; - entries[1].a_flags = OLD_ACE_GROUP; - entries[1].a_who = 0; /* irrelevant */ - entries[1].a_access_mask = (mode >> 3) & 7; - entries[2].a_type = OLD_ALLOW; - entries[2].a_flags = OLD_ACE_OTHER; - entries[2].a_who = 0; - entries[2].a_access_mask = mode & 7; - count = 3; - } - else - { - /* Running on Solaris 10 (newer version) or Solaris 11. - The details here were found through "/bin/ls -lvd somefiles". */ - entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; - entries[0].a_flags = NEW_ACE_OWNER; - entries[0].a_who = 0; /* irrelevant */ - entries[0].a_access_mask = 0; - entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; - entries[1].a_flags = NEW_ACE_OWNER; - entries[1].a_who = 0; /* irrelevant */ - entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS - | NEW_ACE_WRITE_ATTRIBUTES - | NEW_ACE_WRITE_ACL - | NEW_ACE_WRITE_OWNER; - if (mode & 0400) - entries[1].a_access_mask |= NEW_ACE_READ_DATA; - else - entries[0].a_access_mask |= NEW_ACE_READ_DATA; - if (mode & 0200) - entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - else - entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - if (mode & 0100) - entries[1].a_access_mask |= NEW_ACE_EXECUTE; - else - entries[0].a_access_mask |= NEW_ACE_EXECUTE; - entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; - entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; - entries[2].a_who = 0; /* irrelevant */ - entries[2].a_access_mask = 0; - entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; - entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; - entries[3].a_who = 0; /* irrelevant */ - entries[3].a_access_mask = 0; - if (mode & 0040) - entries[3].a_access_mask |= NEW_ACE_READ_DATA; - else - entries[2].a_access_mask |= NEW_ACE_READ_DATA; - if (mode & 0020) - entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - else - entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - if (mode & 0010) - entries[3].a_access_mask |= NEW_ACE_EXECUTE; - else - entries[2].a_access_mask |= NEW_ACE_EXECUTE; - entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; - entries[4].a_flags = NEW_ACE_EVERYONE; - entries[4].a_who = 0; - entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS - | NEW_ACE_WRITE_ATTRIBUTES - | NEW_ACE_WRITE_ACL - | NEW_ACE_WRITE_OWNER; - entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; - entries[5].a_flags = NEW_ACE_EVERYONE; - entries[5].a_who = 0; - entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS - | NEW_ACE_READ_ATTRIBUTES - | NEW_ACE_READ_ACL - | NEW_ACE_SYNCHRONIZE; - if (mode & 0004) - entries[5].a_access_mask |= NEW_ACE_READ_DATA; - else - entries[4].a_access_mask |= NEW_ACE_READ_DATA; - if (mode & 0002) - entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - else - entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; - if (mode & 0001) - entries[5].a_access_mask |= NEW_ACE_EXECUTE; - else - entries[4].a_access_mask |= NEW_ACE_EXECUTE; - count = 6; - } - if (desc != -1) - ret = facl (desc, ACE_SETACL, count, entries); - else - ret = acl (name, ACE_SETACL, count, entries); - if (ret < 0 && errno != EINVAL && errno != ENOTSUP) - { - if (errno == ENOSYS) - { - *must_chmod = true; - return 0; - } - return -1; - } - if (ret == 0) - return 0; - } -# endif - - { - aclent_t entries[3]; - int ret; - - entries[0].a_type = USER_OBJ; - entries[0].a_id = 0; /* irrelevant */ - entries[0].a_perm = (mode >> 6) & 7; - entries[1].a_type = GROUP_OBJ; - entries[1].a_id = 0; /* irrelevant */ - entries[1].a_perm = (mode >> 3) & 7; - entries[2].a_type = OTHER_OBJ; - entries[2].a_id = 0; - entries[2].a_perm = mode & 7; - - if (desc != -1) - ret = facl (desc, SETACL, - sizeof (entries) / sizeof (aclent_t), entries); - else - ret = acl (name, SETACL, - sizeof (entries) / sizeof (aclent_t), entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP) - { - *must_chmod = true; - return 0; - } - return -1; - } - return 0; - } -} - -# elif HAVE_GETACL /* HP-UX */ -static int -context_acl_from_mode (struct permission_context *ctx, const char *name, int desc) -{ - struct stat statbuf; - int ret; - - if (desc != -1) - ret = fstat (desc, &statbuf); - else - ret = stat (name, &statbuf); - if (ret < 0) - return -1; - - ctx->entries[0].uid = statbuf.st_uid; - ctx->entries[0].gid = ACL_NSGROUP; - ctx->entries[0].mode = (ctx->mode >> 6) & 7; - ctx->entries[1].uid = ACL_NSUSER; - ctx->entries[1].gid = statbuf.st_gid; - ctx->entries[1].mode = (ctx->mode >> 3) & 7; - ctx->entries[2].uid = ACL_NSUSER; - ctx->entries[2].gid = ACL_NSGROUP; - ctx->entries[2].mode = ctx->mode & 7; - ctx->count = 3; - return 0; -} - -# if HAVE_ACLV_H /* HP-UX >= 11.11 */ -static int -context_aclv_from_mode (struct permission_context *ctx) -{ - int ret; - - ctx->aclv_entries[0].a_type = USER_OBJ; - ctx->aclv_entries[0].a_id = 0; /* irrelevant */ - ctx->aclv_entries[0].a_perm = (ctx->mode >> 6) & 7; - ctx->aclv_entries[1].a_type = GROUP_OBJ; - ctx->aclv_entries[1].a_id = 0; /* irrelevant */ - ctx->aclv_entries[1].a_perm = (ctx->mode >> 3) & 7; - ctx->aclv_entries[2].a_type = CLASS_OBJ; - ctx->aclv_entries[2].a_id = 0; - ctx->aclv_entries[2].a_perm = (ctx->mode >> 3) & 7; - ctx->aclv_entries[3].a_type = OTHER_OBJ; - ctx->aclv_entries[3].a_id = 0; - ctx->aclv_entries[3].a_perm = ctx->mode & 7; - ctx->aclv_count = 4; - - ret = aclsort (ctx->aclv_count, 1, ctx->aclv_entries); - if (ret > 0) - abort (); - return ret; -} -# endif - -# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ -static int -set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) -{ - acl_type_list_t types; - size_t types_size = sizeof (types); - acl_type_t type; - - if (aclx_gettypes (name, &types, &types_size) < 0 - || types.num_entries == 0) - { - *must_chmod = true; - return 0; - } - - /* XXX Do we need to clear all types of ACLs for the given file, or is it - sufficient to clear the first one? */ - type = types.entries[0]; - if (type.u64 == ACL_AIXC) - { - union { struct acl a; char room[128]; } u; - int ret; - - u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ - u.a.acl_mode = mode & ~(S_IXACL | 0777); - u.a.u_access = (mode >> 6) & 7; - u.a.g_access = (mode >> 3) & 7; - u.a.o_access = mode & 7; - - if (desc != -1) - ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.acl_len, mode); - else - ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.acl_len, mode); - if (!(ret < 0 && errno == ENOSYS)) - return ret; - } - else if (type.u64 == ACL_NFS4) - { - union { nfs4_acl_int_t a; char room[128]; } u; - nfs4_ace_int_t *ace; - int ret; - - u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION; - u.a.aclEntryN = 0; - ace = &u.a.aclEntry[0]; - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_OWNER; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0200 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0100 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_GROUP; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0020 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0010 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_EVERYONE; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0002 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0001 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - u.a.aclLength = (char *) ace - (char *) &u.a; - - if (desc != -1) - ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.aclLength, mode); - else - ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.aclLength, mode); - if (!(ret < 0 && errno == ENOSYS)) - return ret; - } - - *must_chmod = true; - return 0; -} - -# elif HAVE_STATACL /* older AIX */ -static int -context_acl_from_mode (struct permission_context *ctx) -{ - ctx->u.a.acl_len = (char *) &ctx->u.a.acl_ext[0] - (char *) &ctx->u.a; /* no entries */ - ctx->u.a.acl_mode = ctx->mode & ~(S_IXACL | 0777); - ctx->u.a.u_access = (ctx->mode >> 6) & 7; - ctx->u.a.g_access = (ctx->mode >> 3) & 7; - ctx->u.a.o_access = ctx->mode & 7; - ctx->have_u = true; - return 0; -} - -# elif HAVE_ACLSORT /* NonStop Kernel */ -static int -context_acl_from_mode (struct permission_context *ctx) -{ - int ret; - - ctx->entries[0].a_type = USER_OBJ; - ctx->entries[0].a_id = 0; /* irrelevant */ - ctx->entries[0].a_perm = (ctx->mode >> 6) & 7; - ctx->entries[1].a_type = GROUP_OBJ; - ctx->entries[1].a_id = 0; /* irrelevant */ - ctx->entries[1].a_perm = (ctx->mode >> 3) & 7; - ctx->entries[2].a_type = CLASS_OBJ; - ctx->entries[2].a_id = 0; - ctx->entries[2].a_perm = (ctx->mode >> 3) & 7; - ctx->entries[3].a_type = OTHER_OBJ; - ctx->entries[3].a_id = 0; - ctx->entries[3].a_perm = ctx->mode & 7; - ctx->count = 4; - - ret = aclsort (ctx->count, 1, entries); - if (ret > 0) - abort (); - return ret; -} -# endif - -static int -set_acls (struct permission_context *ctx, const char *name, int desc, - int from_mode, bool *must_chmod, bool *acls_set) -{ - int ret = 0; - -# if HAVE_ACL_GET_FILE - /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ - /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */ -# if !HAVE_ACL_TYPE_EXTENDED - /* Linux, FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */ - -# ifndef HAVE_ACL_FROM_TEXT -# error Must have acl_from_text (see POSIX 1003.1e draft 17). -# endif -# ifndef HAVE_ACL_DELETE_DEF_FILE -# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). -# endif - - if (! ctx->acls_not_supported) - { - if (ret == 0 && from_mode) - { - if (ctx->acl) - acl_free (ctx->acl); - ctx->acl = acl_from_mode (ctx->mode); - if (ctx->acl == NULL) - ret = -1; - } - - if (ret == 0 && ctx->acl) - { - if (HAVE_ACL_SET_FD && desc != -1) - ret = acl_set_fd (desc, ctx->acl); - else - ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl); - if (ret != 0) - { - if (! acl_errno_valid (errno)) - { - ctx->acls_not_supported = true; - if (from_mode || acl_access_nontrivial (ctx->acl) == 0) - ret = 0; - } - } - else - { - *acls_set = true; - if (S_ISDIR(ctx->mode)) - { - if (! from_mode && ctx->default_acl && - acl_default_nontrivial (ctx->default_acl)) - ret = acl_set_file (name, ACL_TYPE_DEFAULT, - ctx->default_acl); - else - ret = acl_delete_def_file (name); - } - } - } - } - -# if HAVE_ACL_TYPE_NFS4 /* FreeBSD */ - - /* File systems either support POSIX ACLs (for example, ufs) or NFS4 ACLs - (for example, zfs). */ - - /* TODO: Implement setting ACLs once get_permissions() reads them. */ - -# endif - -# else /* HAVE_ACL_TYPE_EXTENDED */ - /* Mac OS X */ - - /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) - always return NULL / EINVAL. You have to use - acl_get_file (name, ACL_TYPE_EXTENDED) - or acl_get_fd (open (name, ...)) - to retrieve an ACL. - On the other hand, - acl_set_file (name, ACL_TYPE_ACCESS, acl) - and acl_set_file (name, ACL_TYPE_DEFAULT, acl) - have the same effect as - acl_set_file (name, ACL_TYPE_EXTENDED, acl): - Each of these calls sets the file's ACL. */ - - if (ctx->acl == NULL) - { - acl_t acl; - - /* Remove ACLs if the file has ACLs. */ - if (HAVE_ACL_GET_FD && desc != -1) - acl = acl_get_fd (desc); - else - acl = acl_get_file (name, ACL_TYPE_EXTENDED); - if (acl) - { - acl_free (acl); - - acl = acl_init (0); - if (acl) - { - if (HAVE_ACL_SET_FD && desc != -1) - ret = acl_set_fd (desc, acl); - else - ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); - acl_free (acl); - } - else - ret = -1; - } - } - else - { - if (HAVE_ACL_SET_FD && desc != -1) - ret = acl_set_fd (desc, ctx->acl); - else - ret = acl_set_file (name, ACL_TYPE_EXTENDED, ctx->acl); - if (ret != 0) - { - if (! acl_errno_valid (errno) - && ! acl_extended_nontrivial (ctx->acl)) - ret = 0; - } - } - *acls_set = true; - -# endif - -# elif defined GETACL /* Solaris, Cygwin, not HP-UX */ - - /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions - of Unixware. The acl() call returns the access and default ACL both - at once. */ - - /* If both ace_entries and entries are available, try SETACL before - ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL - can. */ - - if (from_mode) - return set_acls_from_mode (name, desc, ctx->mode, must_chmod); - - if (ret == 0 && ctx->count) - { - if (desc != -1) - ret = facl (desc, SETACL, ctx->count, ctx->entries); - else - ret = acl (name, SETACL, ctx->count, ctx->entries); - if (ret < 0) - { - if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - && acl_nontrivial (ctx->count, ctx->entries) == 0) - ret = 0; - } - else - *acls_set = true; - } - -# ifdef ACE_GETACL - if (ret == 0 && ctx->ace_count) - { - if (desc != -1) - ret = facl (desc, ACE_SETACL, ctx->ace_count, ctx->ace_entries); - else - ret = acl (name, ACE_SETACL, ctx->ace_count, ctx->ace_entries); - if (ret < 0) - { - if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) - && acl_ace_nontrivial (ctx->ace_count, ctx->ace_entries) == 0) - ret = 0; - } - else - *acls_set = true; - } -# endif - -# elif HAVE_GETACL /* HP-UX */ - - if (from_mode) - ret = context_acl_from_mode (ctx, name, desc); - - if (ret == 0 && ctx->count > 0) - { - if (desc != -1) - ret = fsetacl (desc, ctx->count, ctx->entries); - else - ret = setacl (name, ctx->count, ctx->entries); - if (ret < 0) - { - if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) - && (from_mode || !acl_nontrivial (ctx->count, ctx->entries))) - ret = 0; - } - else - *acls_set = true; - } - -# if HAVE_ACLV_H - if (from_mode) - ret = context_aclv_from_mode (ctx); - - if (ret == 0 && ctx->aclv_count > 0) - { - ret = acl ((char *) name, ACL_SET, ctx->aclv_count, ctx->aclv_entries); - if (ret < 0) - { - if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries))) - ret = 0; - } - else - *acls_set = true; - } -# endif - -# elif HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ - - /* TODO: Implement setting ACLs once get_permissions() reads them. */ - - if (from_mode) - ret = set_acls_from_mode (name, desc, mode, must_chmod); - -# elif HAVE_STATACL /* older AIX */ - - if (from_mode) - ret = context_acl_from_mode (ctx); - - if (ret == 0 && ctx->have_u) - { - if (desc != -1) - ret = fchacl (desc, &ctx->u.a, ctx->u.a.acl_len); - else - ret = chacl ((char *) name, &ctx->u.a, ctx->u.a.acl_len); - if (ret < 0) - { - if (errno == ENOSYS && from_mode) - ret = 0; - } - else - *acls_set = true; - } - -# elif HAVE_ACLSORT /* NonStop Kernel */ - - if (from_mode) - ret = context_acl_from_mode (ctx); - - if (ret == 0 && ctx->count) - { - ret = acl ((char *) name, ACL_SET, ctx->count, ctx->entries); - if (ret != 0) - { - if (!acl_nontrivial (ctx->count, ctx->entries)) - ret = 0; - } - else - *acls_set = true; - } - -# else /* No ACLs */ - - /* Nothing to do. */ - -# endif - - return ret; -} -#endif - -/* If DESC is a valid file descriptor use fchmod to change the - file's mode to MODE on systems that have fchmod. On systems - that don't have fchmod and if DESC is invalid, use chmod on - NAME instead. - Return 0 if successful. Return -1 and set errno upon failure. */ - -int -chmod_or_fchmod (const char *name, int desc, mode_t mode) -{ - if (HAVE_FCHMOD && desc != -1) - return fchmod (desc, mode); - else - return chmod (name, mode); -} - -/* Set the permissions in CTX on a file. If DESC is a valid file descriptor, - use file descriptor operations, else use filename based operations on NAME. - If access control lists are not available, fchmod the target file to the - mode in CTX. Also sets the non-permission bits of the destination file - (S_ISUID, S_ISGID, S_ISVTX) to those from the mode in CTX if any are set. - Return 0 if successful. Return -1 and set errno upon failure. */ - -int -set_permissions (struct permission_context *ctx, const char *name, int desc) -{ - _GL_UNUSED bool acls_set = false; - bool early_chmod; - bool must_chmod = false; - int ret = 0; - -#if USE_ACL -# if HAVE_STATACL - /* older AIX */ - /* There is no need to call chmod_or_fchmod, since the mode - bits S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ - - early_chmod = false; -# else - /* All other platforms */ - /* On Cygwin, it is necessary to call chmod before acl, because - chmod can change the contents of the ACL (in ways that don't - change the allowed accesses, but still visible). */ - - early_chmod = (! MODE_INSIDE_ACL || (ctx->mode & (S_ISUID | S_ISGID | S_ISVTX))); -# endif -#else - /* No ACLs */ - - early_chmod = true; -#endif - - if (early_chmod) - { - ret = chmod_or_fchmod (name, desc, ctx->mode); - if (ret != 0) - return -1; - } - -#if USE_ACL - ret = set_acls (ctx, name, desc, false, &must_chmod, &acls_set); - if (! acls_set) - { - int saved_errno = ret ? errno : 0; - - /* If we can't set an acl which we expect to be able to set, try setting - the permissions to ctx->mode. Due to possible inherited permissions, - we cannot simply chmod. */ - - ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set); - if (! acls_set) - must_chmod = true; - - if (saved_errno) - { - errno = saved_errno; - ret = -1; - } - } -#endif - - if (must_chmod && ! early_chmod) - { - int saved_errno = ret ? errno : 0; - - ret = chmod_or_fchmod (name, desc, ctx->mode); - - if (saved_errno) - { - errno = saved_errno; - ret = -1; - } - } - - return ret; -} diff --git a/xcompile/lib/sha1.c b/xcompile/lib/sha1.c deleted file mode 100644 index 80f0b7a3314..00000000000 --- a/xcompile/lib/sha1.c +++ /dev/null @@ -1,360 +0,0 @@ -/* sha1.c - Functions to compute SHA1 message digest of files or - memory blocks according to the NIST specification FIPS-180-1. - - Copyright (C) 2000-2001, 2003-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Scott G. Miller - Credits: - Robert Klep -- Expansion function fix -*/ - -#include - -/* Specification. */ -#if HAVE_OPENSSL_SHA1 -# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE -#endif -#include "sha1.h" - -#include -#include - -#include -#ifdef WORDS_BIGENDIAN -# define SWAP(n) (n) -#else -# define SWAP(n) bswap_32 (n) -#endif - -#if ! HAVE_OPENSSL_SHA1 - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Take a pointer to a 160 bit block of data (five 32 bit ints) and - initialize it to the start constants of the SHA1 algorithm. This - must be called before using hash in the call to sha1_hash. */ -void -sha1_init_ctx (struct sha1_ctx *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - ctx->E = 0xc3d2e1f0; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the 4 byte value from v into the memory location pointed to by *cp, - If your architecture allows unaligned access this is equivalent to - * (uint32_t *) cp = v */ -static void -set_uint32 (char *cp, uint32_t v) -{ - memcpy (cp, &v, sizeof v); -} - -/* Put result from CTX in first 20 bytes following RESBUF. The result - must be in little endian byte order. */ -void * -sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) -{ - char *r = resbuf; - set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); - set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); - set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); - set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); - set_uint32 (r + 4 * sizeof ctx->E, SWAP (ctx->E)); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -void * -sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) -{ - /* Take yet unprocessed bytes into account. */ - uint32_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3); - - memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha1_process_block (ctx->buffer, size * 4, ctx); - - return sha1_read_ctx (ctx, resbuf); -} - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -sha1_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha1_ctx ctx; - - /* Initialize the computation context. */ - sha1_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha1_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha1_finish_ctx (&ctx, resblock); -} - -void -sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) - { - sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy (ctx->buffer, - &((char *) ctx->buffer)[(left_over + add) & ~63], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 64) - { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) - if (UNALIGNED_P (buffer)) - while (len > 64) - { - sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - else -#endif - { - sha1_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - size_t left_over = ctx->buflen; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, len); - left_over += len; - if (left_over >= 64) - { - sha1_process_block (ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy (ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between md5.c and sha1.c --- */ - -/* SHA1 round constants */ -#define K1 0x5a827999 -#define K2 0x6ed9eba1 -#define K3 0x8f1bbcdc -#define K4 0xca62c1d6 - -/* Round functions. Note that F2 is the same as F4. */ -#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) -#define F2(B,C,D) (B ^ C ^ D) -#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) -#define F4(B,C,D) (B ^ C ^ D) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void -sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) -{ - const uint32_t *words = buffer; - size_t nwords = len / sizeof (uint32_t); - const uint32_t *endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->A; - uint32_t b = ctx->B; - uint32_t c = ctx->C; - uint32_t d = ctx->D; - uint32_t e = ctx->E; - uint32_t lolen = len; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((uint32_t) (x) >> (32 - (n)))) - -#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ - ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ - , (x[I&0x0f] = rol(tm, 1)) ) - -#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ - + F( B, C, D ) \ - + K \ - + M; \ - B = rol( B, 30 ); \ - } while(0) - - while (words < endp) - { - uint32_t tm; - int t; - for (t = 0; t < 16; t++) - { - x[t] = SWAP (*words); - words++; - } - - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); - R( e, a, b, c, d, F1, K1, M(16) ); - R( d, e, a, b, c, F1, K1, M(17) ); - R( c, d, e, a, b, F1, K1, M(18) ); - R( b, c, d, e, a, F1, K1, M(19) ); - R( a, b, c, d, e, F2, K2, M(20) ); - R( e, a, b, c, d, F2, K2, M(21) ); - R( d, e, a, b, c, F2, K2, M(22) ); - R( c, d, e, a, b, F2, K2, M(23) ); - R( b, c, d, e, a, F2, K2, M(24) ); - R( a, b, c, d, e, F2, K2, M(25) ); - R( e, a, b, c, d, F2, K2, M(26) ); - R( d, e, a, b, c, F2, K2, M(27) ); - R( c, d, e, a, b, F2, K2, M(28) ); - R( b, c, d, e, a, F2, K2, M(29) ); - R( a, b, c, d, e, F2, K2, M(30) ); - R( e, a, b, c, d, F2, K2, M(31) ); - R( d, e, a, b, c, F2, K2, M(32) ); - R( c, d, e, a, b, F2, K2, M(33) ); - R( b, c, d, e, a, F2, K2, M(34) ); - R( a, b, c, d, e, F2, K2, M(35) ); - R( e, a, b, c, d, F2, K2, M(36) ); - R( d, e, a, b, c, F2, K2, M(37) ); - R( c, d, e, a, b, F2, K2, M(38) ); - R( b, c, d, e, a, F2, K2, M(39) ); - R( a, b, c, d, e, F3, K3, M(40) ); - R( e, a, b, c, d, F3, K3, M(41) ); - R( d, e, a, b, c, F3, K3, M(42) ); - R( c, d, e, a, b, F3, K3, M(43) ); - R( b, c, d, e, a, F3, K3, M(44) ); - R( a, b, c, d, e, F3, K3, M(45) ); - R( e, a, b, c, d, F3, K3, M(46) ); - R( d, e, a, b, c, F3, K3, M(47) ); - R( c, d, e, a, b, F3, K3, M(48) ); - R( b, c, d, e, a, F3, K3, M(49) ); - R( a, b, c, d, e, F3, K3, M(50) ); - R( e, a, b, c, d, F3, K3, M(51) ); - R( d, e, a, b, c, F3, K3, M(52) ); - R( c, d, e, a, b, F3, K3, M(53) ); - R( b, c, d, e, a, F3, K3, M(54) ); - R( a, b, c, d, e, F3, K3, M(55) ); - R( e, a, b, c, d, F3, K3, M(56) ); - R( d, e, a, b, c, F3, K3, M(57) ); - R( c, d, e, a, b, F3, K3, M(58) ); - R( b, c, d, e, a, F3, K3, M(59) ); - R( a, b, c, d, e, F4, K4, M(60) ); - R( e, a, b, c, d, F4, K4, M(61) ); - R( d, e, a, b, c, F4, K4, M(62) ); - R( c, d, e, a, b, F4, K4, M(63) ); - R( b, c, d, e, a, F4, K4, M(64) ); - R( a, b, c, d, e, F4, K4, M(65) ); - R( e, a, b, c, d, F4, K4, M(66) ); - R( d, e, a, b, c, F4, K4, M(67) ); - R( c, d, e, a, b, F4, K4, M(68) ); - R( b, c, d, e, a, F4, K4, M(69) ); - R( a, b, c, d, e, F4, K4, M(70) ); - R( e, a, b, c, d, F4, K4, M(71) ); - R( d, e, a, b, c, F4, K4, M(72) ); - R( c, d, e, a, b, F4, K4, M(73) ); - R( b, c, d, e, a, F4, K4, M(74) ); - R( a, b, c, d, e, F4, K4, M(75) ); - R( e, a, b, c, d, F4, K4, M(76) ); - R( d, e, a, b, c, F4, K4, M(77) ); - R( c, d, e, a, b, F4, K4, M(78) ); - R( b, c, d, e, a, F4, K4, M(79) ); - - a = ctx->A += a; - b = ctx->B += b; - c = ctx->C += c; - d = ctx->D += d; - e = ctx->E += e; - } -} - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sha1.h b/xcompile/lib/sha1.h deleted file mode 100644 index 5a58b567ceb..00000000000 --- a/xcompile/lib/sha1.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Declarations of functions and data types used for SHA1 sum - library functions. - Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2023 Free Software - Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef SHA1_H -# define SHA1_H 1 - -# include -# include - -# if HAVE_OPENSSL_SHA1 -# ifndef OPENSSL_API_COMPAT -# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ -# endif -# include -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -# define SHA1_DIGEST_SIZE 20 - -# if HAVE_OPENSSL_SHA1 -# define GL_OPENSSL_NAME 1 -# include "gl_openssl.h" -# else -/* Structure to save state of computation between the single steps. */ -struct sha1_ctx -{ - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - uint32_t E; - - uint32_t total[2]; - uint32_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha1_init_ctx (struct sha1_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha1_process_block (const void *buffer, size_t len, - struct sha1_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha1_process_bytes (const void *buffer, size_t len, - struct sha1_ctx *ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 20 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *restrict resbuf); - - -/* Put result from CTX in first 20 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *restrict resbuf); - - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *sha1_buffer (const char *buffer, size_t len, - void *restrict resblock); - -# endif - -/* Compute SHA1 message digest for bytes read from STREAM. - STREAM is an open file stream. Regular files are handled more efficiently. - The contents of STREAM from its current position to its end will be read. - The case that the last operation on STREAM was an 'ungetc' is not supported. - The resulting message digest number will be written into the 20 bytes - beginning at RESBLOCK. */ -extern int sha1_stream (FILE *stream, void *resblock); - - -# ifdef __cplusplus -} -# endif - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sha256.c b/xcompile/lib/sha256.c deleted file mode 100644 index e5fea02bc2e..00000000000 --- a/xcompile/lib/sha256.c +++ /dev/null @@ -1,432 +0,0 @@ -/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -#include - -/* Specification. */ -#if HAVE_OPENSSL_SHA256 -# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE -#endif -#include "sha256.h" - -#include -#include - -#include -#ifdef WORDS_BIGENDIAN -# define SWAP(n) (n) -#else -# define SWAP(n) bswap_32 (n) -#endif - -#if ! HAVE_OPENSSL_SHA256 - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* - Takes a pointer to a 256 bit block of data (eight 32 bit ints) and - initializes it to the start constants of the SHA256 algorithm. This - must be called before using hash in the call to sha256_hash -*/ -void -sha256_init_ctx (struct sha256_ctx *ctx) -{ - ctx->state[0] = 0x6a09e667UL; - ctx->state[1] = 0xbb67ae85UL; - ctx->state[2] = 0x3c6ef372UL; - ctx->state[3] = 0xa54ff53aUL; - ctx->state[4] = 0x510e527fUL; - ctx->state[5] = 0x9b05688cUL; - ctx->state[6] = 0x1f83d9abUL; - ctx->state[7] = 0x5be0cd19UL; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -void -sha224_init_ctx (struct sha256_ctx *ctx) -{ - ctx->state[0] = 0xc1059ed8UL; - ctx->state[1] = 0x367cd507UL; - ctx->state[2] = 0x3070dd17UL; - ctx->state[3] = 0xf70e5939UL; - ctx->state[4] = 0xffc00b31UL; - ctx->state[5] = 0x68581511UL; - ctx->state[6] = 0x64f98fa7UL; - ctx->state[7] = 0xbefa4fa4UL; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the value from v into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void -set_uint32 (char *cp, uint32_t v) -{ - memcpy (cp, &v, sizeof v); -} - -/* Put result from CTX in first 32 bytes following RESBUF. - The result must be in little endian byte order. */ -void * -sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf) -{ - int i; - char *r = resbuf; - - for (i = 0; i < 8; i++) - set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); - - return resbuf; -} - -void * -sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf) -{ - int i; - char *r = resbuf; - - for (i = 0; i < 7; i++) - set_uint32 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void -sha256_conclude_ctx (struct sha256_ctx *ctx) -{ - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. - Use set_uint32 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint32 ((char *) &ctx->buffer[size - 2], - SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29))); - set_uint32 ((char *) &ctx->buffer[size - 1], - SWAP (ctx->total[0] << 3)); - - memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha256_process_block (ctx->buffer, size * 4, ctx); -} - -void * -sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf) -{ - sha256_conclude_ctx (ctx); - return sha256_read_ctx (ctx, resbuf); -} - -void * -sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf) -{ - sha256_conclude_ctx (ctx); - return sha224_read_ctx (ctx, resbuf); -} - -/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -sha256_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha256_ctx ctx; - - /* Initialize the computation context. */ - sha256_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha256_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha256_finish_ctx (&ctx, resblock); -} - -void * -sha224_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha256_ctx ctx; - - /* Initialize the computation context. */ - sha224_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha256_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha224_finish_ctx (&ctx, resblock); -} - -void -sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) - { - sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy (ctx->buffer, - &((char *) ctx->buffer)[(left_over + add) & ~63], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 64) - { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (uint32_t) != 0) - if (UNALIGNED_P (buffer)) - while (len > 64) - { - sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - else -#endif - { - sha256_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - size_t left_over = ctx->buflen; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, len); - left_over += len; - if (left_over >= 64) - { - sha256_process_block (ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy (ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha256.c --- */ - -/* SHA256 round constants */ -#define K(I) sha256_round_constants[I] -static const uint32_t sha256_round_constants[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, - 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, - 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, - 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, - 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, - 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, - 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, - 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, - 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, -}; - -/* Round functions. */ -#define F2(A,B,C) ( ( A & B ) | ( C & ( A | B ) ) ) -#define F1(E,F,G) ( G ^ ( E & ( F ^ G ) ) ) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void -sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx) -{ - const uint32_t *words = buffer; - size_t nwords = len / sizeof (uint32_t); - const uint32_t *endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->state[0]; - uint32_t b = ctx->state[1]; - uint32_t c = ctx->state[2]; - uint32_t d = ctx->state[3]; - uint32_t e = ctx->state[4]; - uint32_t f = ctx->state[5]; - uint32_t g = ctx->state[6]; - uint32_t h = ctx->state[7]; - uint32_t lolen = len; - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define S0(x) (rol(x,25)^rol(x,14)^(x>>3)) -#define S1(x) (rol(x,15)^rol(x,13)^(x>>10)) -#define SS0(x) (rol(x,30)^rol(x,19)^rol(x,10)) -#define SS1(x) (rol(x,26)^rol(x,21)^rol(x,7)) - -#define M(I) ( tm = S1(x[(I-2)&0x0f]) + x[(I-7)&0x0f] \ - + S0(x[(I-15)&0x0f]) + x[I&0x0f] \ - , x[I&0x0f] = tm ) - -#define R(A,B,C,D,E,F,G,H,K,M) do { t0 = SS0(A) + F2(A,B,C); \ - t1 = H + SS1(E) \ - + F1(E,F,G) \ - + K \ - + M; \ - D += t1; H = t0 + t1; \ - } while(0) - - while (words < endp) - { - uint32_t tm; - uint32_t t0, t1; - int t; - /* FIXME: see sha1.c for a better implementation. */ - for (t = 0; t < 16; t++) - { - x[t] = SWAP (*words); - words++; - } - - R( a, b, c, d, e, f, g, h, K( 0), x[ 0] ); - R( h, a, b, c, d, e, f, g, K( 1), x[ 1] ); - R( g, h, a, b, c, d, e, f, K( 2), x[ 2] ); - R( f, g, h, a, b, c, d, e, K( 3), x[ 3] ); - R( e, f, g, h, a, b, c, d, K( 4), x[ 4] ); - R( d, e, f, g, h, a, b, c, K( 5), x[ 5] ); - R( c, d, e, f, g, h, a, b, K( 6), x[ 6] ); - R( b, c, d, e, f, g, h, a, K( 7), x[ 7] ); - R( a, b, c, d, e, f, g, h, K( 8), x[ 8] ); - R( h, a, b, c, d, e, f, g, K( 9), x[ 9] ); - R( g, h, a, b, c, d, e, f, K(10), x[10] ); - R( f, g, h, a, b, c, d, e, K(11), x[11] ); - R( e, f, g, h, a, b, c, d, K(12), x[12] ); - R( d, e, f, g, h, a, b, c, K(13), x[13] ); - R( c, d, e, f, g, h, a, b, K(14), x[14] ); - R( b, c, d, e, f, g, h, a, K(15), x[15] ); - R( a, b, c, d, e, f, g, h, K(16), M(16) ); - R( h, a, b, c, d, e, f, g, K(17), M(17) ); - R( g, h, a, b, c, d, e, f, K(18), M(18) ); - R( f, g, h, a, b, c, d, e, K(19), M(19) ); - R( e, f, g, h, a, b, c, d, K(20), M(20) ); - R( d, e, f, g, h, a, b, c, K(21), M(21) ); - R( c, d, e, f, g, h, a, b, K(22), M(22) ); - R( b, c, d, e, f, g, h, a, K(23), M(23) ); - R( a, b, c, d, e, f, g, h, K(24), M(24) ); - R( h, a, b, c, d, e, f, g, K(25), M(25) ); - R( g, h, a, b, c, d, e, f, K(26), M(26) ); - R( f, g, h, a, b, c, d, e, K(27), M(27) ); - R( e, f, g, h, a, b, c, d, K(28), M(28) ); - R( d, e, f, g, h, a, b, c, K(29), M(29) ); - R( c, d, e, f, g, h, a, b, K(30), M(30) ); - R( b, c, d, e, f, g, h, a, K(31), M(31) ); - R( a, b, c, d, e, f, g, h, K(32), M(32) ); - R( h, a, b, c, d, e, f, g, K(33), M(33) ); - R( g, h, a, b, c, d, e, f, K(34), M(34) ); - R( f, g, h, a, b, c, d, e, K(35), M(35) ); - R( e, f, g, h, a, b, c, d, K(36), M(36) ); - R( d, e, f, g, h, a, b, c, K(37), M(37) ); - R( c, d, e, f, g, h, a, b, K(38), M(38) ); - R( b, c, d, e, f, g, h, a, K(39), M(39) ); - R( a, b, c, d, e, f, g, h, K(40), M(40) ); - R( h, a, b, c, d, e, f, g, K(41), M(41) ); - R( g, h, a, b, c, d, e, f, K(42), M(42) ); - R( f, g, h, a, b, c, d, e, K(43), M(43) ); - R( e, f, g, h, a, b, c, d, K(44), M(44) ); - R( d, e, f, g, h, a, b, c, K(45), M(45) ); - R( c, d, e, f, g, h, a, b, K(46), M(46) ); - R( b, c, d, e, f, g, h, a, K(47), M(47) ); - R( a, b, c, d, e, f, g, h, K(48), M(48) ); - R( h, a, b, c, d, e, f, g, K(49), M(49) ); - R( g, h, a, b, c, d, e, f, K(50), M(50) ); - R( f, g, h, a, b, c, d, e, K(51), M(51) ); - R( e, f, g, h, a, b, c, d, K(52), M(52) ); - R( d, e, f, g, h, a, b, c, K(53), M(53) ); - R( c, d, e, f, g, h, a, b, K(54), M(54) ); - R( b, c, d, e, f, g, h, a, K(55), M(55) ); - R( a, b, c, d, e, f, g, h, K(56), M(56) ); - R( h, a, b, c, d, e, f, g, K(57), M(57) ); - R( g, h, a, b, c, d, e, f, K(58), M(58) ); - R( f, g, h, a, b, c, d, e, K(59), M(59) ); - R( e, f, g, h, a, b, c, d, K(60), M(60) ); - R( d, e, f, g, h, a, b, c, K(61), M(61) ); - R( c, d, e, f, g, h, a, b, K(62), M(62) ); - R( b, c, d, e, f, g, h, a, K(63), M(63) ); - - a = ctx->state[0] += a; - b = ctx->state[1] += b; - c = ctx->state[2] += c; - d = ctx->state[3] += d; - e = ctx->state[4] += e; - f = ctx->state[5] += f; - g = ctx->state[6] += g; - h = ctx->state[7] += h; - } -} - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sha256.h b/xcompile/lib/sha256.h deleted file mode 100644 index 2879477e89c..00000000000 --- a/xcompile/lib/sha256.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Declarations of functions and data types used for SHA256 and SHA224 sum - library functions. - Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef SHA256_H -# define SHA256_H 1 - -# include -# include - -# if HAVE_OPENSSL_SHA256 -# ifndef OPENSSL_API_COMPAT -# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ -# endif -# include -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -enum { SHA224_DIGEST_SIZE = 224 / 8 }; -enum { SHA256_DIGEST_SIZE = 256 / 8 }; - -# if HAVE_OPENSSL_SHA256 -# define GL_OPENSSL_NAME 224 -# include "gl_openssl.h" -# define GL_OPENSSL_NAME 256 -# include "gl_openssl.h" -# else -/* Structure to save state of computation between the single steps. */ -struct sha256_ctx -{ - uint32_t state[8]; - - uint32_t total[2]; - size_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha256_init_ctx (struct sha256_ctx *ctx); -extern void sha224_init_ctx (struct sha256_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha256_process_block (const void *buffer, size_t len, - struct sha256_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha256_process_bytes (const void *buffer, size_t len, - struct sha256_ctx *ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 32 (28) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf); -extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf); - - -/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void *sha256_read_ctx (const struct sha256_ctx *ctx, - void *restrict resbuf); -extern void *sha224_read_ctx (const struct sha256_ctx *ctx, - void *restrict resbuf); - - -/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *sha256_buffer (const char *buffer, size_t len, - void *restrict resblock); -extern void *sha224_buffer (const char *buffer, size_t len, - void *restrict resblock); - -# endif - -/* Compute SHA256 (SHA224) message digest for bytes read from STREAM. - STREAM is an open file stream. Regular files are handled more efficiently. - The contents of STREAM from its current position to its end will be read. - The case that the last operation on STREAM was an 'ungetc' is not supported. - The resulting message digest number will be written into the 32 (28) bytes - beginning at RESBLOCK. */ -extern int sha256_stream (FILE *stream, void *resblock); -extern int sha224_stream (FILE *stream, void *resblock); - - -# ifdef __cplusplus -} -# endif - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sha512.c b/xcompile/lib/sha512.c deleted file mode 100644 index 8ca7fa319f5..00000000000 --- a/xcompile/lib/sha512.c +++ /dev/null @@ -1,477 +0,0 @@ -/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -#include - -/* Specification. */ -#if HAVE_OPENSSL_SHA512 -# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE -#endif -#include "sha512.h" - -#include -#include - -#include -#ifdef WORDS_BIGENDIAN -# define SWAP(n) (n) -#else -# define SWAP(n) bswap_64 (n) -#endif - -#if ! HAVE_OPENSSL_SHA512 - -/* This array contains the bytes used to pad the buffer to the next - 128-byte boundary. */ -static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* - Takes a pointer to a 512 bit block of data (eight 64 bit ints) and - initializes it to the start constants of the SHA512 algorithm. This - must be called before using hash in the call to sha512_hash -*/ -void -sha512_init_ctx (struct sha512_ctx *ctx) -{ - ctx->state[0] = u64hilo (0x6a09e667, 0xf3bcc908); - ctx->state[1] = u64hilo (0xbb67ae85, 0x84caa73b); - ctx->state[2] = u64hilo (0x3c6ef372, 0xfe94f82b); - ctx->state[3] = u64hilo (0xa54ff53a, 0x5f1d36f1); - ctx->state[4] = u64hilo (0x510e527f, 0xade682d1); - ctx->state[5] = u64hilo (0x9b05688c, 0x2b3e6c1f); - ctx->state[6] = u64hilo (0x1f83d9ab, 0xfb41bd6b); - ctx->state[7] = u64hilo (0x5be0cd19, 0x137e2179); - - ctx->total[0] = ctx->total[1] = u64lo (0); - ctx->buflen = 0; -} - -void -sha384_init_ctx (struct sha512_ctx *ctx) -{ - ctx->state[0] = u64hilo (0xcbbb9d5d, 0xc1059ed8); - ctx->state[1] = u64hilo (0x629a292a, 0x367cd507); - ctx->state[2] = u64hilo (0x9159015a, 0x3070dd17); - ctx->state[3] = u64hilo (0x152fecd8, 0xf70e5939); - ctx->state[4] = u64hilo (0x67332667, 0xffc00b31); - ctx->state[5] = u64hilo (0x8eb44a87, 0x68581511); - ctx->state[6] = u64hilo (0xdb0c2e0d, 0x64f98fa7); - ctx->state[7] = u64hilo (0x47b5481d, 0xbefa4fa4); - - ctx->total[0] = ctx->total[1] = u64lo (0); - ctx->buflen = 0; -} - -/* Copy the value from V into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void -set_uint64 (char *cp, u64 v) -{ - memcpy (cp, &v, sizeof v); -} - -/* Put result from CTX in first 64 bytes following RESBUF. - The result must be in little endian byte order. */ -void * -sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf) -{ - int i; - char *r = resbuf; - - for (i = 0; i < 8; i++) - set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); - - return resbuf; -} - -void * -sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf) -{ - int i; - char *r = resbuf; - - for (i = 0; i < 6; i++) - set_uint64 (r + i * sizeof ctx->state[0], SWAP (ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void -sha512_conclude_ctx (struct sha512_ctx *ctx) -{ - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8; - - /* Now count remaining bytes. */ - ctx->total[0] = u64plus (ctx->total[0], u64lo (bytes)); - if (u64lt (ctx->total[0], u64lo (bytes))) - ctx->total[1] = u64plus (ctx->total[1], u64lo (1)); - - /* Put the 128-bit file length in *bits* at the end of the buffer. - Use set_uint64 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint64 ((char *) &ctx->buffer[size - 2], - SWAP (u64or (u64shl (ctx->total[1], 3), - u64shr (ctx->total[0], 61)))); - set_uint64 ((char *) &ctx->buffer[size - 1], - SWAP (u64shl (ctx->total[0], 3))); - - memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 8 - bytes); - - /* Process last bytes. */ - sha512_process_block (ctx->buffer, size * 8, ctx); -} - -void * -sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf) -{ - sha512_conclude_ctx (ctx); - return sha512_read_ctx (ctx, resbuf); -} - -void * -sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf) -{ - sha512_conclude_ctx (ctx); - return sha384_read_ctx (ctx, resbuf); -} - -/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -sha512_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha512_ctx ctx; - - /* Initialize the computation context. */ - sha512_init_ctx (&ctx); - - /* Process whole buffer but last len % 128 bytes. */ - sha512_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha512_finish_ctx (&ctx, resblock); -} - -void * -sha384_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha512_ctx ctx; - - /* Initialize the computation context. */ - sha384_init_ctx (&ctx); - - /* Process whole buffer but last len % 128 bytes. */ - sha512_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha384_finish_ctx (&ctx, resblock); -} - -void -sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 256 - left_over > len ? len : 256 - left_over; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 128) - { - sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx); - - ctx->buflen &= 127; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 128 ≤ (left_over + add) & ~127. */ - memcpy (ctx->buffer, - &((char *) ctx->buffer)[(left_over + add) & ~127], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 128) - { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -# define UNALIGNED_P(p) ((uintptr_t) (p) % alignof (u64) != 0) - if (UNALIGNED_P (buffer)) - while (len > 128) - { - sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128, ctx); - buffer = (const char *) buffer + 128; - len -= 128; - } - else -#endif - { - sha512_process_block (buffer, len & ~127, ctx); - buffer = (const char *) buffer + (len & ~127); - len &= 127; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - size_t left_over = ctx->buflen; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, len); - left_over += len; - if (left_over >= 128) - { - sha512_process_block (ctx->buffer, 128, ctx); - left_over -= 128; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 128. */ - memcpy (ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha512.c --- */ - -/* SHA512 round constants */ -#define K(I) sha512_round_constants[I] -static u64 const sha512_round_constants[80] = { - u64init (0x428a2f98, 0xd728ae22), u64init (0x71374491, 0x23ef65cd), - u64init (0xb5c0fbcf, 0xec4d3b2f), u64init (0xe9b5dba5, 0x8189dbbc), - u64init (0x3956c25b, 0xf348b538), u64init (0x59f111f1, 0xb605d019), - u64init (0x923f82a4, 0xaf194f9b), u64init (0xab1c5ed5, 0xda6d8118), - u64init (0xd807aa98, 0xa3030242), u64init (0x12835b01, 0x45706fbe), - u64init (0x243185be, 0x4ee4b28c), u64init (0x550c7dc3, 0xd5ffb4e2), - u64init (0x72be5d74, 0xf27b896f), u64init (0x80deb1fe, 0x3b1696b1), - u64init (0x9bdc06a7, 0x25c71235), u64init (0xc19bf174, 0xcf692694), - u64init (0xe49b69c1, 0x9ef14ad2), u64init (0xefbe4786, 0x384f25e3), - u64init (0x0fc19dc6, 0x8b8cd5b5), u64init (0x240ca1cc, 0x77ac9c65), - u64init (0x2de92c6f, 0x592b0275), u64init (0x4a7484aa, 0x6ea6e483), - u64init (0x5cb0a9dc, 0xbd41fbd4), u64init (0x76f988da, 0x831153b5), - u64init (0x983e5152, 0xee66dfab), u64init (0xa831c66d, 0x2db43210), - u64init (0xb00327c8, 0x98fb213f), u64init (0xbf597fc7, 0xbeef0ee4), - u64init (0xc6e00bf3, 0x3da88fc2), u64init (0xd5a79147, 0x930aa725), - u64init (0x06ca6351, 0xe003826f), u64init (0x14292967, 0x0a0e6e70), - u64init (0x27b70a85, 0x46d22ffc), u64init (0x2e1b2138, 0x5c26c926), - u64init (0x4d2c6dfc, 0x5ac42aed), u64init (0x53380d13, 0x9d95b3df), - u64init (0x650a7354, 0x8baf63de), u64init (0x766a0abb, 0x3c77b2a8), - u64init (0x81c2c92e, 0x47edaee6), u64init (0x92722c85, 0x1482353b), - u64init (0xa2bfe8a1, 0x4cf10364), u64init (0xa81a664b, 0xbc423001), - u64init (0xc24b8b70, 0xd0f89791), u64init (0xc76c51a3, 0x0654be30), - u64init (0xd192e819, 0xd6ef5218), u64init (0xd6990624, 0x5565a910), - u64init (0xf40e3585, 0x5771202a), u64init (0x106aa070, 0x32bbd1b8), - u64init (0x19a4c116, 0xb8d2d0c8), u64init (0x1e376c08, 0x5141ab53), - u64init (0x2748774c, 0xdf8eeb99), u64init (0x34b0bcb5, 0xe19b48a8), - u64init (0x391c0cb3, 0xc5c95a63), u64init (0x4ed8aa4a, 0xe3418acb), - u64init (0x5b9cca4f, 0x7763e373), u64init (0x682e6ff3, 0xd6b2b8a3), - u64init (0x748f82ee, 0x5defb2fc), u64init (0x78a5636f, 0x43172f60), - u64init (0x84c87814, 0xa1f0ab72), u64init (0x8cc70208, 0x1a6439ec), - u64init (0x90befffa, 0x23631e28), u64init (0xa4506ceb, 0xde82bde9), - u64init (0xbef9a3f7, 0xb2c67915), u64init (0xc67178f2, 0xe372532b), - u64init (0xca273ece, 0xea26619c), u64init (0xd186b8c7, 0x21c0c207), - u64init (0xeada7dd6, 0xcde0eb1e), u64init (0xf57d4f7f, 0xee6ed178), - u64init (0x06f067aa, 0x72176fba), u64init (0x0a637dc5, 0xa2c898a6), - u64init (0x113f9804, 0xbef90dae), u64init (0x1b710b35, 0x131c471b), - u64init (0x28db77f5, 0x23047d84), u64init (0x32caab7b, 0x40c72493), - u64init (0x3c9ebe0a, 0x15c9bebc), u64init (0x431d67c4, 0x9c100d4c), - u64init (0x4cc5d4be, 0xcb3e42b6), u64init (0x597f299c, 0xfc657e2a), - u64init (0x5fcb6fab, 0x3ad6faec), u64init (0x6c44198c, 0x4a475817), -}; - -/* Round functions. */ -#define F2(A, B, C) u64or (u64and (A, B), u64and (C, u64or (A, B))) -#define F1(E, F, G) u64xor (G, u64and (E, u64xor (F, G))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 128 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void -sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx) -{ - u64 const *words = buffer; - u64 const *endp = words + len / sizeof (u64); - u64 x[16]; - u64 a = ctx->state[0]; - u64 b = ctx->state[1]; - u64 c = ctx->state[2]; - u64 d = ctx->state[3]; - u64 e = ctx->state[4]; - u64 f = ctx->state[5]; - u64 g = ctx->state[6]; - u64 h = ctx->state[7]; - u64 lolen = u64size (len); - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^128 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] = u64plus (ctx->total[0], lolen); - ctx->total[1] = u64plus (ctx->total[1], - u64plus (u64size (len >> 31 >> 31 >> 2), - u64lo (u64lt (ctx->total[0], lolen)))); - -#define S0(x) u64xor (u64rol(x, 63), u64xor (u64rol (x, 56), u64shr (x, 7))) -#define S1(x) u64xor (u64rol (x, 45), u64xor (u64rol (x, 3), u64shr (x, 6))) -#define SS0(x) u64xor (u64rol (x, 36), u64xor (u64rol (x, 30), u64rol (x, 25))) -#define SS1(x) u64xor (u64rol(x, 50), u64xor (u64rol (x, 46), u64rol (x, 23))) - -#define M(I) (x[(I) & 15] \ - = u64plus (x[(I) & 15], \ - u64plus (S1 (x[((I) - 2) & 15]), \ - u64plus (x[((I) - 7) & 15], \ - S0 (x[((I) - 15) & 15]))))) - -#define R(A, B, C, D, E, F, G, H, K, M) \ - do \ - { \ - u64 t0 = u64plus (SS0 (A), F2 (A, B, C)); \ - u64 t1 = \ - u64plus (H, u64plus (SS1 (E), \ - u64plus (F1 (E, F, G), u64plus (K, M)))); \ - D = u64plus (D, t1); \ - H = u64plus (t0, t1); \ - } \ - while (0) - - while (words < endp) - { - int t; - /* FIXME: see sha1.c for a better implementation. */ - for (t = 0; t < 16; t++) - { - x[t] = SWAP (*words); - words++; - } - - R( a, b, c, d, e, f, g, h, K( 0), x[ 0] ); - R( h, a, b, c, d, e, f, g, K( 1), x[ 1] ); - R( g, h, a, b, c, d, e, f, K( 2), x[ 2] ); - R( f, g, h, a, b, c, d, e, K( 3), x[ 3] ); - R( e, f, g, h, a, b, c, d, K( 4), x[ 4] ); - R( d, e, f, g, h, a, b, c, K( 5), x[ 5] ); - R( c, d, e, f, g, h, a, b, K( 6), x[ 6] ); - R( b, c, d, e, f, g, h, a, K( 7), x[ 7] ); - R( a, b, c, d, e, f, g, h, K( 8), x[ 8] ); - R( h, a, b, c, d, e, f, g, K( 9), x[ 9] ); - R( g, h, a, b, c, d, e, f, K(10), x[10] ); - R( f, g, h, a, b, c, d, e, K(11), x[11] ); - R( e, f, g, h, a, b, c, d, K(12), x[12] ); - R( d, e, f, g, h, a, b, c, K(13), x[13] ); - R( c, d, e, f, g, h, a, b, K(14), x[14] ); - R( b, c, d, e, f, g, h, a, K(15), x[15] ); - R( a, b, c, d, e, f, g, h, K(16), M(16) ); - R( h, a, b, c, d, e, f, g, K(17), M(17) ); - R( g, h, a, b, c, d, e, f, K(18), M(18) ); - R( f, g, h, a, b, c, d, e, K(19), M(19) ); - R( e, f, g, h, a, b, c, d, K(20), M(20) ); - R( d, e, f, g, h, a, b, c, K(21), M(21) ); - R( c, d, e, f, g, h, a, b, K(22), M(22) ); - R( b, c, d, e, f, g, h, a, K(23), M(23) ); - R( a, b, c, d, e, f, g, h, K(24), M(24) ); - R( h, a, b, c, d, e, f, g, K(25), M(25) ); - R( g, h, a, b, c, d, e, f, K(26), M(26) ); - R( f, g, h, a, b, c, d, e, K(27), M(27) ); - R( e, f, g, h, a, b, c, d, K(28), M(28) ); - R( d, e, f, g, h, a, b, c, K(29), M(29) ); - R( c, d, e, f, g, h, a, b, K(30), M(30) ); - R( b, c, d, e, f, g, h, a, K(31), M(31) ); - R( a, b, c, d, e, f, g, h, K(32), M(32) ); - R( h, a, b, c, d, e, f, g, K(33), M(33) ); - R( g, h, a, b, c, d, e, f, K(34), M(34) ); - R( f, g, h, a, b, c, d, e, K(35), M(35) ); - R( e, f, g, h, a, b, c, d, K(36), M(36) ); - R( d, e, f, g, h, a, b, c, K(37), M(37) ); - R( c, d, e, f, g, h, a, b, K(38), M(38) ); - R( b, c, d, e, f, g, h, a, K(39), M(39) ); - R( a, b, c, d, e, f, g, h, K(40), M(40) ); - R( h, a, b, c, d, e, f, g, K(41), M(41) ); - R( g, h, a, b, c, d, e, f, K(42), M(42) ); - R( f, g, h, a, b, c, d, e, K(43), M(43) ); - R( e, f, g, h, a, b, c, d, K(44), M(44) ); - R( d, e, f, g, h, a, b, c, K(45), M(45) ); - R( c, d, e, f, g, h, a, b, K(46), M(46) ); - R( b, c, d, e, f, g, h, a, K(47), M(47) ); - R( a, b, c, d, e, f, g, h, K(48), M(48) ); - R( h, a, b, c, d, e, f, g, K(49), M(49) ); - R( g, h, a, b, c, d, e, f, K(50), M(50) ); - R( f, g, h, a, b, c, d, e, K(51), M(51) ); - R( e, f, g, h, a, b, c, d, K(52), M(52) ); - R( d, e, f, g, h, a, b, c, K(53), M(53) ); - R( c, d, e, f, g, h, a, b, K(54), M(54) ); - R( b, c, d, e, f, g, h, a, K(55), M(55) ); - R( a, b, c, d, e, f, g, h, K(56), M(56) ); - R( h, a, b, c, d, e, f, g, K(57), M(57) ); - R( g, h, a, b, c, d, e, f, K(58), M(58) ); - R( f, g, h, a, b, c, d, e, K(59), M(59) ); - R( e, f, g, h, a, b, c, d, K(60), M(60) ); - R( d, e, f, g, h, a, b, c, K(61), M(61) ); - R( c, d, e, f, g, h, a, b, K(62), M(62) ); - R( b, c, d, e, f, g, h, a, K(63), M(63) ); - R( a, b, c, d, e, f, g, h, K(64), M(64) ); - R( h, a, b, c, d, e, f, g, K(65), M(65) ); - R( g, h, a, b, c, d, e, f, K(66), M(66) ); - R( f, g, h, a, b, c, d, e, K(67), M(67) ); - R( e, f, g, h, a, b, c, d, K(68), M(68) ); - R( d, e, f, g, h, a, b, c, K(69), M(69) ); - R( c, d, e, f, g, h, a, b, K(70), M(70) ); - R( b, c, d, e, f, g, h, a, K(71), M(71) ); - R( a, b, c, d, e, f, g, h, K(72), M(72) ); - R( h, a, b, c, d, e, f, g, K(73), M(73) ); - R( g, h, a, b, c, d, e, f, K(74), M(74) ); - R( f, g, h, a, b, c, d, e, K(75), M(75) ); - R( e, f, g, h, a, b, c, d, K(76), M(76) ); - R( d, e, f, g, h, a, b, c, K(77), M(77) ); - R( c, d, e, f, g, h, a, b, K(78), M(78) ); - R( b, c, d, e, f, g, h, a, K(79), M(79) ); - - a = ctx->state[0] = u64plus (ctx->state[0], a); - b = ctx->state[1] = u64plus (ctx->state[1], b); - c = ctx->state[2] = u64plus (ctx->state[2], c); - d = ctx->state[3] = u64plus (ctx->state[3], d); - e = ctx->state[4] = u64plus (ctx->state[4], e); - f = ctx->state[5] = u64plus (ctx->state[5], f); - g = ctx->state[6] = u64plus (ctx->state[6], g); - h = ctx->state[7] = u64plus (ctx->state[7], h); - } -} - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sha512.h b/xcompile/lib/sha512.h deleted file mode 100644 index e3a98a2644c..00000000000 --- a/xcompile/lib/sha512.h +++ /dev/null @@ -1,124 +0,0 @@ -/* Declarations of functions and data types used for SHA512 and SHA384 sum - library functions. - Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef SHA512_H -# define SHA512_H 1 - -# include -# include "u64.h" - -# if HAVE_OPENSSL_SHA512 -# ifndef OPENSSL_API_COMPAT -# define OPENSSL_API_COMPAT 0x10101000L /* FIXME: Use OpenSSL 1.1+ API. */ -# endif -# include -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -enum { SHA384_DIGEST_SIZE = 384 / 8 }; -enum { SHA512_DIGEST_SIZE = 512 / 8 }; - -# if HAVE_OPENSSL_SHA512 -# define GL_OPENSSL_NAME 384 -# include "gl_openssl.h" -# define GL_OPENSSL_NAME 512 -# include "gl_openssl.h" -# else -/* Structure to save state of computation between the single steps. */ -struct sha512_ctx -{ - u64 state[8]; - - u64 total[2]; - size_t buflen; /* ≥ 0, ≤ 256 */ - u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha512_init_ctx (struct sha512_ctx *ctx); -extern void sha384_init_ctx (struct sha512_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 128!!! */ -extern void sha512_process_block (const void *buffer, size_t len, - struct sha512_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 128. */ -extern void sha512_process_bytes (const void *buffer, size_t len, - struct sha512_ctx *ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 64 (48) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf); -extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf); - - -/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void *sha512_read_ctx (const struct sha512_ctx *ctx, - void *restrict resbuf); -extern void *sha384_read_ctx (const struct sha512_ctx *ctx, - void *restrict resbuf); - - -/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *sha512_buffer (const char *buffer, size_t len, - void *restrict resblock); -extern void *sha384_buffer (const char *buffer, size_t len, - void *restrict resblock); - -# endif - -/* Compute SHA512 (SHA384) message digest for bytes read from STREAM. - STREAM is an open file stream. Regular files are handled more efficiently. - The contents of STREAM from its current position to its end will be read. - The case that the last operation on STREAM was an 'ungetc' is not supported. - The resulting message digest number will be written into the 64 (48) bytes - beginning at RESBLOCK. */ -extern int sha512_stream (FILE *stream, void *resblock); -extern int sha384_stream (FILE *stream, void *resblock); - - -# ifdef __cplusplus -} -# endif - -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/xcompile/lib/sig2str.c b/xcompile/lib/sig2str.c deleted file mode 100644 index c5219caaaed..00000000000 --- a/xcompile/lib/sig2str.c +++ /dev/null @@ -1,364 +0,0 @@ -/* sig2str.c -- convert between signal names and numbers - - Copyright (C) 2002, 2004, 2006, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -#include - -#include -#include -#include -#include -#include - -#include "sig2str.h" - -#ifndef SIGRTMIN -# define SIGRTMIN 0 -# undef SIGRTMAX -#endif -#ifndef SIGRTMAX -# define SIGRTMAX (SIGRTMIN - 1) -#endif - -#define NUMNAME(name) { SIG##name, #name } - -/* Signal names and numbers. Put the preferred name first. */ -static struct numname { int num; char const name[8]; } numname_table[] = - { - /* Signals required by POSIX 1003.1-2001 base, listed in - traditional numeric order where possible. */ -#ifdef SIGHUP - NUMNAME (HUP), -#endif -#ifdef SIGINT - NUMNAME (INT), -#endif -#ifdef SIGQUIT - NUMNAME (QUIT), -#endif -#ifdef SIGILL - NUMNAME (ILL), -#endif -#ifdef SIGTRAP - NUMNAME (TRAP), -#endif -#ifdef SIGABRT - NUMNAME (ABRT), -#endif -#ifdef SIGFPE - NUMNAME (FPE), -#endif -#ifdef SIGKILL - NUMNAME (KILL), -#endif -#ifdef SIGSEGV - NUMNAME (SEGV), -#endif - /* On Haiku, SIGSEGV == SIGBUS, but we prefer SIGSEGV to match - strsignal.c output, so SIGBUS must be listed second. */ -#ifdef SIGBUS - NUMNAME (BUS), -#endif -#ifdef SIGPIPE - NUMNAME (PIPE), -#endif -#ifdef SIGALRM - NUMNAME (ALRM), -#endif -#ifdef SIGTERM - NUMNAME (TERM), -#endif -#ifdef SIGUSR1 - NUMNAME (USR1), -#endif -#ifdef SIGUSR2 - NUMNAME (USR2), -#endif -#ifdef SIGCHLD - NUMNAME (CHLD), -#endif -#ifdef SIGURG - NUMNAME (URG), -#endif -#ifdef SIGSTOP - NUMNAME (STOP), -#endif -#ifdef SIGTSTP - NUMNAME (TSTP), -#endif -#ifdef SIGCONT - NUMNAME (CONT), -#endif -#ifdef SIGTTIN - NUMNAME (TTIN), -#endif -#ifdef SIGTTOU - NUMNAME (TTOU), -#endif - - /* Signals required by POSIX 1003.1-2001 with the XSI extension. */ -#ifdef SIGSYS - NUMNAME (SYS), -#endif -#ifdef SIGPOLL - NUMNAME (POLL), -#endif -#ifdef SIGVTALRM - NUMNAME (VTALRM), -#endif -#ifdef SIGPROF - NUMNAME (PROF), -#endif -#ifdef SIGXCPU - NUMNAME (XCPU), -#endif -#ifdef SIGXFSZ - NUMNAME (XFSZ), -#endif - - /* Unix Version 7. */ -#ifdef SIGIOT - NUMNAME (IOT), /* Older name for ABRT. */ -#endif -#ifdef SIGEMT - NUMNAME (EMT), -#endif - - /* USG Unix. */ -#ifdef SIGPHONE - NUMNAME (PHONE), -#endif -#ifdef SIGWIND - NUMNAME (WIND), -#endif - - /* Unix System V. */ -#ifdef SIGCLD - NUMNAME (CLD), -#endif -#ifdef SIGPWR - NUMNAME (PWR), -#endif - - /* GNU/Linux 2.2 and Solaris 8. */ -#ifdef SIGCANCEL - NUMNAME (CANCEL), -#endif -#ifdef SIGLWP - NUMNAME (LWP), -#endif -#ifdef SIGWAITING - NUMNAME (WAITING), -#endif -#ifdef SIGFREEZE - NUMNAME (FREEZE), -#endif -#ifdef SIGTHAW - NUMNAME (THAW), -#endif -#ifdef SIGLOST - NUMNAME (LOST), -#endif -#ifdef SIGWINCH - NUMNAME (WINCH), -#endif - - /* GNU/Linux 2.2. */ -#ifdef SIGINFO - NUMNAME (INFO), -#endif -#ifdef SIGIO - NUMNAME (IO), -#endif -#ifdef SIGSTKFLT - NUMNAME (STKFLT), -#endif - - /* AIX 7. */ -#ifdef SIGCPUFAIL - NUMNAME (CPUFAIL), -#endif - - /* AIX 5L. */ -#ifdef SIGDANGER - NUMNAME (DANGER), -#endif -#ifdef SIGGRANT - NUMNAME (GRANT), -#endif -#ifdef SIGMIGRATE - NUMNAME (MIGRATE), -#endif -#ifdef SIGMSG - NUMNAME (MSG), -#endif -#ifdef SIGPRE - NUMNAME (PRE), -#endif -#ifdef SIGRETRACT - NUMNAME (RETRACT), -#endif -#ifdef SIGSAK - NUMNAME (SAK), -#endif -#ifdef SIGSOUND - NUMNAME (SOUND), -#endif - - /* Older AIX versions. */ -#ifdef SIGALRM1 - NUMNAME (ALRM1), /* unknown; taken from Bash 2.05 */ -#endif -#ifdef SIGKAP - NUMNAME (KAP), /* Older name for SIGGRANT. */ -#endif -#ifdef SIGVIRT - NUMNAME (VIRT), /* unknown; taken from Bash 2.05 */ -#endif -#ifdef SIGWINDOW - NUMNAME (WINDOW), /* Older name for SIGWINCH. */ -#endif - - /* OpenBSD. */ -#ifdef SIGTHR - NUMNAME (THR), -#endif - - /* BeOS, Haiku */ -#ifdef SIGKILLTHR - NUMNAME (KILLTHR), -#endif - - /* Older HP-UX versions. */ -#ifdef SIGDIL - NUMNAME (DIL), -#endif - - /* native Windows */ -#ifdef SIGBREAK - NUMNAME (BREAK), -#endif - - /* Korn shell and Bash, of uncertain vintage. */ - { 0, "EXIT" } - }; - -#define NUMNAME_ENTRIES (sizeof numname_table / sizeof numname_table[0]) - -/* ISDIGIT differs from isdigit, as follows: - - Its arg may be any int or unsigned int; it need not be an unsigned char - or EOF. - - It's typically faster. - POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to - isdigit unless it's important to use the locale's definition - of "digit" even when the host does not conform to POSIX. */ -#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) - -/* Convert the signal name SIGNAME to a signal number. Return the - signal number if successful, -1 otherwise. */ - -static int -str2signum (char const *signame) -{ - if (ISDIGIT (*signame)) - { - char *endp; - long int n = strtol (signame, &endp, 10); - if (! *endp && n <= SIGNUM_BOUND) - return n; - } - else - { - unsigned int i; - for (i = 0; i < NUMNAME_ENTRIES; i++) - if (strcmp (numname_table[i].name, signame) == 0) - return numname_table[i].num; - - { - char *endp; - int rtmin = SIGRTMIN; - int rtmax = SIGRTMAX; - - if (0 < rtmin && strncmp (signame, "RTMIN", 5) == 0) - { - long int n = strtol (signame + 5, &endp, 10); - if (! *endp && 0 <= n && n <= rtmax - rtmin) - return rtmin + n; - } - else if (0 < rtmax && strncmp (signame, "RTMAX", 5) == 0) - { - long int n = strtol (signame + 5, &endp, 10); - if (! *endp && rtmin - rtmax <= n && n <= 0) - return rtmax + n; - } - } - } - - return -1; -} - -/* Convert the signal name SIGNAME to the signal number *SIGNUM. - Return 0 if successful, -1 otherwise. */ - -int -str2sig (char const *signame, int *signum) -{ - *signum = str2signum (signame); - return *signum < 0 ? -1 : 0; -} - -/* Convert SIGNUM to a signal name in SIGNAME. SIGNAME must point to - a buffer of at least SIG2STR_MAX bytes. Return 0 if successful, -1 - otherwise. */ - -int -sig2str (int signum, char *signame) -{ - unsigned int i; - for (i = 0; i < NUMNAME_ENTRIES; i++) - if (numname_table[i].num == signum) - { - strcpy (signame, numname_table[i].name); - return 0; - } - - { - int rtmin = SIGRTMIN; - int rtmax = SIGRTMAX; - int base, delta; - - if (! (rtmin <= signum && signum <= rtmax)) - return -1; - - if (signum <= rtmin + (rtmax - rtmin) / 2) - { - strcpy (signame, "RTMIN"); - base = rtmin; - } - else - { - strcpy (signame, "RTMAX"); - base = rtmax; - } - - delta = signum - base; - if (delta != 0) - sprintf (signame + 5, "%+d", delta); - return 0; - } -} diff --git a/xcompile/lib/sig2str.h b/xcompile/lib/sig2str.h deleted file mode 100644 index 1e5253658e7..00000000000 --- a/xcompile/lib/sig2str.h +++ /dev/null @@ -1,53 +0,0 @@ -/* sig2str.h -- convert between signal names and numbers - - Copyright (C) 2002, 2005, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -#include - -/* Don't override system declarations of SIG2STR_MAX, sig2str, str2sig. */ -#ifndef SIG2STR_MAX - -# include "intprops.h" - -/* Size of a buffer needed to hold a signal name like "HUP". */ -# define SIG2STR_MAX (sizeof "SIGRTMAX" + INT_STRLEN_BOUND (int) - 1) - -#ifdef __cplusplus -extern "C" { -#endif - -int sig2str (int, char *); -int str2sig (char const *, int *); - -#ifdef __cplusplus -} -#endif - -#endif - -/* An upper bound on signal numbers allowed by the system. */ - -#if defined _sys_nsig -# define SIGNUM_BOUND (_sys_nsig - 1) -#elif defined _SIG_MAXSIG -# define SIGNUM_BOUND (_SIG_MAXSIG - 2) /* FreeBSD >= 7. */ -#elif defined NSIG -# define SIGNUM_BOUND (NSIG - 1) -#else -# define SIGNUM_BOUND 64 -#endif diff --git a/xcompile/lib/sigdescr_np.c b/xcompile/lib/sigdescr_np.c deleted file mode 100644 index fc8a4ad47a2..00000000000 --- a/xcompile/lib/sigdescr_np.c +++ /dev/null @@ -1,376 +0,0 @@ -/* English descriptions of signals. - Copyright (C) 2020-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Bruno Haible , 2020. */ - -#include - -/* Specification. */ -#include - -#include - -const char * -sigdescr_np (int sig) -{ - /* Note: Some platforms (glibc, FreeBSD, NetBSD, OpenBSD, AIX, IRIX, Haiku, - Android) have an array 'sys_siglist'. (On AIX, you need to declare it - yourself, and it has fewer than NSIG elements.) Its contents varies - depending on the OS. - On other OSes, you can invoke strsignal (sig) in the C locale. - In the code below, we show the differences. - You can see how cryptic some of these strings are. We try to pick more - understandable wordings. */ - - switch (sig) - { - /* Signals specified by ISO C. */ - case SIGABRT: - /* glibc: "Aborted". *BSD: "Abort trap". Solaris: "Abort". */ - return "Aborted"; - case SIGFPE: - /* glibc, *BSD: "Floating point exception". Solaris: "Arithmetic exception". - The latter is more correct, because of integer division by 0 or -1. */ - return "Arithmetic exception"; - case SIGILL: - return "Illegal instruction"; - case SIGINT: - return "Interrupt"; - case SIGSEGV: - return "Segmentation fault"; - case SIGTERM: - return "Terminated"; - - /* Signals specified by POSIX. - */ - #if defined SIGALRM - case SIGALRM: - return "Alarm clock"; - #endif - #if defined SIGBUS - case SIGBUS: - return "Bus error"; - #endif - #if defined SIGCHLD - case SIGCHLD: - /* glibc, *BSD: "Child exited". Solaris: "Child status changed". */ - return "Child stopped or exited"; - #endif - #if defined SIGCONT - case SIGCONT: - return "Continued"; - #endif - #if defined SIGHUP - case SIGHUP: - return "Hangup"; - #endif - #if defined SIGKILL - case SIGKILL: - return "Killed"; - #endif - #if defined SIGPIPE - case SIGPIPE: - return "Broken pipe"; - #endif - #if defined SIGQUIT - case SIGQUIT: - return "Quit"; - #endif - #if defined SIGSTOP - case SIGSTOP: - /* glibc, Solaris: "Stopped (signal)". *BSD: "Suspended (signal)". */ - return "Stopped (signal)"; - #endif - #if defined SIGTSTP - case SIGTSTP: - /* glibc: "Stopped". *BSD: "Suspended". Solaris: "Stopped (user)". */ - return "Stopped"; - #endif - #if defined SIGTTIN - case SIGTTIN: - return "Stopped (tty input)"; - #endif - #if defined SIGTTOU - case SIGTTOU: - return "Stopped (tty output)"; - #endif - #if defined SIGUSR1 - case SIGUSR1: - /* glibc, *BSD: "User defined signal 1". Solaris: "User signal 1". */ - return "User defined signal 1"; - #endif - #if defined SIGUSR2 - case SIGUSR2: - /* glibc, *BSD: "User defined signal 2". Solaris: "User signal 2". */ - return "User defined signal 2"; - #endif - #if defined SIGPOLL - case SIGPOLL: - /* glibc: "I/O possible". Solaris: "Pollable event". */ - return "I/O possible"; - #endif - #if defined SIGPROF - case SIGPROF: - return "Profiling timer expired"; - #endif - #if defined SIGSYS - case SIGSYS: - return "Bad system call"; - #endif - #if defined SIGTRAP - case SIGTRAP: - /* glibc, Solaris: "Trace/breakpoint trap". *BSD: "Trace/BPT trap". */ - return "Trace/breakpoint trap"; - #endif - #if defined SIGURG - case SIGURG: - /* glibc, *BSD: "Urgent I/O condition". Solaris: "Urgent socket condition". */ - return "Urgent I/O condition"; - #endif - #if defined SIGVTALRM - case SIGVTALRM: - return "Virtual timer expired"; - #endif - #if defined SIGXCPU - case SIGXCPU: - /* glibc, *BSD: "CPU time limit exceeded". Solaris: "Cpu limit exceeded". */ - return "CPU time limit exceeded"; - #endif - #if defined SIGXFSZ - case SIGXFSZ: - return "File size limit exceeded"; - #endif - - /* Other signals on other systems. */ - /* native Windows */ - #if defined SIGBREAK - case SIGBREAK: - return "Ctrl-Break"; - #endif - /* IRIX */ - #if defined SIGCKPT - case SIGCKPT: - return "Checkpoint"; /* See man 1 cpr, man 3C atcheckpoint */ - #endif - /* Linux, IRIX, Cygwin */ - #if defined SIGCLD && SIGCLD != SIGCHLD - case SIGCLD: - return "Child stopped or exited"; - #endif - /* AIX */ - #if defined SIGCPUFAIL - case SIGCPUFAIL: - /* AIX: "CPU failure predicted". */ - return "CPU going down"; /* See man bindprocessor */ - #endif - /* AIX */ - #if defined SIGDANGER - case SIGDANGER: - /* AIX: "Paging space low". */ - return "Swap space nearly exhausted"; - #endif - /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, mingw */ - #if defined SIGEMT - case SIGEMT: - /* glibc/Hurd, *BSD: "EMT trap". Solaris: "Emulation trap". */ - return "Instruction emulation needed"; - #endif - /* Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix */ - #if defined SIGINFO && SIGINFO != SIGPWR - case SIGINFO: - return "Information request"; - #endif - /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin */ - #if defined SIGIO && SIGIO != SIGPOLL - case SIGIO: - return "I/O possible"; - #endif - /* Linux, IRIX, Cygwin, mingw */ - #if defined SIGIOT && SIGIOT != SIGABRT - case SIGIOT: - return "IOT instruction"; /* a PDP-11 instruction */ - #endif - /* AIX */ - #if defined SIGKAP - case SIGKAP: - /* Process must issue a KSKAPACK ioctl, or will be killed in 30 seconds. */ - /* AIX: "Monitor mode granted". */ - return "Keep Alive Poll"; - #endif - /* Haiku */ - #if defined SIGKILLTHR - case SIGKILLTHR: - return "Kill thread"; - #endif - /* Minix */ - #if defined SIGKMEM - case SIGKMEM: - return "Kernel memory request"; - #endif - /* Minix */ - #if defined SIGKMESS - case SIGKMESS: - return "Kernel message"; - #endif - /* Minix */ - #if defined SIGKSIG - case SIGKSIG: - return "Kernel signal"; - #endif - /* Minix */ - #if defined SIGKSIGSM - case SIGKSIGSM: - return "Kernel signal for signal manager"; - #endif - /* FreeBSD */ - #if defined SIGLIBRT - case SIGLIBRT: - return "Real-time library interrupt"; - #endif - /* Cygwin */ - #if defined SIGLOST && SIGLOST != SIGABRT && SIGLOST != SIGPWR - case SIGLOST: - /* Solaris: "Resource lost". */ - return "File lock lost"; - #endif - /* AIX */ - #if defined SIGMIGRATE - case SIGMIGRATE: - return "Process migration"; - #endif - /* AIX */ - #if defined SIGMSG - case SIGMSG: - /* AIX: "Input device data". */ - return "Message in the ring"; - #endif - /* ACM */ - #if defined SIGPLAN - case SIGPLAN: - return "Programming language anomaly"; - #endif - /* AIX */ - #if defined SIGPRE - case SIGPRE: - return "Programmed exception"; - #endif - /* IRIX */ - #if defined SIGPTINTR - case SIGPTINTR: - return "Pthread interrupt"; - #endif - /* IRIX */ - #if defined SIGPTRESCHED - case SIGPTRESCHED: - return "Pthread rescheduling"; - #endif - /* Linux, NetBSD, Minix, AIX, IRIX, Cygwin */ - #if defined SIGPWR - case SIGPWR: - /* glibc: "Power failure". NetBSD: "Power fail/restart". */ - return "Power failure"; - #endif - /* AIX */ - #if defined SIGRECONFIG - case SIGRECONFIG: - return "Dynamic logical partitioning changed"; - #endif - /* AIX */ - #if defined SIGRECOVERY - case SIGRECOVERY: - return "Kernel recovery"; - #endif - /* IRIX */ - #if defined SIGRESTART - case SIGRESTART: - return "Checkpoint restart"; /* See man 1 cpr, man 3C atrestart */ - #endif - /* AIX */ - #if defined SIGRETRACT - case SIGRETRACT: - /* AIX: "Monitor mode retracted". */ - return "Retracting Keep Alive Poll"; - #endif - /* AIX */ - #if defined SIGSAK - case SIGSAK: - /* AIX: "Secure attention". */ - return "Secure Attention Key"; - #endif - /* ACM */ - #if defined SIGSAM - case SIGSAM: - return "Symbolic computation failed"; - #endif - /* Minix */ - #if defined SIGSNDELAY - case SIGSNDELAY: - return "Done sending message"; - #endif - /* AIX */ - #if defined SIGSOUND - case SIGSOUND: - /* AIX: "Sound completed". */ - return "Sound configuration changed"; - #endif - /* Linux */ - #if defined SIGSTKFLT - case SIGSTKFLT: - return "Stack fault"; - #endif - /* AIX */ - #if defined SIGSYSERROR - case SIGSYSERROR: - return "Kernel error"; - #endif - /* AIX */ - #if defined SIGTALRM - case SIGTALRM: - return "Thread alarm clock"; - #endif - /* FreeBSD, OpenBSD */ - #if defined SIGTHR - case SIGTHR: - /* OpenBSD: "Thread AST". */ - return "Thread library interrupt"; - #endif - /* IRIX */ - #if defined SIGUME - case SIGUME: - return "Uncorrectable memory error"; - #endif - /* AIX */ - #if defined SIGVIRT - case SIGVIRT: - return "Virtual time alarm clock"; - #endif - /* AIX */ - #if defined SIGWAITING - case SIGWAITING: - /* AIX: "No runnable lwp". */ - return "Thread waiting"; - #endif - /* Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Minix, AIX, IRIX, Cygwin, Haiku */ - #if defined SIGWINCH - case SIGWINCH: - /* glibc: "Window changed". *BSD: "Window size changed" or "Window size changes". */ - return "Window size changed"; - #endif - - default: - return NULL; - } -} diff --git a/xcompile/lib/signal.in.h b/xcompile/lib/signal.in.h deleted file mode 100644 index fea12e6572d..00000000000 --- a/xcompile/lib/signal.in.h +++ /dev/null @@ -1,495 +0,0 @@ -/* A GNU-like . - - Copyright (C) 2006-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined __need_sig_atomic_t || defined __need_sigset_t || defined _GL_ALREADY_INCLUDING_SIGNAL_H || (defined _SIGNAL_H && !defined __SIZEOF_PTHREAD_MUTEX_T) -/* Special invocation convention: - - Inside glibc header files. - - On glibc systems we have a sequence of nested includes - -> -> . - In this situation, the functions are not yet declared, therefore we cannot - provide the C++ aliases. - - On glibc systems with GCC 4.3 we have a sequence of nested includes - -> -> -> . - In this situation, some of the functions are not yet declared, therefore - we cannot provide the C++ aliases. */ - -# @INCLUDE_NEXT@ @NEXT_SIGNAL_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_SIGNAL_H - -#define _GL_ALREADY_INCLUDING_SIGNAL_H - -/* Define pid_t, uid_t. - Also, mingw defines sigset_t not in , but in . - On Solaris 10, includes , which eventually includes - us; so include now, before the second inclusion guard. */ -#include - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_SIGNAL_H@ - -#undef _GL_ALREADY_INCLUDING_SIGNAL_H - -#ifndef _@GUARD_PREFIX@_SIGNAL_H -#define _@GUARD_PREFIX@_SIGNAL_H - -/* For testing the OpenBSD version. */ -#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ - && defined __OpenBSD__ -# include -#endif - -/* Mac OS X 10.3, FreeBSD < 8.0, OpenBSD < 5.1, OSF/1 4.0, Solaris 2.6, Android, - OS/2 kLIBC declare pthread_sigmask in , not in . - But avoid namespace pollution on glibc systems.*/ -#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \ - && ((defined __APPLE__ && defined __MACH__) \ - || (defined __FreeBSD__ && __FreeBSD__ < 8) \ - || (defined __OpenBSD__ && OpenBSD < 201205) \ - || defined __osf__ || defined __sun || defined __ANDROID__ \ - || defined __KLIBC__) \ - && ! defined __GLIBC__ -# include -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* On AIX, sig_atomic_t already includes volatile. C99 requires that - 'volatile sig_atomic_t' ignore the extra modifier, but C89 did not. - Hence, redefine this to a non-volatile type as needed. */ -#if ! @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ -# if !GNULIB_defined_sig_atomic_t -typedef int rpl_sig_atomic_t; -# undef sig_atomic_t -# define sig_atomic_t rpl_sig_atomic_t -# define GNULIB_defined_sig_atomic_t 1 -# endif -#endif - -/* A set or mask of signals. */ -#if !@HAVE_SIGSET_T@ -# if !GNULIB_defined_sigset_t -typedef unsigned int sigset_t; -# define GNULIB_defined_sigset_t 1 -# endif -#endif - -/* Define sighandler_t, the type of signal handlers. A GNU extension. */ -#if !@HAVE_SIGHANDLER_T@ -# ifdef __cplusplus -extern "C" { -# endif -# if !GNULIB_defined_sighandler_t -typedef void (*sighandler_t) (int); -# define GNULIB_defined_sighandler_t 1 -# endif -# ifdef __cplusplus -} -# endif -#endif - - -#if @GNULIB_SIGNAL_H_SIGPIPE@ -# ifndef SIGPIPE -/* Define SIGPIPE to a value that does not overlap with other signals. */ -# define SIGPIPE 13 -# define GNULIB_defined_SIGPIPE 1 -/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask', - 'write', 'stdio'. */ -# endif -#endif - - -/* Maximum signal number + 1. */ -#ifndef NSIG -# if defined __TANDEM -# define NSIG 32 -# endif -#endif - - -#if @GNULIB_PTHREAD_SIGMASK@ -# if @REPLACE_PTHREAD_SIGMASK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef pthread_sigmask -# define pthread_sigmask rpl_pthread_sigmask -# endif -_GL_FUNCDECL_RPL (pthread_sigmask, int, - (int how, - const sigset_t *restrict new_mask, - sigset_t *restrict old_mask)); -_GL_CXXALIAS_RPL (pthread_sigmask, int, - (int how, - const sigset_t *restrict new_mask, - sigset_t *restrict old_mask)); -# else -# if !(@HAVE_PTHREAD_SIGMASK@ || defined pthread_sigmask) -_GL_FUNCDECL_SYS (pthread_sigmask, int, - (int how, - const sigset_t *restrict new_mask, - sigset_t *restrict old_mask)); -# endif -_GL_CXXALIAS_SYS (pthread_sigmask, int, - (int how, - const sigset_t *restrict new_mask, - sigset_t *restrict old_mask)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (pthread_sigmask); -# endif -#elif defined GNULIB_POSIXCHECK -# undef pthread_sigmask -# if HAVE_RAW_DECL_PTHREAD_SIGMASK -_GL_WARN_ON_USE (pthread_sigmask, "pthread_sigmask is not portable - " - "use gnulib module pthread_sigmask for portability"); -# endif -#endif - - -#if @GNULIB_RAISE@ -# if @REPLACE_RAISE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef raise -# define raise rpl_raise -# endif -_GL_FUNCDECL_RPL (raise, int, (int sig)); -_GL_CXXALIAS_RPL (raise, int, (int sig)); -# else -# if !@HAVE_RAISE@ -_GL_FUNCDECL_SYS (raise, int, (int sig)); -# endif -_GL_CXXALIAS_SYS (raise, int, (int sig)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (raise); -# endif -#elif defined GNULIB_POSIXCHECK -# undef raise -/* Assume raise is always declared. */ -_GL_WARN_ON_USE (raise, "raise can crash on native Windows - " - "use gnulib module raise for portability"); -#endif - - -#if @GNULIB_SIGPROCMASK@ -# if !@HAVE_POSIX_SIGNALBLOCKING@ - -# ifndef GNULIB_defined_signal_blocking -# define GNULIB_defined_signal_blocking 1 -# endif - -/* Maximum signal number + 1. */ -# ifndef NSIG -# define NSIG 32 -# endif - -/* This code supports only 32 signals. */ -# if !GNULIB_defined_verify_NSIG_constraint -typedef int verify_NSIG_constraint[NSIG <= 32 ? 1 : -1]; -# define GNULIB_defined_verify_NSIG_constraint 1 -# endif - -# endif - -/* When also using extern inline, suppress the use of static inline in - standard headers of problematic Apple configurations, as Libc at - least through Libc-825.26 (2013-04-09) mishandles it; see, e.g., - . - Perhaps Apple will fix this some day. */ -#if (defined _GL_EXTERN_INLINE_IN_USE && defined __APPLE__ \ - && (defined __i386__ || defined __x86_64__)) -# undef sigaddset -# undef sigdelset -# undef sigemptyset -# undef sigfillset -# undef sigismember -#endif - -/* Test whether a given signal is contained in a signal set. */ -# if @HAVE_POSIX_SIGNALBLOCKING@ -/* This function is defined as a macro on Mac OS X. */ -# if defined __cplusplus && defined GNULIB_NAMESPACE -# undef sigismember -# endif -# else -_GL_FUNCDECL_SYS (sigismember, int, (const sigset_t *set, int sig) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigismember, int, (const sigset_t *set, int sig)); -_GL_CXXALIASWARN (sigismember); - -/* Initialize a signal set to the empty set. */ -# if @HAVE_POSIX_SIGNALBLOCKING@ -/* This function is defined as a macro on Mac OS X. */ -# if defined __cplusplus && defined GNULIB_NAMESPACE -# undef sigemptyset -# endif -# else -_GL_FUNCDECL_SYS (sigemptyset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigemptyset, int, (sigset_t *set)); -_GL_CXXALIASWARN (sigemptyset); - -/* Add a signal to a signal set. */ -# if @HAVE_POSIX_SIGNALBLOCKING@ -/* This function is defined as a macro on Mac OS X. */ -# if defined __cplusplus && defined GNULIB_NAMESPACE -# undef sigaddset -# endif -# else -_GL_FUNCDECL_SYS (sigaddset, int, (sigset_t *set, int sig) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigaddset, int, (sigset_t *set, int sig)); -_GL_CXXALIASWARN (sigaddset); - -/* Remove a signal from a signal set. */ -# if @HAVE_POSIX_SIGNALBLOCKING@ -/* This function is defined as a macro on Mac OS X. */ -# if defined __cplusplus && defined GNULIB_NAMESPACE -# undef sigdelset -# endif -# else -_GL_FUNCDECL_SYS (sigdelset, int, (sigset_t *set, int sig) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigdelset, int, (sigset_t *set, int sig)); -_GL_CXXALIASWARN (sigdelset); - -/* Fill a signal set with all possible signals. */ -# if @HAVE_POSIX_SIGNALBLOCKING@ -/* This function is defined as a macro on Mac OS X. */ -# if defined __cplusplus && defined GNULIB_NAMESPACE -# undef sigfillset -# endif -# else -_GL_FUNCDECL_SYS (sigfillset, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigfillset, int, (sigset_t *set)); -_GL_CXXALIASWARN (sigfillset); - -/* Return the set of those blocked signals that are pending. */ -# if !@HAVE_POSIX_SIGNALBLOCKING@ -_GL_FUNCDECL_SYS (sigpending, int, (sigset_t *set) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (sigpending, int, (sigset_t *set)); -_GL_CXXALIASWARN (sigpending); - -/* If OLD_SET is not NULL, put the current set of blocked signals in *OLD_SET. - Then, if SET is not NULL, affect the current set of blocked signals by - combining it with *SET as indicated in OPERATION. - In this implementation, you are not allowed to change a signal handler - while the signal is blocked. */ -# if !@HAVE_POSIX_SIGNALBLOCKING@ -# define SIG_BLOCK 0 /* blocked_set = blocked_set | *set; */ -# define SIG_SETMASK 1 /* blocked_set = *set; */ -# define SIG_UNBLOCK 2 /* blocked_set = blocked_set & ~*set; */ -_GL_FUNCDECL_SYS (sigprocmask, int, - (int operation, - const sigset_t *restrict set, - sigset_t *restrict old_set)); -# endif -_GL_CXXALIAS_SYS (sigprocmask, int, - (int operation, - const sigset_t *restrict set, - sigset_t *restrict old_set)); -_GL_CXXALIASWARN (sigprocmask); - -/* Install the handler FUNC for signal SIG, and return the previous - handler. */ -# ifdef __cplusplus -extern "C" { -# endif -# if !GNULIB_defined_function_taking_int_returning_void_t -typedef void (*_gl_function_taking_int_returning_void_t) (int); -# define GNULIB_defined_function_taking_int_returning_void_t 1 -# endif -# ifdef __cplusplus -} -# endif -# if !@HAVE_POSIX_SIGNALBLOCKING@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define signal rpl_signal -# endif -_GL_FUNCDECL_RPL (signal, _gl_function_taking_int_returning_void_t, - (int sig, _gl_function_taking_int_returning_void_t func)); -_GL_CXXALIAS_RPL (signal, _gl_function_taking_int_returning_void_t, - (int sig, _gl_function_taking_int_returning_void_t func)); -# else -/* On OpenBSD, the declaration of 'signal' may not be present at this point, - because it occurs in , not directly. */ -# if defined __OpenBSD__ -_GL_FUNCDECL_SYS (signal, _gl_function_taking_int_returning_void_t, - (int sig, _gl_function_taking_int_returning_void_t func)); -# endif -_GL_CXXALIAS_SYS (signal, _gl_function_taking_int_returning_void_t, - (int sig, _gl_function_taking_int_returning_void_t func)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (signal); -# endif - -# if !@HAVE_POSIX_SIGNALBLOCKING@ && GNULIB_defined_SIGPIPE -/* Raise signal SIGPIPE. */ -_GL_EXTERN_C int _gl_raise_SIGPIPE (void); -# endif - -#elif defined GNULIB_POSIXCHECK -# undef sigaddset -# if HAVE_RAW_DECL_SIGADDSET -_GL_WARN_ON_USE (sigaddset, "sigaddset is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigdelset -# if HAVE_RAW_DECL_SIGDELSET -_GL_WARN_ON_USE (sigdelset, "sigdelset is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigemptyset -# if HAVE_RAW_DECL_SIGEMPTYSET -_GL_WARN_ON_USE (sigemptyset, "sigemptyset is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigfillset -# if HAVE_RAW_DECL_SIGFILLSET -_GL_WARN_ON_USE (sigfillset, "sigfillset is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigismember -# if HAVE_RAW_DECL_SIGISMEMBER -_GL_WARN_ON_USE (sigismember, "sigismember is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigpending -# if HAVE_RAW_DECL_SIGPENDING -_GL_WARN_ON_USE (sigpending, "sigpending is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -# undef sigprocmask -# if HAVE_RAW_DECL_SIGPROCMASK -_GL_WARN_ON_USE (sigprocmask, "sigprocmask is unportable - " - "use the gnulib module sigprocmask for portability"); -# endif -#endif /* @GNULIB_SIGPROCMASK@ */ - - -#if @GNULIB_SIGACTION@ -# if !@HAVE_SIGACTION@ - -# if !@HAVE_SIGINFO_T@ - -# if !GNULIB_defined_siginfo_types - -/* Present to allow compilation, but unsupported by gnulib. */ -union sigval -{ - int sival_int; - void *sival_ptr; -}; - -/* Present to allow compilation, but unsupported by gnulib. */ -struct siginfo_t -{ - int si_signo; - int si_code; - int si_errno; - pid_t si_pid; - uid_t si_uid; - void *si_addr; - int si_status; - long si_band; - union sigval si_value; -}; -typedef struct siginfo_t siginfo_t; - -# define GNULIB_defined_siginfo_types 1 -# endif - -# endif /* !@HAVE_SIGINFO_T@ */ - -/* We assume that platforms which lack the sigaction() function also lack - the 'struct sigaction' type, and vice versa. */ - -# if !GNULIB_defined_struct_sigaction - -struct sigaction -{ - union - { - void (*_sa_handler) (int); - /* Present to allow compilation, but unsupported by gnulib. POSIX - says that implementations may, but not must, make sa_sigaction - overlap with sa_handler, but we know of no implementation where - they do not overlap. */ - void (*_sa_sigaction) (int, siginfo_t *, void *); - } _sa_func; - sigset_t sa_mask; - /* Not all POSIX flags are supported. */ - int sa_flags; -}; -# define sa_handler _sa_func._sa_handler -# define sa_sigaction _sa_func._sa_sigaction -/* Unsupported flags are not present. */ -# define SA_RESETHAND 1 -# define SA_NODEFER 2 -# define SA_RESTART 4 - -# define GNULIB_defined_struct_sigaction 1 -# endif - -_GL_FUNCDECL_SYS (sigaction, int, (int, const struct sigaction *restrict, - struct sigaction *restrict)); - -# elif !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ - -# define sa_sigaction sa_handler - -# endif /* !@HAVE_SIGACTION@, !@HAVE_STRUCT_SIGACTION_SA_SIGACTION@ */ - -_GL_CXXALIAS_SYS (sigaction, int, (int, const struct sigaction *restrict, - struct sigaction *restrict)); -_GL_CXXALIASWARN (sigaction); - -#elif defined GNULIB_POSIXCHECK -# undef sigaction -# if HAVE_RAW_DECL_SIGACTION -_GL_WARN_ON_USE (sigaction, "sigaction is unportable - " - "use the gnulib module sigaction for portability"); -# endif -#endif - -/* Some systems don't have SA_NODEFER. */ -#ifndef SA_NODEFER -# define SA_NODEFER 0 -#endif - - -#endif /* _@GUARD_PREFIX@_SIGNAL_H */ -#endif /* _@GUARD_PREFIX@_SIGNAL_H */ -#endif diff --git a/xcompile/lib/stat-time.c b/xcompile/lib/stat-time.c deleted file mode 100644 index bc282232ab3..00000000000 --- a/xcompile/lib/stat-time.c +++ /dev/null @@ -1,21 +0,0 @@ -/* stat-related time functions. - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define _GL_STAT_TIME_INLINE _GL_EXTERN_INLINE -#include "stat-time.h" diff --git a/xcompile/lib/stat-time.h b/xcompile/lib/stat-time.h deleted file mode 100644 index 92aa1e64e20..00000000000 --- a/xcompile/lib/stat-time.h +++ /dev/null @@ -1,251 +0,0 @@ -/* stat-related time functions. - - Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef STAT_TIME_H -#define STAT_TIME_H 1 - -#include -#include -#include -#include -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_STAT_TIME_INLINE -# define _GL_STAT_TIME_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type - struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST, - ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST, - if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim - for access, status change, data modification, or birth (creation) - time respectively. - - These macros are private to stat-time.h. */ -#if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC -# if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC -# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) -# else -# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) -# endif -#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC -# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) -#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC -# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) -#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC -# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec) -#endif - -/* Return the nanosecond component of *ST's access time. */ -_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE -get_stat_atime_ns (struct stat const *st) -{ -# if defined STAT_TIMESPEC - return STAT_TIMESPEC (st, st_atim).tv_nsec; -# elif defined STAT_TIMESPEC_NS - return STAT_TIMESPEC_NS (st, st_atim); -# else - return 0; -# endif -} - -/* Return the nanosecond component of *ST's status change time. */ -_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE -get_stat_ctime_ns (struct stat const *st) -{ -# if defined STAT_TIMESPEC - return STAT_TIMESPEC (st, st_ctim).tv_nsec; -# elif defined STAT_TIMESPEC_NS - return STAT_TIMESPEC_NS (st, st_ctim); -# else - return 0; -# endif -} - -/* Return the nanosecond component of *ST's data modification time. */ -_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE -get_stat_mtime_ns (struct stat const *st) -{ -# if defined STAT_TIMESPEC - return STAT_TIMESPEC (st, st_mtim).tv_nsec; -# elif defined STAT_TIMESPEC_NS - return STAT_TIMESPEC_NS (st, st_mtim); -# else - return 0; -# endif -} - -/* Return the nanosecond component of *ST's birth time. */ -_GL_STAT_TIME_INLINE long int _GL_ATTRIBUTE_PURE -get_stat_birthtime_ns (_GL_UNUSED struct stat const *st) -{ -# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC - return STAT_TIMESPEC (st, st_birthtim).tv_nsec; -# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC - return STAT_TIMESPEC_NS (st, st_birthtim); -# else - return 0; -# endif -} - -/* Return *ST's access time. */ -_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE -get_stat_atime (struct stat const *st) -{ -#ifdef STAT_TIMESPEC - return STAT_TIMESPEC (st, st_atim); -#else - struct timespec t; - t.tv_sec = st->st_atime; - t.tv_nsec = get_stat_atime_ns (st); - return t; -#endif -} - -/* Return *ST's status change time. */ -_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE -get_stat_ctime (struct stat const *st) -{ -#ifdef STAT_TIMESPEC - return STAT_TIMESPEC (st, st_ctim); -#else - struct timespec t; - t.tv_sec = st->st_ctime; - t.tv_nsec = get_stat_ctime_ns (st); - return t; -#endif -} - -/* Return *ST's data modification time. */ -_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE -get_stat_mtime (struct stat const *st) -{ -#ifdef STAT_TIMESPEC - return STAT_TIMESPEC (st, st_mtim); -#else - struct timespec t; - t.tv_sec = st->st_mtime; - t.tv_nsec = get_stat_mtime_ns (st); - return t; -#endif -} - -/* Return *ST's birth time, if available; otherwise return a value - with tv_sec and tv_nsec both equal to -1. */ -_GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE -get_stat_birthtime (_GL_UNUSED struct stat const *st) -{ - struct timespec t; - -#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ - || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) - t = STAT_TIMESPEC (st, st_birthtim); -#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC - t.tv_sec = st->st_birthtime; - t.tv_nsec = st->st_birthtimensec; -#elif defined _WIN32 && ! defined __CYGWIN__ - /* Native Windows platforms (but not Cygwin) put the "file creation - time" in st_ctime (!). See - . */ -# if _GL_WINDOWS_STAT_TIMESPEC - t = st->st_ctim; -# else - t.tv_sec = st->st_ctime; - t.tv_nsec = 0; -# endif -#else - /* Birth time is not supported. */ - t.tv_sec = -1; - t.tv_nsec = -1; -#endif - -#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ - || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \ - || defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC) - /* FreeBSD and NetBSD sometimes signal the absence of knowledge by - using zero. Attempt to work around this problem. Alas, this can - report failure even for valid timestamps. Also, NetBSD - sometimes returns junk in the birth time fields; work around this - bug if it is detected. */ - if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) - { - t.tv_sec = -1; - t.tv_nsec = -1; - } -#endif - - return t; -} - -/* If a stat-like function returned RESULT, normalize the timestamps - in *ST, in case this platform suffers from the Solaris 11 bug where - tv_nsec might be negative. Return the adjusted RESULT, setting - errno to EOVERFLOW if normalization overflowed. This function - is intended to be private to this .h file. */ -_GL_STAT_TIME_INLINE int -stat_time_normalize (int result, _GL_UNUSED struct stat *st) -{ -#if defined __sun && defined STAT_TIMESPEC - if (result == 0) - { - long int timespec_hz = 1000000000; - short int const ts_off[] = { offsetof (struct stat, st_atim), - offsetof (struct stat, st_mtim), - offsetof (struct stat, st_ctim) }; - int i; - for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) - { - struct timespec *ts = (struct timespec *) ((char *) st + ts_off[i]); - long int q = ts->tv_nsec / timespec_hz; - long int r = ts->tv_nsec % timespec_hz; - if (r < 0) - { - r += timespec_hz; - q--; - } - ts->tv_nsec = r; - /* Overflow is possible, as Solaris 11 stat can yield - tv_sec == TYPE_MINIMUM (time_t) && tv_nsec == -1000000000. - INT_ADD_WRAPV is OK, since time_t is signed on Solaris. */ - if (ckd_add (&ts->tv_sec, q, ts->tv_sec)) - { - errno = EOVERFLOW; - return -1; - } - } - } -#endif - return result; -} - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif diff --git a/xcompile/lib/stpcpy.c b/xcompile/lib/stpcpy.c deleted file mode 100644 index 73c1eb786ff..00000000000 --- a/xcompile/lib/stpcpy.c +++ /dev/null @@ -1,49 +0,0 @@ -/* stpcpy.c -- copy a string and return pointer to end of new string - Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2023 Free Software - Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#include - -#undef __stpcpy -#ifdef _LIBC -# undef stpcpy -#endif - -#ifndef weak_alias -# define __stpcpy stpcpy -#endif - -/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ -char * -__stpcpy (char *dest, const char *src) -{ - register char *d = dest; - register const char *s = src; - - do - *d++ = *s; - while (*s++ != '\0'); - - return d - 1; -} -#ifdef weak_alias -weak_alias (__stpcpy, stpcpy) -#endif diff --git a/xcompile/lib/str-two-way.h b/xcompile/lib/str-two-way.h deleted file mode 100644 index dfe702241c0..00000000000 --- a/xcompile/lib/str-two-way.h +++ /dev/null @@ -1,452 +0,0 @@ -/* Byte-wise substring search, using the Two-Way algorithm. - Copyright (C) 2008-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Eric Blake , 2008. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Before including this file, you need to include and - , and define: - RETURN_TYPE A macro that expands to the return type. - AVAILABLE(h, h_l, j, n_l) - A macro that returns nonzero if there are - at least N_L bytes left starting at H[J]. - H is 'unsigned char *', H_L, J, and N_L - are 'size_t'; H_L is an lvalue. For - NUL-terminated searches, H_L can be - modified each iteration to avoid having - to compute the end of H up front. - - For case-insensitivity, you may optionally define: - CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L - characters of P1 and P2 are equal. - CANON_ELEMENT(c) A macro that canonicalizes an element right after - it has been fetched from one of the two strings. - The argument is an 'unsigned char'; the result - must be an 'unsigned char' as well. - - This file undefines the macros documented above, and defines - LONG_NEEDLE_THRESHOLD. -*/ - -#include -#include - -/* We use the Two-Way string matching algorithm (also known as - Chrochemore-Perrin), which guarantees linear complexity with - constant space. Additionally, for long needles, we also use a bad - character shift table similar to the Boyer-Moore algorithm to - achieve improved (potentially sub-linear) performance. - - See https://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260, - https://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm, - https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.6641&rep=rep1&type=pdf -*/ - -/* Point at which computing a bad-byte shift table is likely to be - worthwhile. Small needles should not compute a table, since it - adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a - speedup no greater than a factor of NEEDLE_LEN. The larger the - needle, the better the potential performance gain. On the other - hand, on non-POSIX systems with CHAR_BIT larger than eight, the - memory required for the table is prohibitive. */ -#if CHAR_BIT < 10 -# define LONG_NEEDLE_THRESHOLD 32U -#else -# define LONG_NEEDLE_THRESHOLD SIZE_MAX -#endif - -#ifndef MAX -# define MAX(a, b) ((a < b) ? (b) : (a)) -#endif - -#ifndef CANON_ELEMENT -# define CANON_ELEMENT(c) c -#endif -#ifndef CMP_FUNC -# define CMP_FUNC memcmp -#endif - -/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN. - Return the index of the first byte in the right half, and set - *PERIOD to the global period of the right half. - - The global period of a string is the smallest index (possibly its - length) at which all remaining bytes in the string are repetitions - of the prefix (the last repetition may be a subset of the prefix). - - When NEEDLE is factored into two halves, a local period is the - length of the smallest word that shares a suffix with the left half - and shares a prefix with the right half. All factorizations of a - non-empty NEEDLE have a local period of at least 1 and no greater - than NEEDLE_LEN. - - A critical factorization has the property that the local period - equals the global period. All strings have at least one critical - factorization with the left half smaller than the global period. - And while some strings have more than one critical factorization, - it is provable that with an ordered alphabet, at least one of the - critical factorizations corresponds to a maximal suffix. - - Given an ordered alphabet, a critical factorization can be computed - in linear time, with 2 * NEEDLE_LEN comparisons, by computing the - shorter of two ordered maximal suffixes. The ordered maximal - suffixes are determined by lexicographic comparison while tracking - periodicity. */ -static size_t -critical_factorization (const unsigned char *needle, size_t needle_len, - size_t *period) -{ - /* Index of last byte of left half, or SIZE_MAX. */ - size_t max_suffix, max_suffix_rev; - size_t j; /* Index into NEEDLE for current candidate suffix. */ - size_t k; /* Offset into current period. */ - size_t p; /* Intermediate period. */ - unsigned char a, b; /* Current comparison bytes. */ - - /* Special case NEEDLE_LEN of 1 or 2 (all callers already filtered - out 0-length needles. */ - if (needle_len < 3) - { - *period = 1; - return needle_len - 1; - } - - /* Invariants: - 0 <= j < NEEDLE_LEN - 1 - -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed) - min(max_suffix, max_suffix_rev) < global period of NEEDLE - 1 <= p <= global period of NEEDLE - p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j] - 1 <= k <= p - */ - - /* Perform lexicographic search. */ - max_suffix = SIZE_MAX; - j = 0; - k = p = 1; - while (j + k < needle_len) - { - a = CANON_ELEMENT (needle[j + k]); - b = CANON_ELEMENT (needle[max_suffix + k]); - if (a < b) - { - /* Suffix is smaller, period is entire prefix so far. */ - j += k; - k = 1; - p = j - max_suffix; - } - else if (a == b) - { - /* Advance through repetition of the current period. */ - if (k != p) - ++k; - else - { - j += p; - k = 1; - } - } - else /* b < a */ - { - /* Suffix is larger, start over from current location. */ - max_suffix = j++; - k = p = 1; - } - } - *period = p; - - /* Perform reverse lexicographic search. */ - max_suffix_rev = SIZE_MAX; - j = 0; - k = p = 1; - while (j + k < needle_len) - { - a = CANON_ELEMENT (needle[j + k]); - b = CANON_ELEMENT (needle[max_suffix_rev + k]); - if (b < a) - { - /* Suffix is smaller, period is entire prefix so far. */ - j += k; - k = 1; - p = j - max_suffix_rev; - } - else if (a == b) - { - /* Advance through repetition of the current period. */ - if (k != p) - ++k; - else - { - j += p; - k = 1; - } - } - else /* a < b */ - { - /* Suffix is larger, start over from current location. */ - max_suffix_rev = j++; - k = p = 1; - } - } - - /* Choose the shorter suffix. Return the index of the first byte of - the right half, rather than the last byte of the left half. - - For some examples, 'banana' has two critical factorizations, both - exposed by the two lexicographic extreme suffixes of 'anana' and - 'nana', where both suffixes have a period of 2. On the other - hand, with 'aab' and 'bba', both strings have a single critical - factorization of the last byte, with the suffix having a period - of 1. While the maximal lexicographic suffix of 'aab' is 'b', - the maximal lexicographic suffix of 'bba' is 'ba', which is not a - critical factorization. Conversely, the maximal reverse - lexicographic suffix of 'a' works for 'bba', but not 'ab' for - 'aab'. The shorter suffix of the two will always be a critical - factorization. */ - if (max_suffix_rev + 1 < max_suffix + 1) - return max_suffix + 1; - *period = p; - return max_suffix_rev + 1; -} - -/* Return the first location of non-empty NEEDLE within HAYSTACK, or - NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This - method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD. - Performance is guaranteed to be linear, with an initialization cost - of 2 * NEEDLE_LEN comparisons. - - If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at - most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. - If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * - HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ -static RETURN_TYPE _GL_ATTRIBUTE_PURE -two_way_short_needle (const unsigned char *haystack, size_t haystack_len, - const unsigned char *needle, size_t needle_len) -{ - size_t i; /* Index into current byte of NEEDLE. */ - size_t j; /* Index into current window of HAYSTACK. */ - size_t period; /* The period of the right half of needle. */ - size_t suffix; /* The index of the right half of needle. */ - - /* Factor the needle into two halves, such that the left half is - smaller than the global period, and the right half is - periodic (with a period as large as NEEDLE_LEN - suffix). */ - suffix = critical_factorization (needle, needle_len, &period); - - /* Perform the search. Each iteration compares the right half - first. */ - if (CMP_FUNC (needle, needle + period, suffix) == 0) - { - /* Entire needle is periodic; a mismatch in the left half can - only advance by the period, so use memory to avoid rescanning - known occurrences of the period in the right half. */ - size_t memory = 0; - j = 0; - while (AVAILABLE (haystack, haystack_len, j, needle_len)) - { - /* Scan for matches in right half. */ - i = MAX (suffix, memory); - while (i < needle_len && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - ++i; - if (needle_len <= i) - { - /* Scan for matches in left half. */ - i = suffix - 1; - while (memory < i + 1 && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - --i; - if (i + 1 < memory + 1) - return (RETURN_TYPE) (haystack + j); - /* No match, so remember how many repetitions of period - on the right half were scanned. */ - j += period; - memory = needle_len - period; - } - else - { - j += i - suffix + 1; - memory = 0; - } - } - } - else - { - /* The two halves of needle are distinct; no extra memory is - required, and any mismatch results in a maximal shift. */ - period = MAX (suffix, needle_len - suffix) + 1; - j = 0; - while (AVAILABLE (haystack, haystack_len, j, needle_len)) - { - /* Scan for matches in right half. */ - i = suffix; - while (i < needle_len && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - ++i; - if (needle_len <= i) - { - /* Scan for matches in left half. */ - i = suffix - 1; - while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - --i; - if (i == SIZE_MAX) - return (RETURN_TYPE) (haystack + j); - j += period; - } - else - j += i - suffix + 1; - } - } - return NULL; -} - -/* Return the first location of non-empty NEEDLE within HAYSTACK, or - NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This - method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN. - Performance is guaranteed to be linear, with an initialization cost - of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations. - - If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at - most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, - and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. - If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * - HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and - sublinear performance is not possible. */ -static RETURN_TYPE _GL_ATTRIBUTE_PURE -two_way_long_needle (const unsigned char *haystack, size_t haystack_len, - const unsigned char *needle, size_t needle_len) -{ - size_t i; /* Index into current byte of NEEDLE. */ - size_t j; /* Index into current window of HAYSTACK. */ - size_t period; /* The period of the right half of needle. */ - size_t suffix; /* The index of the right half of needle. */ - size_t shift_table[1U << CHAR_BIT]; /* See below. */ - - /* Factor the needle into two halves, such that the left half is - smaller than the global period, and the right half is - periodic (with a period as large as NEEDLE_LEN - suffix). */ - suffix = critical_factorization (needle, needle_len, &period); - - /* Populate shift_table. For each possible byte value c, - shift_table[c] is the distance from the last occurrence of c to - the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE. - shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */ - for (i = 0; i < 1U << CHAR_BIT; i++) - shift_table[i] = needle_len; - for (i = 0; i < needle_len; i++) - shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1; - - /* Perform the search. Each iteration compares the right half - first. */ - if (CMP_FUNC (needle, needle + period, suffix) == 0) - { - /* Entire needle is periodic; a mismatch in the left half can - only advance by the period, so use memory to avoid rescanning - known occurrences of the period in the right half. */ - size_t memory = 0; - size_t shift; - j = 0; - while (AVAILABLE (haystack, haystack_len, j, needle_len)) - { - /* Check the last byte first; if it does not match, then - shift to the next possible match location. */ - shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; - if (0 < shift) - { - if (memory && shift < period) - { - /* Since needle is periodic, but the last period has - a byte out of place, there can be no match until - after the mismatch. */ - shift = needle_len - period; - } - memory = 0; - j += shift; - continue; - } - /* Scan for matches in right half. The last byte has - already been matched, by virtue of the shift table. */ - i = MAX (suffix, memory); - while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - ++i; - if (needle_len - 1 <= i) - { - /* Scan for matches in left half. */ - i = suffix - 1; - while (memory < i + 1 && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - --i; - if (i + 1 < memory + 1) - return (RETURN_TYPE) (haystack + j); - /* No match, so remember how many repetitions of period - on the right half were scanned. */ - j += period; - memory = needle_len - period; - } - else - { - j += i - suffix + 1; - memory = 0; - } - } - } - else - { - /* The two halves of needle are distinct; no extra memory is - required, and any mismatch results in a maximal shift. */ - size_t shift; - period = MAX (suffix, needle_len - suffix) + 1; - j = 0; - while (AVAILABLE (haystack, haystack_len, j, needle_len)) - { - /* Check the last byte first; if it does not match, then - shift to the next possible match location. */ - shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; - if (0 < shift) - { - j += shift; - continue; - } - /* Scan for matches in right half. The last byte has - already been matched, by virtue of the shift table. */ - i = suffix; - while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - ++i; - if (needle_len - 1 <= i) - { - /* Scan for matches in left half. */ - i = suffix - 1; - while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) - == CANON_ELEMENT (haystack[i + j]))) - --i; - if (i == SIZE_MAX) - return (RETURN_TYPE) (haystack + j); - j += period; - } - else - j += i - suffix + 1; - } - } - return NULL; -} - -#undef AVAILABLE -#undef CANON_ELEMENT -#undef CMP_FUNC -#undef MAX -#undef RETURN_TYPE diff --git a/xcompile/lib/strftime.h b/xcompile/lib/strftime.h deleted file mode 100644 index 88c1f73928f..00000000000 --- a/xcompile/lib/strftime.h +++ /dev/null @@ -1,38 +0,0 @@ -/* declarations for strftime.c - - Copyright (C) 2002, 2004, 2008-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Just like strftime, but with two more arguments: - POSIX requires that strftime use the local timezone information. - Use the timezone __TZ instead. Use __NS as the number of - nanoseconds in the %N directive. - - On error, set errno and return 0. Otherwise, return the number of - bytes generated (not counting the trailing NUL), preserving errno - if the number is 0. This errno behavior is in draft POSIX 202x - plus some requested changes to POSIX. */ -size_t nstrftime (char *restrict, size_t, char const *, struct tm const *, - timezone_t __tz, int __ns); - -#ifdef __cplusplus -} -#endif diff --git a/xcompile/lib/string.in.h b/xcompile/lib/string.in.h deleted file mode 100644 index b227a178873..00000000000 --- a/xcompile/lib/string.in.h +++ /dev/null @@ -1,1323 +0,0 @@ -/* A GNU-like . - - Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined _GL_ALREADY_INCLUDING_STRING_H -/* Special invocation convention: - - On OS X/NetBSD we have a sequence of nested includes - -> -> "string.h" - In this situation system _chk variants due to -D_FORTIFY_SOURCE - might be used after any replacements defined here. */ - -#@INCLUDE_NEXT@ @NEXT_STRING_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_STRING_H - -#define _GL_ALREADY_INCLUDING_STRING_H - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STRING_H@ - -#undef _GL_ALREADY_INCLUDING_STRING_H - -#ifndef _@GUARD_PREFIX@_STRING_H -#define _@GUARD_PREFIX@_STRING_H - -/* NetBSD 5.0 mis-defines NULL. */ -#include - -/* MirBSD defines mbslen as a macro. */ -#if @GNULIB_MBSLEN@ && defined __MirBSD__ -# include -#endif - -/* NetBSD 5.0 declares strsignal in , not in . */ -/* But in any case avoid namespace pollution on glibc systems. */ -#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) && defined __NetBSD__ \ - && ! defined __GLIBC__ -# include -#endif - -/* AIX 7.2 and Android 13 declare ffsl and ffsll in , not in - . */ -/* But in any case avoid namespace pollution on glibc systems. */ -#if ((@GNULIB_FFSL@ || @GNULIB_FFSLL@ || defined GNULIB_POSIXCHECK) \ - && (defined _AIX || defined __ANDROID__)) \ - && ! defined __GLIBC__ -# include -#endif - -/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers - that can be freed by passing them as the Ith argument to the - function F. */ -#ifndef _GL_ATTRIBUTE_DEALLOC -# if __GNUC__ >= 11 -# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) -# else -# define _GL_ATTRIBUTE_DEALLOC(f, i) -# endif -#endif - -/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that - can be freed via 'free'; it can be used only after declaring 'free'. */ -/* Applies to: functions. Cannot be used on inline functions. */ -#ifndef _GL_ATTRIBUTE_DEALLOC_FREE -# if defined __cplusplus && defined __GNUC__ && !defined __clang__ -/* Work around GCC bug */ -# define _GL_ATTRIBUTE_DEALLOC_FREE \ - _GL_ATTRIBUTE_DEALLOC ((void (*) (void *)) free, 1) -# else -# define _GL_ATTRIBUTE_DEALLOC_FREE \ - _GL_ATTRIBUTE_DEALLOC (free, 1) -# endif -#endif - -/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly - allocated memory. */ -/* Applies to: functions. */ -#ifndef _GL_ATTRIBUTE_MALLOC -# if __GNUC__ >= 3 || defined __clang__ -# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) -# else -# define _GL_ATTRIBUTE_MALLOC -# endif -#endif - -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The attribute __pure__ was added in gcc 2.96. */ -#ifndef _GL_ATTRIBUTE_PURE -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ -# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define _GL_ATTRIBUTE_PURE /* empty */ -# endif -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Make _GL_ATTRIBUTE_DEALLOC_FREE work, even though may not have - been included yet. */ -#if @GNULIB_FREE_POSIX@ -# if (@REPLACE_FREE@ && !defined free \ - && !(defined __cplusplus && defined GNULIB_NAMESPACE)) -/* We can't do '#define free rpl_free' here. */ -_GL_EXTERN_C void rpl_free (void *); -# undef _GL_ATTRIBUTE_DEALLOC_FREE -# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1) -# else -# if defined _MSC_VER && !defined free -_GL_EXTERN_C -# if defined _DLL - __declspec (dllimport) -# endif - void __cdecl free (void *); -# else -# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) -_GL_EXTERN_C void free (void *) throw (); -# else -_GL_EXTERN_C void free (void *); -# endif -# endif -# endif -#else -# if defined _MSC_VER && !defined free -_GL_EXTERN_C -# if defined _DLL - __declspec (dllimport) -# endif - void __cdecl free (void *); -# else -# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) -_GL_EXTERN_C void free (void *) throw (); -# else -_GL_EXTERN_C void free (void *); -# endif -# endif -#endif - -/* Clear a block of memory. The compiler will not delete a call to - this function, even if the block is dead after the call. */ -#if @GNULIB_EXPLICIT_BZERO@ -# if ! @HAVE_EXPLICIT_BZERO@ -_GL_FUNCDECL_SYS (explicit_bzero, void, - (void *__dest, size_t __n) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (explicit_bzero, void, (void *__dest, size_t __n)); -_GL_CXXALIASWARN (explicit_bzero); -#elif defined GNULIB_POSIXCHECK -# undef explicit_bzero -# if HAVE_RAW_DECL_EXPLICIT_BZERO -_GL_WARN_ON_USE (explicit_bzero, "explicit_bzero is unportable - " - "use gnulib module explicit_bzero for portability"); -# endif -#endif - -/* Find the index of the least-significant set bit. */ -#if @GNULIB_FFSL@ -# if !@HAVE_FFSL@ -_GL_FUNCDECL_SYS (ffsl, int, (long int i)); -# endif -_GL_CXXALIAS_SYS (ffsl, int, (long int i)); -_GL_CXXALIASWARN (ffsl); -#elif defined GNULIB_POSIXCHECK -# undef ffsl -# if HAVE_RAW_DECL_FFSL -_GL_WARN_ON_USE (ffsl, "ffsl is not portable - use the ffsl module"); -# endif -#endif - - -/* Find the index of the least-significant set bit. */ -#if @GNULIB_FFSLL@ -# if @REPLACE_FFSLL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define ffsll rpl_ffsll -# endif -_GL_FUNCDECL_RPL (ffsll, int, (long long int i)); -_GL_CXXALIAS_RPL (ffsll, int, (long long int i)); -# else -# if !@HAVE_FFSLL@ -_GL_FUNCDECL_SYS (ffsll, int, (long long int i)); -# endif -_GL_CXXALIAS_SYS (ffsll, int, (long long int i)); -# endif -_GL_CXXALIASWARN (ffsll); -#elif defined GNULIB_POSIXCHECK -# undef ffsll -# if HAVE_RAW_DECL_FFSLL -_GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module"); -# endif -#endif - - -#if @GNULIB_MDA_MEMCCPY@ -/* On native Windows, map 'memccpy' to '_memccpy', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::memccpy always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef memccpy -# define memccpy _memccpy -# endif -_GL_CXXALIAS_MDA (memccpy, void *, - (void *dest, const void *src, int c, size_t n)); -# else -_GL_CXXALIAS_SYS (memccpy, void *, - (void *dest, const void *src, int c, size_t n)); -# endif -_GL_CXXALIASWARN (memccpy); -#endif - - -/* Return the first instance of C within N bytes of S, or NULL. */ -#if @GNULIB_MEMCHR@ -# if @REPLACE_MEMCHR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef memchr -# define memchr rpl_memchr -# endif -_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n)); -# else - /* On some systems, this function is defined as an overloaded function: - extern "C" { const void * std::memchr (const void *, int, size_t); } - extern "C++" { void * std::memchr (void *, int, size_t); } */ -_GL_CXXALIAS_SYS_CAST2 (memchr, - void *, (void const *__s, int __c, size_t __n), - void const *, (void const *__s, int __c, size_t __n)); -# endif -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n) throw ()); -_GL_CXXALIASWARN1 (memchr, void const *, - (void const *__s, int __c, size_t __n) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (memchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef memchr -/* Assume memchr is always declared. */ -_GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " - "use gnulib module memchr for portability" ); -#endif - -/* Return the first occurrence of NEEDLE in HAYSTACK. */ -#if @GNULIB_MEMMEM@ -# if @REPLACE_MEMMEM@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define memmem rpl_memmem -# endif -_GL_FUNCDECL_RPL (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 3))); -_GL_CXXALIAS_RPL (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len)); -# else -# if ! @HAVE_DECL_MEMMEM@ -_GL_FUNCDECL_SYS (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 3))); -# endif -_GL_CXXALIAS_SYS (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len)); -# endif -_GL_CXXALIASWARN (memmem); -#elif defined GNULIB_POSIXCHECK -# undef memmem -# if HAVE_RAW_DECL_MEMMEM -_GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " - "use gnulib module memmem-simple for portability, " - "and module memmem for speed" ); -# endif -#endif - -/* Copy N bytes of SRC to DEST, return pointer to bytes after the - last written byte. */ -#if @GNULIB_MEMPCPY@ -# if ! @HAVE_MEMPCPY@ -_GL_FUNCDECL_SYS (mempcpy, void *, - (void *restrict __dest, void const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (mempcpy, void *, - (void *restrict __dest, void const *restrict __src, - size_t __n)); -_GL_CXXALIASWARN (mempcpy); -#elif defined GNULIB_POSIXCHECK -# undef mempcpy -# if HAVE_RAW_DECL_MEMPCPY -_GL_WARN_ON_USE (mempcpy, "mempcpy is unportable - " - "use gnulib module mempcpy for portability"); -# endif -#endif - -/* Search backwards through a block for a byte (specified as an int). */ -#if @GNULIB_MEMRCHR@ -# if ! @HAVE_DECL_MEMRCHR@ -_GL_FUNCDECL_SYS (memrchr, void *, (void const *, int, size_t) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const void * std::memrchr (const void *, int, size_t); } - extern "C++" { void * std::memrchr (void *, int, size_t); } */ -_GL_CXXALIAS_SYS_CAST2 (memrchr, - void *, (void const *, int, size_t), - void const *, (void const *, int, size_t)); -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t) throw ()); -_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (memrchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef memrchr -# if HAVE_RAW_DECL_MEMRCHR -_GL_WARN_ON_USE (memrchr, "memrchr is unportable - " - "use gnulib module memrchr for portability"); -# endif -#endif - -/* Overwrite a block of memory. The compiler will not optimize - effects away, even if the block is dead after the call. */ -#if @GNULIB_MEMSET_EXPLICIT@ -# if ! @HAVE_MEMSET_EXPLICIT@ -_GL_FUNCDECL_SYS (memset_explicit, void *, - (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t __n)); -_GL_CXXALIASWARN (memset_explicit); -#elif defined GNULIB_POSIXCHECK -# undef memset_explicit -# if HAVE_RAW_DECL_MEMSET_EXPLICIT -_GL_WARN_ON_USE (memset_explicit, "memset_explicit is unportable - " - "use gnulib module memset_explicit for portability"); -# endif -#endif - -/* Find the first occurrence of C in S. More efficient than - memchr(S,C,N), at the expense of undefined behavior if C does not - occur within N bytes. */ -#if @GNULIB_RAWMEMCHR@ -# if ! @HAVE_RAWMEMCHR@ -_GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const void * std::rawmemchr (const void *, int); } - extern "C++" { void * std::rawmemchr (void *, int); } */ -_GL_CXXALIAS_SYS_CAST2 (rawmemchr, - void *, (void const *__s, int __c_in), - void const *, (void const *__s, int __c_in)); -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in) throw ()); -_GL_CXXALIASWARN1 (rawmemchr, void const *, - (void const *__s, int __c_in) throw ()); -# else -_GL_CXXALIASWARN (rawmemchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef rawmemchr -# if HAVE_RAW_DECL_RAWMEMCHR -_GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - " - "use gnulib module rawmemchr for portability"); -# endif -#endif - -/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */ -#if @GNULIB_STPCPY@ -# if ! @HAVE_STPCPY@ -_GL_FUNCDECL_SYS (stpcpy, char *, - (char *restrict __dst, char const *restrict __src) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (stpcpy, char *, - (char *restrict __dst, char const *restrict __src)); -_GL_CXXALIASWARN (stpcpy); -#elif defined GNULIB_POSIXCHECK -# undef stpcpy -# if HAVE_RAW_DECL_STPCPY -_GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " - "use gnulib module stpcpy for portability"); -# endif -#endif - -/* Copy no more than N bytes of SRC to DST, returning a pointer past the - last non-NUL byte written into DST. */ -#if @GNULIB_STPNCPY@ -# if @REPLACE_STPNCPY@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef stpncpy -# define stpncpy rpl_stpncpy -# endif -_GL_FUNCDECL_RPL (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n)); -# else -# if ! @HAVE_STPNCPY@ -_GL_FUNCDECL_SYS (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n)); -# endif -_GL_CXXALIASWARN (stpncpy); -#elif defined GNULIB_POSIXCHECK -# undef stpncpy -# if HAVE_RAW_DECL_STPNCPY -_GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " - "use gnulib module stpncpy for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ -# undef strchr -/* Assume strchr is always declared. */ -_GL_WARN_ON_USE_CXX (strchr, - const char *, char *, (const char *, int), - "strchr cannot work correctly on character strings " - "in some multibyte locales - " - "use mbschr if you care about internationalization"); -#endif - -/* Find the first occurrence of C in S or the final NUL byte. */ -#if @GNULIB_STRCHRNUL@ -# if @REPLACE_STRCHRNUL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strchrnul rpl_strchrnul -# endif -_GL_FUNCDECL_RPL (strchrnul, char *, (const char *__s, int __c_in) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strchrnul, char *, - (const char *str, int ch)); -# else -# if ! @HAVE_STRCHRNUL@ -_GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * std::strchrnul (const char *, int); } - extern "C++" { char * std::strchrnul (char *, int); } */ -_GL_CXXALIAS_SYS_CAST2 (strchrnul, - char *, (char const *__s, int __c_in), - char const *, (char const *__s, int __c_in)); -# endif -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in) throw ()); -_GL_CXXALIASWARN1 (strchrnul, char const *, - (char const *__s, int __c_in) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (strchrnul); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strchrnul -# if HAVE_RAW_DECL_STRCHRNUL -_GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - " - "use gnulib module strchrnul for portability"); -# endif -#endif - -/* Duplicate S, returning an identical malloc'd string. */ -#if @GNULIB_STRDUP@ -# if @REPLACE_STRDUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strdup -# define strdup rpl_strdup -# endif -_GL_FUNCDECL_RPL (strdup, char *, - (char const *__s) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -_GL_CXXALIAS_RPL (strdup, char *, (char const *__s)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strdup -# define strdup _strdup -# endif -_GL_CXXALIAS_MDA (strdup, char *, (char const *__s)); -# else -# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup - /* strdup exists as a function and as a macro. Get rid of the macro. */ -# undef strdup -# endif -# if (!@HAVE_DECL_STRDUP@ || __GNUC__ >= 11) && !defined strdup -_GL_FUNCDECL_SYS (strdup, char *, - (char const *__s) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -# endif -_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); -# endif -_GL_CXXALIASWARN (strdup); -#else -# if __GNUC__ >= 11 && !defined strdup -/* For -Wmismatched-dealloc: Associate strdup with free or rpl_free. */ -_GL_FUNCDECL_SYS (strdup, char *, - (char const *__s) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -# endif -# if defined GNULIB_POSIXCHECK -# undef strdup -# if HAVE_RAW_DECL_STRDUP -_GL_WARN_ON_USE (strdup, "strdup is unportable - " - "use gnulib module strdup for portability"); -# endif -# elif @GNULIB_MDA_STRDUP@ -/* On native Windows, map 'creat' to '_creat', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::strdup always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strdup -# define strdup _strdup -# endif -_GL_CXXALIAS_MDA (strdup, char *, (char const *__s)); -# else -# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup -# undef strdup -# endif -_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); -# endif -_GL_CXXALIASWARN (strdup); -# endif -#endif - -/* Append no more than N characters from SRC onto DEST. */ -#if @GNULIB_STRNCAT@ -# if @REPLACE_STRNCAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strncat -# define strncat rpl_strncat -# endif -_GL_FUNCDECL_RPL (strncat, char *, - (char *restrict dest, const char *restrict src, size_t n) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strncat, char *, - (char *restrict dest, const char *restrict src, size_t n)); -# else -_GL_CXXALIAS_SYS (strncat, char *, - (char *restrict dest, const char *restrict src, size_t n)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (strncat); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strncat -# if HAVE_RAW_DECL_STRNCAT -_GL_WARN_ON_USE (strncat, "strncat is unportable - " - "use gnulib module strncat for portability"); -# endif -#endif - -/* Return a newly allocated copy of at most N bytes of STRING. */ -#if @GNULIB_STRNDUP@ -# if @REPLACE_STRNDUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strndup -# define strndup rpl_strndup -# endif -_GL_FUNCDECL_RPL (strndup, char *, - (char const *__s, size_t __n) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -_GL_CXXALIAS_RPL (strndup, char *, (char const *__s, size_t __n)); -# else -# if !@HAVE_DECL_STRNDUP@ || (__GNUC__ >= 11 && !defined strndup) -_GL_FUNCDECL_SYS (strndup, char *, - (char const *__s, size_t __n) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -# endif -_GL_CXXALIAS_SYS (strndup, char *, (char const *__s, size_t __n)); -# endif -_GL_CXXALIASWARN (strndup); -#else -# if __GNUC__ >= 11 && !defined strndup -/* For -Wmismatched-dealloc: Associate strndup with free or rpl_free. */ -_GL_FUNCDECL_SYS (strndup, char *, - (char const *__s, size_t __n) - _GL_ARG_NONNULL ((1)) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE); -# endif -# if defined GNULIB_POSIXCHECK -# undef strndup -# if HAVE_RAW_DECL_STRNDUP -_GL_WARN_ON_USE (strndup, "strndup is unportable - " - "use gnulib module strndup for portability"); -# endif -# endif -#endif - -/* Find the length (number of bytes) of STRING, but scan at most - MAXLEN bytes. If no '\0' terminator is found in that many bytes, - return MAXLEN. */ -#if @GNULIB_STRNLEN@ -# if @REPLACE_STRNLEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strnlen -# define strnlen rpl_strnlen -# endif -_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__s, size_t __maxlen) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__s, size_t __maxlen)); -# else -# if ! @HAVE_DECL_STRNLEN@ -_GL_FUNCDECL_SYS (strnlen, size_t, (char const *__s, size_t __maxlen) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strnlen, size_t, (char const *__s, size_t __maxlen)); -# endif -_GL_CXXALIASWARN (strnlen); -#elif defined GNULIB_POSIXCHECK -# undef strnlen -# if HAVE_RAW_DECL_STRNLEN -_GL_WARN_ON_USE (strnlen, "strnlen is unportable - " - "use gnulib module strnlen for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strcspn() assumes the second argument is a list of single-byte characters. - Even in this simple case, it does not work with multibyte strings if the - locale encoding is GB18030 and one of the characters to be searched is a - digit. */ -# undef strcspn -/* Assume strcspn is always declared. */ -_GL_WARN_ON_USE (strcspn, "strcspn cannot work correctly on character strings " - "in multibyte locales - " - "use mbscspn if you care about internationalization"); -#endif - -/* Find the first occurrence in S of any character in ACCEPT. */ -#if @GNULIB_STRPBRK@ -# if ! @HAVE_STRPBRK@ -_GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C" { const char * strpbrk (const char *, const char *); } - extern "C++" { char * strpbrk (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strpbrk, - char *, (char const *__s, char const *__accept), - const char *, (char const *__s, char const *__accept)); -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept) throw ()); -_GL_CXXALIASWARN1 (strpbrk, char const *, - (char const *__s, char const *__accept) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (strpbrk); -# endif -# if defined GNULIB_POSIXCHECK -/* strpbrk() assumes the second argument is a list of single-byte characters. - Even in this simple case, it does not work with multibyte strings if the - locale encoding is GB18030 and one of the characters to be searched is a - digit. */ -# undef strpbrk -_GL_WARN_ON_USE_CXX (strpbrk, - const char *, char *, (const char *, const char *), - "strpbrk cannot work correctly on character strings " - "in multibyte locales - " - "use mbspbrk if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strpbrk -# if HAVE_RAW_DECL_STRPBRK -_GL_WARN_ON_USE_CXX (strpbrk, - const char *, char *, (const char *, const char *), - "strpbrk is unportable - " - "use gnulib module strpbrk for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strspn() assumes the second argument is a list of single-byte characters. - Even in this simple case, it cannot work with multibyte strings. */ -# undef strspn -/* Assume strspn is always declared. */ -_GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " - "in multibyte locales - " - "use mbsspn if you care about internationalization"); -#endif - -#if defined GNULIB_POSIXCHECK -/* strrchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ -# undef strrchr -/* Assume strrchr is always declared. */ -_GL_WARN_ON_USE_CXX (strrchr, - const char *, char *, (const char *, int), - "strrchr cannot work correctly on character strings " - "in some multibyte locales - " - "use mbsrchr if you care about internationalization"); -#endif - -/* Search the next delimiter (char listed in DELIM) starting at *STRINGP. - If one is found, overwrite it with a NUL, and advance *STRINGP - to point to the next char after it. Otherwise, set *STRINGP to NULL. - If *STRINGP was already NULL, nothing happens. - Return the old value of *STRINGP. - - This is a variant of strtok() that is multithread-safe and supports - empty fields. - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - Caveat: It doesn't work with multibyte strings unless all of the delimiter - characters are ASCII characters < 0x30. - - See also strtok_r(). */ -#if @GNULIB_STRSEP@ -# if ! @HAVE_STRSEP@ -_GL_FUNCDECL_SYS (strsep, char *, - (char **restrict __stringp, char const *restrict __delim) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (strsep, char *, - (char **restrict __stringp, char const *restrict __delim)); -_GL_CXXALIASWARN (strsep); -# if defined GNULIB_POSIXCHECK -# undef strsep -_GL_WARN_ON_USE (strsep, "strsep cannot work correctly on character strings " - "in multibyte locales - " - "use mbssep if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strsep -# if HAVE_RAW_DECL_STRSEP -_GL_WARN_ON_USE (strsep, "strsep is unportable - " - "use gnulib module strsep for portability"); -# endif -#endif - -#if @GNULIB_STRSTR@ -# if @REPLACE_STRSTR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strstr rpl_strstr -# endif -_GL_FUNCDECL_RPL (strstr, char *, (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strstr, char *, (const char *haystack, const char *needle)); -# else - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * strstr (const char *, const char *); } - extern "C++" { char * strstr (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strstr, - char *, (const char *haystack, const char *needle), - const char *, (const char *haystack, const char *needle)); -# endif -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (strstr, char *, - (char *haystack, const char *needle) throw ()); -_GL_CXXALIASWARN1 (strstr, const char *, - (const char *haystack, const char *needle) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (strstr); -# endif -#elif defined GNULIB_POSIXCHECK -/* strstr() does not work with multibyte strings if the locale encoding is - different from UTF-8: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strstr -/* Assume strstr is always declared. */ -_GL_WARN_ON_USE (strstr, "strstr is quadratic on many systems, and cannot " - "work correctly on character strings in most " - "multibyte locales - " - "use mbsstr if you care about internationalization, " - "or use strstr if you care about speed"); -#endif - -/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive - comparison. */ -#if @GNULIB_STRCASESTR@ -# if @REPLACE_STRCASESTR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strcasestr rpl_strcasestr -# endif -_GL_FUNCDECL_RPL (strcasestr, char *, - (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strcasestr, char *, - (const char *haystack, const char *needle)); -# else -# if ! @HAVE_STRCASESTR@ -_GL_FUNCDECL_SYS (strcasestr, char *, - (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * strcasestr (const char *, const char *); } - extern "C++" { char * strcasestr (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strcasestr, - char *, (const char *haystack, const char *needle), - const char *, (const char *haystack, const char *needle)); -# endif -# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10) && !defined __UCLIBC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \ - || defined __clang__) -_GL_CXXALIASWARN1 (strcasestr, char *, - (char *haystack, const char *needle) throw ()); -_GL_CXXALIASWARN1 (strcasestr, const char *, - (const char *haystack, const char *needle) throw ()); -# elif __GLIBC__ >= 2 -_GL_CXXALIASWARN (strcasestr); -# endif -#elif defined GNULIB_POSIXCHECK -/* strcasestr() does not work with multibyte strings: - It is a glibc extension, and glibc implements it only for unibyte - locales. */ -# undef strcasestr -# if HAVE_RAW_DECL_STRCASESTR -_GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " - "strings in multibyte locales - " - "use mbscasestr if you care about " - "internationalization, or use c-strcasestr if you want " - "a locale independent function"); -# endif -#endif - -/* Parse S into tokens separated by characters in DELIM. - If S is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = strtok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" - - This is a variant of strtok() that is multithread-safe. - - For the POSIX documentation for this function, see: - https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - Caveat: It doesn't work with multibyte strings unless all of the delimiter - characters are ASCII characters < 0x30. - - See also strsep(). */ -#if @GNULIB_STRTOK_R@ -# if @REPLACE_STRTOK_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strtok_r -# define strtok_r rpl_strtok_r -# endif -_GL_FUNCDECL_RPL (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr) - _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_RPL (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr)); -# else -# if @UNDEFINE_STRTOK_R@ || defined GNULIB_POSIXCHECK -# undef strtok_r -# endif -# if ! @HAVE_DECL_STRTOK_R@ -_GL_FUNCDECL_SYS (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr) - _GL_ARG_NONNULL ((2, 3))); -# endif -_GL_CXXALIAS_SYS (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr)); -# endif -_GL_CXXALIASWARN (strtok_r); -# if defined GNULIB_POSIXCHECK -_GL_WARN_ON_USE (strtok_r, "strtok_r cannot work correctly on character " - "strings in multibyte locales - " - "use mbstok_r if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strtok_r -# if HAVE_RAW_DECL_STRTOK_R -_GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " - "use gnulib module strtok_r for portability"); -# endif -#endif - - -/* The following functions are not specified by POSIX. They are gnulib - extensions. */ - -#if @GNULIB_MBSLEN@ -/* Return the number of multibyte characters in the character string STRING. - This considers multibyte characters, unlike strlen, which counts bytes. */ -# ifdef __MirBSD__ /* MirBSD defines mbslen as a macro. Override it. */ -# undef mbslen -# endif -# if @HAVE_MBSLEN@ /* AIX, OSF/1, MirBSD define mbslen already in libc. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbslen rpl_mbslen -# endif -_GL_FUNCDECL_RPL (mbslen, size_t, (const char *string) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbslen, size_t, (const char *string)); -# else -_GL_FUNCDECL_SYS (mbslen, size_t, (const char *string) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (mbslen); -# endif -#endif - -#if @GNULIB_MBSNLEN@ -/* Return the number of multibyte characters in the character string starting - at STRING and ending at STRING + LEN. */ -_GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1)); -#endif - -#if @GNULIB_MBSCHR@ -/* Locate the first single-byte character C in the character string STRING, - and return a pointer to it. Return NULL if C is not found in STRING. - Unlike strchr(), this function works correctly in multibyte locales with - encodings such as GB18030. */ -# if defined __hpux -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbschr rpl_mbschr /* avoid collision with HP-UX function */ -# endif -_GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbschr, char *, (const char *string, int c)); -# else -_GL_FUNCDECL_SYS (mbschr, char *, (const char *string, int c) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); -# endif -_GL_CXXALIASWARN (mbschr); -#endif - -#if @GNULIB_MBSRCHR@ -/* Locate the last single-byte character C in the character string STRING, - and return a pointer to it. Return NULL if C is not found in STRING. - Unlike strrchr(), this function works correctly in multibyte locales with - encodings such as GB18030. */ -# if defined __hpux || defined __INTERIX -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbsrchr rpl_mbsrchr /* avoid collision with system function */ -# endif -_GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbsrchr, char *, (const char *string, int c)); -# else -_GL_FUNCDECL_SYS (mbsrchr, char *, (const char *string, int c) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); -# endif -_GL_CXXALIASWARN (mbsrchr); -#endif - -#if @GNULIB_MBSSTR@ -/* Find the first occurrence of the character string NEEDLE in the character - string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. - Unlike strstr(), this function works correctly in multibyte locales with - encodings different from UTF-8. */ -_GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCASECMP@ -/* Compare the character strings S1 and S2, ignoring case, returning less than, - equal to or greater than zero if S1 is lexicographically less than, equal to - or greater than S2. - Note: This function may, in multibyte locales, return 0 for strings of - different lengths! - Unlike strcasecmp(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSNCASECMP@ -/* Compare the initial segment of the character string S1 consisting of at most - N characters with the initial segment of the character string S2 consisting - of at most N characters, ignoring case, returning less than, equal to or - greater than zero if the initial segment of S1 is lexicographically less - than, equal to or greater than the initial segment of S2. - Note: This function may, in multibyte locales, return 0 for initial segments - of different lengths! - Unlike strncasecmp(), this function works correctly in multibyte locales. - But beware that N is not a byte count but a character count! */ -_GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSPCASECMP@ -/* Compare the initial segment of the character string STRING consisting of - at most mbslen (PREFIX) characters with the character string PREFIX, - ignoring case. If the two match, return a pointer to the first byte - after this prefix in STRING. Otherwise, return NULL. - Note: This function may, in multibyte locales, return non-NULL if STRING - is of smaller length than PREFIX! - Unlike strncasecmp(), this function works correctly in multibyte - locales. */ -_GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCASESTR@ -/* Find the first occurrence of the character string NEEDLE in the character - string HAYSTACK, using case-insensitive comparison. - Note: This function may, in multibyte locales, return success even if - strlen (haystack) < strlen (needle) ! - Unlike strcasestr(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCSPN@ -/* Find the first occurrence in the character string STRING of any character - in the character string ACCEPT. Return the number of bytes from the - beginning of the string to this occurrence, or to the end of the string - if none exists. - Unlike strcspn(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSPBRK@ -/* Find the first occurrence in the character string STRING of any character - in the character string ACCEPT. Return the pointer to it, or NULL if none - exists. - Unlike strpbrk(), this function works correctly in multibyte locales. */ -# if defined __hpux -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ -# endif -_GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (mbspbrk, char *, (const char *string, const char *accept)); -# else -_GL_FUNCDECL_SYS (mbspbrk, char *, (const char *string, const char *accept) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); -# endif -_GL_CXXALIASWARN (mbspbrk); -#endif - -#if @GNULIB_MBSSPN@ -/* Find the first occurrence in the character string STRING of any character - not in the character string REJECT. Return the number of bytes from the - beginning of the string to this occurrence, or to the end of the string - if none exists. - Unlike strspn(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C size_t mbsspn (const char *string, const char *reject) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSSEP@ -/* Search the next delimiter (multibyte character listed in the character - string DELIM) starting at the character string *STRINGP. - If one is found, overwrite it with a NUL, and advance *STRINGP to point - to the next multibyte character after it. Otherwise, set *STRINGP to NULL. - If *STRINGP was already NULL, nothing happens. - Return the old value of *STRINGP. - - This is a variant of mbstok_r() that supports empty fields. - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - - See also mbstok_r(). */ -_GL_EXTERN_C char * mbssep (char **stringp, const char *delim) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSTOK_R@ -/* Parse the character string STRING into tokens separated by characters in - the character string DELIM. - If STRING is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = mbstok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - - See also mbssep(). */ -_GL_EXTERN_C char * mbstok_r (char *restrict string, const char *delim, - char **save_ptr) - _GL_ARG_NONNULL ((2, 3)); -#endif - -/* Map any int, typically from errno, into an error message. */ -#if @GNULIB_STRERROR@ -# if @REPLACE_STRERROR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strerror -# define strerror rpl_strerror -# endif -_GL_FUNCDECL_RPL (strerror, char *, (int)); -_GL_CXXALIAS_RPL (strerror, char *, (int)); -# else -_GL_CXXALIAS_SYS (strerror, char *, (int)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (strerror); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strerror -/* Assume strerror is always declared. */ -_GL_WARN_ON_USE (strerror, "strerror is unportable - " - "use gnulib module strerror to guarantee non-NULL result"); -#endif - -/* Map any int, typically from errno, into an error message. Multithread-safe. - Uses the POSIX declaration, not the glibc declaration. */ -#if @GNULIB_STRERROR_R@ -# if @REPLACE_STRERROR_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strerror_r -# define strerror_r rpl_strerror_r -# endif -_GL_FUNCDECL_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (strerror_r, int, (int errnum, char *buf, size_t buflen)); -# else -# if !@HAVE_DECL_STRERROR_R@ -_GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen)); -# endif -# if @HAVE_DECL_STRERROR_R@ -_GL_CXXALIASWARN (strerror_r); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strerror_r -# if HAVE_RAW_DECL_STRERROR_R -_GL_WARN_ON_USE (strerror_r, "strerror_r is unportable - " - "use gnulib module strerror_r-posix for portability"); -# endif -#endif - -/* Return the name of the system error code ERRNUM. */ -#if @GNULIB_STRERRORNAME_NP@ -# if @REPLACE_STRERRORNAME_NP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strerrorname_np -# define strerrorname_np rpl_strerrorname_np -# endif -_GL_FUNCDECL_RPL (strerrorname_np, const char *, (int errnum)); -_GL_CXXALIAS_RPL (strerrorname_np, const char *, (int errnum)); -# else -# if !@HAVE_STRERRORNAME_NP@ -_GL_FUNCDECL_SYS (strerrorname_np, const char *, (int errnum)); -# endif -_GL_CXXALIAS_SYS (strerrorname_np, const char *, (int errnum)); -# endif -_GL_CXXALIASWARN (strerrorname_np); -#elif defined GNULIB_POSIXCHECK -# undef strerrorname_np -# if HAVE_RAW_DECL_STRERRORNAME_NP -_GL_WARN_ON_USE (strerrorname_np, "strerrorname_np is unportable - " - "use gnulib module strerrorname_np for portability"); -# endif -#endif - -/* Return an abbreviation string for the signal number SIG. */ -#if @GNULIB_SIGABBREV_NP@ -# if ! @HAVE_SIGABBREV_NP@ -_GL_FUNCDECL_SYS (sigabbrev_np, const char *, (int sig)); -# endif -_GL_CXXALIAS_SYS (sigabbrev_np, const char *, (int sig)); -_GL_CXXALIASWARN (sigabbrev_np); -#elif defined GNULIB_POSIXCHECK -# undef sigabbrev_np -# if HAVE_RAW_DECL_SIGABBREV_NP -_GL_WARN_ON_USE (sigabbrev_np, "sigabbrev_np is unportable - " - "use gnulib module sigabbrev_np for portability"); -# endif -#endif - -/* Return an English description string for the signal number SIG. */ -#if @GNULIB_SIGDESCR_NP@ -# if ! @HAVE_SIGDESCR_NP@ -_GL_FUNCDECL_SYS (sigdescr_np, const char *, (int sig)); -# endif -_GL_CXXALIAS_SYS (sigdescr_np, const char *, (int sig)); -_GL_CXXALIASWARN (sigdescr_np); -#elif defined GNULIB_POSIXCHECK -# undef sigdescr_np -# if HAVE_RAW_DECL_SIGDESCR_NP -_GL_WARN_ON_USE (sigdescr_np, "sigdescr_np is unportable - " - "use gnulib module sigdescr_np for portability"); -# endif -#endif - -#if @GNULIB_STRSIGNAL@ -# if @REPLACE_STRSIGNAL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strsignal rpl_strsignal -# endif -_GL_FUNCDECL_RPL (strsignal, char *, (int __sig)); -_GL_CXXALIAS_RPL (strsignal, char *, (int __sig)); -# else -# if ! @HAVE_DECL_STRSIGNAL@ -_GL_FUNCDECL_SYS (strsignal, char *, (int __sig)); -# endif -/* Need to cast, because on Cygwin 1.5.x systems, the return type is - 'const char *'. */ -_GL_CXXALIAS_SYS_CAST (strsignal, char *, (int __sig)); -# endif -_GL_CXXALIASWARN (strsignal); -#elif defined GNULIB_POSIXCHECK -# undef strsignal -# if HAVE_RAW_DECL_STRSIGNAL -_GL_WARN_ON_USE (strsignal, "strsignal is unportable - " - "use gnulib module strsignal for portability"); -# endif -#endif - -#if @GNULIB_STRVERSCMP@ -# if !@HAVE_STRVERSCMP@ -_GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); -_GL_CXXALIASWARN (strverscmp); -#elif defined GNULIB_POSIXCHECK -# undef strverscmp -# if HAVE_RAW_DECL_STRVERSCMP -_GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " - "use gnulib module strverscmp for portability"); -# endif -#endif - - -#endif /* _@GUARD_PREFIX@_STRING_H */ -#endif /* _@GUARD_PREFIX@_STRING_H */ -#endif diff --git a/xcompile/lib/strnlen.c b/xcompile/lib/strnlen.c deleted file mode 100644 index 09c010eac42..00000000000 --- a/xcompile/lib/strnlen.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc. - Written by Simon Josefsson. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#include - -/* Find the length of STRING, but scan at most MAXLEN characters. - If no '\0' terminator is found in that many characters, return MAXLEN. */ - -size_t -strnlen (const char *string, size_t maxlen) -{ - const char *end = memchr (string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} diff --git a/xcompile/lib/strtoimax.c b/xcompile/lib/strtoimax.c deleted file mode 100644 index f7977e28e64..00000000000 --- a/xcompile/lib/strtoimax.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Convert string representation of a number into an intmax_t value. - - Copyright (C) 1999, 2001-2004, 2006, 2009-2023 Free Software Foundation, - Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include - -/* Verify interface. */ -#include - -#include - -#ifdef UNSIGNED -# ifndef HAVE_DECL_STRTOULL -"this configure-time declaration test was not run" -# endif -# if !HAVE_DECL_STRTOULL -unsigned long long int strtoull (char const *, char **, int); -# endif - -#else - -# ifndef HAVE_DECL_STRTOLL -"this configure-time declaration test was not run" -# endif -# if !HAVE_DECL_STRTOLL -long long int strtoll (char const *, char **, int); -# endif -#endif - -#ifdef UNSIGNED -# define Int uintmax_t -# define Strtoimax strtoumax -# define Strtol strtoul -# define Strtoll strtoull -# define Unsigned unsigned -#else -# define Int intmax_t -# define Strtoimax strtoimax -# define Strtol strtol -# define Strtoll strtoll -# define Unsigned -#endif - -Int -Strtoimax (char const *ptr, char **endptr, int base) -{ - static_assert (sizeof (Int) == sizeof (Unsigned long int) - || sizeof (Int) == sizeof (Unsigned long long int)); - - if (sizeof (Int) != sizeof (Unsigned long int)) - return Strtoll (ptr, endptr, base); - - return Strtol (ptr, endptr, base); -} diff --git a/xcompile/lib/strtol.c b/xcompile/lib/strtol.c deleted file mode 100644 index d11269b2622..00000000000 --- a/xcompile/lib/strtol.c +++ /dev/null @@ -1,408 +0,0 @@ -/* Convert string representation of a number into an integer value. - - Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2023 Free Software - Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@gnu.org. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#ifdef _LIBC -# define USE_NUMBER_GROUPING -#else -# include -#endif - -#include -#include -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif - -#include -#include -#include -#include - -#ifdef USE_NUMBER_GROUPING -# include "../locale/localeinfo.h" -#endif - -/* Nonzero if we are defining 'strtoul' or 'strtoull', operating on - unsigned integers. */ -#ifndef UNSIGNED -# define UNSIGNED 0 -# define INT LONG int -#else -# define INT unsigned LONG int -#endif - -/* Determine the name. */ -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# undef strtol -# if UNSIGNED -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol __wcstoull_l -# else -# define strtol __wcstoul_l -# endif -# else -# ifdef QUAD -# define strtol __strtoull_l -# else -# define strtol __strtoul_l -# endif -# endif -# else -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol __wcstoll_l -# else -# define strtol __wcstol_l -# endif -# else -# ifdef QUAD -# define strtol __strtoll_l -# else -# define strtol __strtol_l -# endif -# endif -# endif -#else -# if UNSIGNED -# undef strtol -# ifdef USE_WIDE_CHAR -# ifdef QUAD -# define strtol wcstoull -# else -# define strtol wcstoul -# endif -# else -# ifdef QUAD -# define strtol strtoull -# else -# define strtol strtoul -# endif -# endif -# else -# ifdef USE_WIDE_CHAR -# undef strtol -# ifdef QUAD -# define strtol wcstoll -# else -# define strtol wcstol -# endif -# else -# ifdef QUAD -# undef strtol -# define strtol strtoll -# endif -# endif -# endif -#endif - -/* If QUAD is defined, we are defining 'strtoll' or 'strtoull', - operating on 'long long int's. */ -#ifdef QUAD -# define LONG long long -# define STRTOL_LONG_MIN LLONG_MIN -# define STRTOL_LONG_MAX LLONG_MAX -# define STRTOL_ULONG_MAX ULLONG_MAX -# if __GNUC__ == 2 && __GNUC_MINOR__ < 7 - /* Work around gcc bug with using this constant. */ - static const unsigned long long int maxquad = ULLONG_MAX; -# undef STRTOL_ULONG_MAX -# define STRTOL_ULONG_MAX maxquad -# endif -#else -# define LONG long -# define STRTOL_LONG_MIN LONG_MIN -# define STRTOL_LONG_MAX LONG_MAX -# define STRTOL_ULONG_MAX ULONG_MAX -#endif - - -#ifdef USE_NUMBER_GROUPING -# define GROUP_PARAM_PROTO , int group -#else -# define GROUP_PARAM_PROTO -#endif - -/* We use this code also for the extended locale handling where the - function gets as an additional argument the locale which has to be - used. To access the values we have to redefine the _NL_CURRENT - macro. */ -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# undef _NL_CURRENT -# define _NL_CURRENT(category, item) \ - (current->values[_NL_ITEM_INDEX (item)].string) -# define LOCALE_PARAM , loc -# define LOCALE_PARAM_PROTO , __locale_t loc -#else -# define LOCALE_PARAM -# define LOCALE_PARAM_PROTO -#endif - -#ifdef USE_WIDE_CHAR -# include -# include -# define L_(Ch) L##Ch -# define UCHAR_TYPE wint_t -# define STRING_TYPE wchar_t -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __iswspace_l ((Ch), loc) -# define ISALPHA(Ch) __iswalpha_l ((Ch), loc) -# define TOUPPER(Ch) __towupper_l ((Ch), loc) -# else -# define ISSPACE(Ch) iswspace (Ch) -# define ISALPHA(Ch) iswalpha (Ch) -# define TOUPPER(Ch) towupper (Ch) -# endif -#else -# define L_(Ch) Ch -# define UCHAR_TYPE unsigned char -# define STRING_TYPE char -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc) -# define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc) -# define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc) -# else -# define ISSPACE(Ch) isspace ((unsigned char) (Ch)) -# define ISALPHA(Ch) isalpha ((unsigned char) (Ch)) -# define TOUPPER(Ch) toupper ((unsigned char) (Ch)) -# endif -#endif - -#ifdef USE_NUMBER_GROUPING -# define INTERNAL(X) INTERNAL1(X) -# define INTERNAL1(X) __##X##_internal -# define WEAKNAME(X) WEAKNAME1(X) -#else -# define INTERNAL(X) X -#endif - -#ifdef USE_NUMBER_GROUPING -/* This file defines a function to check for correct grouping. */ -# include "grouping.h" -#endif - - - -/* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE. - If BASE is 0 the base is determined by the presence of a leading - zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. - If BASE is < 2 or > 36, it is reset to 10. - If ENDPTR is not NULL, a pointer to the character after the last - one converted is stored in *ENDPTR. */ - -INT -INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr, - int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO) -{ - int negative; - register unsigned LONG int cutoff; - register unsigned int cutlim; - register unsigned LONG int i; - register const STRING_TYPE *s; - register UCHAR_TYPE c; - const STRING_TYPE *save, *end; - int overflow; - -#ifdef USE_NUMBER_GROUPING -# ifdef USE_IN_EXTENDED_LOCALE_MODEL - struct locale_data *current = loc->__locales[LC_NUMERIC]; -# endif - /* The thousands character of the current locale. */ - wchar_t thousands = L'\0'; - /* The numeric grouping specification of the current locale, - in the format described in . */ - const char *grouping; - - if (group) - { - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); - if (*grouping <= 0 || *grouping == CHAR_MAX) - grouping = NULL; - else - { - /* Figure out the thousands separator character. */ -# if defined _LIBC || defined _HAVE_BTOWC - thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); - if (thousands == WEOF) - thousands = L'\0'; -# endif - if (thousands == L'\0') - grouping = NULL; - } - } - else - grouping = NULL; -#endif - - if (base < 0 || base == 1 || base > 36) - { - __set_errno (EINVAL); - return 0; - } - - save = s = nptr; - - /* Skip white space. */ - while (ISSPACE (*s)) - ++s; - if (*s == L_('\0')) - goto noconv; - - /* Check for a sign. */ - if (*s == L_('-')) - { - negative = 1; - ++s; - } - else if (*s == L_('+')) - { - negative = 0; - ++s; - } - else - negative = 0; - - /* Recognize number prefix and if BASE is zero, figure it out ourselves. */ - if (*s == L_('0')) - { - if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X')) - { - s += 2; - base = 16; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; - - /* Save the pointer so we can check later if anything happened. */ - save = s; - -#ifdef USE_NUMBER_GROUPING - if (group) - { - /* Find the end of the digit string and check its grouping. */ - end = s; - for (c = *end; c != L_('\0'); c = *++end) - if ((wchar_t) c != thousands - && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9')) - && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base)) - break; - if (*s == thousands) - end = s; - else - end = correctly_grouped_prefix (s, end, thousands, grouping); - } - else -#endif - end = NULL; - - cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; - cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; - - overflow = 0; - i = 0; - for (c = *s; c != L_('\0'); c = *++s) - { - if (s == end) - break; - if (c >= L_('0') && c <= L_('9')) - c -= L_('0'); - else if (ISALPHA (c)) - c = TOUPPER (c) - L_('A') + 10; - else - break; - if ((int) c >= base) - break; - /* Check for overflow. */ - if (i > cutoff || (i == cutoff && c > cutlim)) - overflow = 1; - else - { - i *= (unsigned LONG int) base; - i += c; - } - } - - /* Check if anything actually happened. */ - if (s == save) - goto noconv; - - /* Store in ENDPTR the address of one character - past the last character we converted. */ - if (endptr != NULL) - *endptr = (STRING_TYPE *) s; - -#if !UNSIGNED - /* Check for a value that is within the range of - 'unsigned LONG int', but outside the range of 'LONG int'. */ - if (overflow == 0 - && i > (negative - ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1 - : (unsigned LONG int) STRTOL_LONG_MAX)) - overflow = 1; -#endif - - if (overflow) - { - __set_errno (ERANGE); -#if UNSIGNED - return STRTOL_ULONG_MAX; -#else - return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX; -#endif - } - - /* Return the result of the appropriate sign. */ - return negative ? -i : i; - -noconv: - /* We must handle a special case here: the base is 0 or 16 and the - first two characters are '0' and 'x', but the rest are no - hexadecimal digits. This is no error case. We return 0 and - ENDPTR points to the 'x'. */ - if (endptr != NULL) - { - if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X') - && save[-2] == L_('0')) - *endptr = (STRING_TYPE *) &save[-1]; - else - /* There was no number to convert. */ - *endptr = (STRING_TYPE *) nptr; - } - - return 0L; -} - -#ifdef USE_NUMBER_GROUPING -/* External user entry point. */ - -INT -# ifdef weak_function -weak_function -# endif -strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr, - int base LOCALE_PARAM_PROTO) -{ - return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM); -} -#endif diff --git a/xcompile/lib/strtoll.c b/xcompile/lib/strtoll.c deleted file mode 100644 index 9fdfa19b220..00000000000 --- a/xcompile/lib/strtoll.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Function to parse a 'long long int' from text. - Copyright (C) 1995-1997, 1999, 2001, 2009-2023 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#define QUAD 1 - -#include - -#ifdef _LIBC -# ifdef SHARED -# include - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2) -compat_symbol (libc, __strtoll_internal, __strtoq_internal, GLIBC_2_0); -# endif - -# endif -weak_alias (strtoll, strtoq) -#endif diff --git a/xcompile/lib/symlink.c b/xcompile/lib/symlink.c deleted file mode 100644 index b5009ae8355..00000000000 --- a/xcompile/lib/symlink.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Stub for symlink(). - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include - - -#if HAVE_SYMLINK - -# undef symlink - -/* Create a symlink, but reject trailing slash. */ -int -rpl_symlink (char const *contents, char const *name) -{ - size_t len = strlen (name); - if (len && name[len - 1] == '/') - { - struct stat st; - if (lstat (name, &st) == 0 || errno == EOVERFLOW) - errno = EEXIST; - return -1; - } - return symlink (contents, name); -} - -#else /* !HAVE_SYMLINK */ - -/* The system does not support symlinks. */ -int -symlink (_GL_UNUSED char const *contents, - _GL_UNUSED char const *name) -{ - errno = ENOSYS; - return -1; -} - -#endif /* !HAVE_SYMLINK */ diff --git a/xcompile/lib/sys_random.in.h b/xcompile/lib/sys_random.in.h deleted file mode 100644 index 8dca1326837..00000000000 --- a/xcompile/lib/sys_random.in.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Substitute for . - Copyright (C) 2020-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -# if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -# endif -@PRAGMA_COLUMNS@ - -#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H - -#if @HAVE_SYS_RANDOM_H@ - -/* On uClibc < 1.0.35, assumes prior inclusion of . - Do not use __UCLIBC__ here, as it might not be defined yet. - But avoid namespace pollution on glibc systems. */ -# ifndef __GLIBC__ -# include -# endif -/* On Mac OS X 10.5, assumes prior inclusion of . - On Max OS X 10.13, assumes prior inclusion of a file that - includes , such as or . */ -# if defined __APPLE__ && defined __MACH__ /* Mac OS X */ -# include -# include -# endif - -/* The include_next requires a split double-inclusion guard. */ -# @INCLUDE_NEXT@ @NEXT_SYS_RANDOM_H@ - -#endif - -#ifndef _@GUARD_PREFIX@_SYS_RANDOM_H -#define _@GUARD_PREFIX@_SYS_RANDOM_H - -#include - -/* Define the GRND_* constants. */ -#ifndef GRND_NONBLOCK -# define GRND_NONBLOCK 1 -# define GRND_RANDOM 2 -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Declare overridden functions. */ - - -#if @GNULIB_GETRANDOM@ -/* Fill a buffer with random bytes. */ -# if @REPLACE_GETRANDOM@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getrandom -# define getrandom rpl_getrandom -# endif -_GL_FUNCDECL_RPL (getrandom, ssize_t, - (void *buffer, size_t length, unsigned int flags) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (getrandom, ssize_t, - (void *buffer, size_t length, unsigned int flags)); -# else -# if !@HAVE_GETRANDOM@ -_GL_FUNCDECL_SYS (getrandom, ssize_t, - (void *buffer, size_t length, unsigned int flags) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (getrandom, ssize_t, - (void *buffer, size_t length, unsigned int flags)); -# endif -# if __GLIBC__ + (__GLIBC_MINOR__ >= 25) > 2 -_GL_CXXALIASWARN (getrandom); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getrandom -# if HAVE_RAW_DECL_GETRANDOM -_GL_WARN_ON_USE (getrandom, "getrandom is unportable - " - "use gnulib module getrandom for portability"); -# endif -#endif - - -#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */ -#endif /* _@GUARD_PREFIX@_SYS_RANDOM_H */ diff --git a/xcompile/lib/sys_select.in.h b/xcompile/lib/sys_select.in.h deleted file mode 100644 index 13440fa6f0a..00000000000 --- a/xcompile/lib/sys_select.in.h +++ /dev/null @@ -1,334 +0,0 @@ -/* Substitute for . - Copyright (C) 2007-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -# if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -# endif -@PRAGMA_COLUMNS@ - -/* On OSF/1 and Solaris 2.6, and - both include . - On Cygwin and OpenBSD, includes . - Simply delegate to the system's header in this case. */ -#if (@HAVE_SYS_SELECT_H@ \ - && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H \ - && ((defined __osf__ && defined _SYS_TYPES_H_ \ - && defined _OSF_SOURCE) \ - || (defined __sun && defined _SYS_TYPES_H \ - && (! (defined _XOPEN_SOURCE || defined _POSIX_C_SOURCE) \ - || defined __EXTENSIONS__)))) - -# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H -# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ - -#elif (@HAVE_SYS_SELECT_H@ \ - && (defined _CYGWIN_SYS_TIME_H \ - || (!defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H \ - && ((defined __osf__ && defined _SYS_TIME_H_ \ - && defined _OSF_SOURCE) \ - || (defined __OpenBSD__ && defined _SYS_TIME_H_) \ - || (defined __sun && defined _SYS_TIME_H \ - && (! (defined _XOPEN_SOURCE \ - || defined _POSIX_C_SOURCE) \ - || defined __EXTENSIONS__)))))) - -# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H -# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ - -/* On IRIX 6.5, includes , which includes - , which includes . At this point we cannot - include , because that includes , which - gives a syntax error because has not been completely - processed. Simply delegate to the system's header in this case. */ -#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H) - -# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H -# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ - -/* On OpenBSD 5.0, includes , which includes - . At this point we cannot include , because that - includes gnulib's pthread.h override, which gives a syntax error because - /usr/include/pthread.h has not been completely processed. Simply delegate - to the system's header in this case. */ -#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER) - -# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ - -#else - -#ifndef _@GUARD_PREFIX@_SYS_SELECT_H - -/* On many platforms, assumes prior inclusion of - . Also, mingw defines sigset_t there, instead of - in where it belongs. */ -#include - -#if @HAVE_SYS_SELECT_H@ - -/* On OSF/1 4.0, provides only a forward declaration - of 'struct timeval', and no definition of this type. - Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select() - in . - But avoid namespace pollution on glibc systems, a circular include - -> -> on FreeBSD 13.1, and - "unknown type name" problems on Cygwin. */ -# if !(defined __GLIBC__ || defined __FreeBSD__ || defined __CYGWIN__) -# include -# endif - -/* On AIX 7 and Solaris 10, provides an FD_ZERO implementation - that relies on memset(), but without including . - But in any case avoid namespace pollution on glibc systems. */ -# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \ - && ! defined __GLIBC__ -# include -# endif - -/* The include_next requires a split double-inclusion guard. */ -# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@ - -#endif - -/* Get definition of 'sigset_t'. - But avoid namespace pollution on glibc systems and "unknown type - name" problems on Cygwin. - On OS/2 kLIBC, sigset_t is defined in , too. In addition, - if is included, -> -> - are included. Then -> are included by GNULIB. By the - way, requires PAGE_SIZE defined in . However, - has not been processed, yet. As a result, 'PAGE_SIZE' - undeclared error occurs in . - Do this after the include_next (for the sake of OpenBSD 5.0) but before - the split double-inclusion guard (for the sake of Solaris). */ -#if !((defined __GLIBC__ || defined __CYGWIN__ || defined __KLIBC__) \ - && !defined __UCLIBC__) -# include -#endif - -#ifndef _@GUARD_PREFIX@_SYS_SELECT_H -#define _@GUARD_PREFIX@_SYS_SELECT_H - -#if !@HAVE_SYS_SELECT_H@ -/* A platform that lacks . */ -/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros - on most platforms. */ -# include -/* On HP-UX 11, provides an FD_ZERO implementation - that relies on memset(), but without including . */ -# if defined __hpux -# include -# endif -/* On native Windows platforms: - Get the 'fd_set' type. - Get the close() declaration before we override it. */ -# if @HAVE_WINSOCK2_H@ -# if !defined _GL_INCLUDING_WINSOCK2_H -# define _GL_INCLUDING_WINSOCK2_H -# include -# undef _GL_INCLUDING_WINSOCK2_H -# endif -# include -# endif -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Fix some definitions from . */ - -#if @HAVE_WINSOCK2_H@ - -# if !GNULIB_defined_rpl_fd_isset - -/* Re-define FD_ISSET to avoid a WSA call while we are not using - network sockets. */ -static int -rpl_fd_isset (SOCKET fd, fd_set * set) -{ - u_int i; - if (set == NULL) - return 0; - - for (i = 0; i < set->fd_count; i++) - if (set->fd_array[i] == fd) - return 1; - - return 0; -} - -# define GNULIB_defined_rpl_fd_isset 1 -# endif - -# undef FD_ISSET -# define FD_ISSET(fd, set) rpl_fd_isset(fd, set) - -#endif - -/* Hide some function declarations from . */ - -#if @HAVE_WINSOCK2_H@ -# if !defined _@GUARD_PREFIX@_UNISTD_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef close -# define close close_used_without_including_unistd_h -# elif !defined __clang__ - _GL_WARN_ON_USE (close, - "close() used without including "); -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gethostname -# define gethostname gethostname_used_without_including_unistd_h -# elif !defined __clang__ - _GL_WARN_ON_USE (gethostname, - "gethostname() used without including "); -# endif -# endif -# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef socket -# define socket socket_used_without_including_sys_socket_h -# undef connect -# define connect connect_used_without_including_sys_socket_h -# undef accept -# define accept accept_used_without_including_sys_socket_h -# undef bind -# define bind bind_used_without_including_sys_socket_h -# undef getpeername -# define getpeername getpeername_used_without_including_sys_socket_h -# undef getsockname -# define getsockname getsockname_used_without_including_sys_socket_h -# undef getsockopt -# define getsockopt getsockopt_used_without_including_sys_socket_h -# undef listen -# define listen listen_used_without_including_sys_socket_h -# undef recv -# define recv recv_used_without_including_sys_socket_h -# undef send -# define send send_used_without_including_sys_socket_h -# undef recvfrom -# define recvfrom recvfrom_used_without_including_sys_socket_h -# undef sendto -# define sendto sendto_used_without_including_sys_socket_h -# undef setsockopt -# define setsockopt setsockopt_used_without_including_sys_socket_h -# undef shutdown -# define shutdown shutdown_used_without_including_sys_socket_h -# elif !defined __clang__ - _GL_WARN_ON_USE (socket, - "socket() used without including "); - _GL_WARN_ON_USE (connect, - "connect() used without including "); - _GL_WARN_ON_USE (accept, - "accept() used without including "); - _GL_WARN_ON_USE (bind, - "bind() used without including "); - _GL_WARN_ON_USE (getpeername, - "getpeername() used without including "); - _GL_WARN_ON_USE (getsockname, - "getsockname() used without including "); - _GL_WARN_ON_USE (getsockopt, - "getsockopt() used without including "); - _GL_WARN_ON_USE (listen, - "listen() used without including "); - _GL_WARN_ON_USE (recv, - "recv() used without including "); - _GL_WARN_ON_USE (send, - "send() used without including "); - _GL_WARN_ON_USE (recvfrom, - "recvfrom() used without including "); - _GL_WARN_ON_USE (sendto, - "sendto() used without including "); - _GL_WARN_ON_USE (setsockopt, - "setsockopt() used without including "); - _GL_WARN_ON_USE (shutdown, - "shutdown() used without including "); -# endif -# endif -#endif - - -#if @GNULIB_PSELECT@ -# if @REPLACE_PSELECT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef pselect -# define pselect rpl_pselect -# endif -_GL_FUNCDECL_RPL (pselect, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timespec const *restrict, const sigset_t *restrict)); -_GL_CXXALIAS_RPL (pselect, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timespec const *restrict, const sigset_t *restrict)); -# else -# if !@HAVE_PSELECT@ -_GL_FUNCDECL_SYS (pselect, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timespec const *restrict, const sigset_t *restrict)); -# endif -/* Need to cast, because on AIX 7, the second, third, fourth argument may be - void *restrict, void *restrict, void *restrict. */ -_GL_CXXALIAS_SYS_CAST (pselect, int, - (int, - fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timespec const *restrict, - const sigset_t *restrict)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (pselect); -# endif -#elif defined GNULIB_POSIXCHECK -# undef pselect -# if HAVE_RAW_DECL_PSELECT -_GL_WARN_ON_USE (pselect, "pselect is not portable - " - "use gnulib module pselect for portability"); -# endif -#endif - -#if @GNULIB_SELECT@ -# if @REPLACE_SELECT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef select -# define select rpl_select -# endif -_GL_FUNCDECL_RPL (select, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - struct timeval *restrict)); -_GL_CXXALIAS_RPL (select, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - timeval *restrict)); -# else -_GL_CXXALIAS_SYS (select, int, - (int, fd_set *restrict, fd_set *restrict, fd_set *restrict, - timeval *restrict)); -# endif -_GL_CXXALIASWARN (select); -#elif @HAVE_WINSOCK2_H@ -# undef select -# define select select_used_without_requesting_gnulib_module_select -#elif defined GNULIB_POSIXCHECK -# undef select -# if HAVE_RAW_DECL_SELECT -_GL_WARN_ON_USE (select, "select is not always POSIX compliant - " - "use gnulib module select for portability"); -# endif -#endif - - -#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ -#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */ -#endif /* OSF/1 */ diff --git a/xcompile/lib/sys_stat.in.h b/xcompile/lib/sys_stat.in.h deleted file mode 100644 index 096887c0162..00000000000 --- a/xcompile/lib/sys_stat.in.h +++ /dev/null @@ -1,954 +0,0 @@ -/* Provide a more complete sys/stat.h header file. - Copyright (C) 2005-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Eric Blake, Paul Eggert, and Jim Meyering. */ - -/* This file is supposed to be used on platforms where is - incomplete. It is intended to provide definitions and prototypes - needed by an application. Start with what the system provides. */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined __need_system_sys_stat_h -/* Special invocation convention. */ - -#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_SYS_STAT_H - -/* Get nlink_t. - May also define off_t to a 64-bit type on native Windows. */ -#include - -/* Get struct timespec. */ -#include - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_SYS_STAT_H@ - -#ifndef _@GUARD_PREFIX@_SYS_STAT_H -#define _@GUARD_PREFIX@_SYS_STAT_H - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Before doing "#define mknod rpl_mknod" below, we need to include all - headers that may declare mknod(). OS/2 kLIBC declares mknod() in - , not in . */ -#ifdef __KLIBC__ -# include -#endif - -/* Before doing "#define mkdir rpl_mkdir" below, we need to include all - headers that may declare mkdir(). Native Windows platforms declare mkdir - in and/or , not in . */ -#if defined _WIN32 && ! defined __CYGWIN__ -# include /* mingw32, mingw64 */ -# include /* mingw64, MSVC 9 */ -#endif - -/* Native Windows platforms declare umask() in . */ -#if 0 && (defined _WIN32 && ! defined __CYGWIN__) -# include -#endif - -/* Large File Support on native Windows. */ -#if @WINDOWS_64_BIT_ST_SIZE@ -# define stat _stati64 -#endif - -/* Optionally, override 'struct stat' on native Windows. */ -#if @GNULIB_OVERRIDES_STRUCT_STAT@ - -# undef stat -# if @GNULIB_STAT@ -# define stat rpl_stat -# else - /* Provoke a clear link error if stat() is used as a function and - module 'stat' is not in use. */ -# define stat stat_used_without_requesting_gnulib_module_stat -# endif - -# if !GNULIB_defined_struct_stat -struct stat -{ - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; -# if 0 - uid_t st_uid; -# else /* uid_t is not defined by default on native Windows. */ - short st_uid; -# endif -# if 0 - gid_t st_gid; -# else /* gid_t is not defined by default on native Windows. */ - short st_gid; -# endif - dev_t st_rdev; - off_t st_size; -# if 0 - blksize_t st_blksize; - blkcnt_t st_blocks; -# endif - -# if @WINDOWS_STAT_TIMESPEC@ - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; -# else - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -# endif -}; -# if @WINDOWS_STAT_TIMESPEC@ -# define st_atime st_atim.tv_sec -# define st_mtime st_mtim.tv_sec -# define st_ctime st_ctim.tv_sec - /* Indicator, for gnulib internal purposes. */ -# define _GL_WINDOWS_STAT_TIMESPEC 1 -# endif -# define GNULIB_defined_struct_stat 1 -# endif - -/* Other possible values of st_mode. */ -# if 0 -# define _S_IFBLK 0x6000 -# endif -# if 0 -# define _S_IFLNK 0xA000 -# endif -# if 0 -# define _S_IFSOCK 0xC000 -# endif - -#endif - -#ifndef S_IFIFO -# ifdef _S_IFIFO -# define S_IFIFO _S_IFIFO -# endif -#endif - -#ifndef S_IFMT -# define S_IFMT 0170000 -#endif - -#if STAT_MACROS_BROKEN -# undef S_ISBLK -# undef S_ISCHR -# undef S_ISDIR -# undef S_ISFIFO -# undef S_ISLNK -# undef S_ISNAM -# undef S_ISMPB -# undef S_ISMPC -# undef S_ISNWK -# undef S_ISREG -# undef S_ISSOCK -#endif - -#ifndef S_ISBLK -# ifdef S_IFBLK -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -# else -# define S_ISBLK(m) 0 -# endif -#endif - -#ifndef S_ISCHR -# ifdef S_IFCHR -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -# else -# define S_ISCHR(m) 0 -# endif -#endif - -#ifndef S_ISDIR -# ifdef S_IFDIR -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -# else -# define S_ISDIR(m) 0 -# endif -#endif - -#ifndef S_ISDOOR /* Solaris 2.5 and up */ -# define S_ISDOOR(m) 0 -#endif - -#ifndef S_ISFIFO -# ifdef S_IFIFO -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -# else -# define S_ISFIFO(m) 0 -# endif -#endif - -#ifndef S_ISLNK -# ifdef S_IFLNK -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -# else -# define S_ISLNK(m) 0 -# endif -#endif - -#ifndef S_ISMPB /* V7 */ -# ifdef S_IFMPB -# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) -# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) -# else -# define S_ISMPB(m) 0 -# define S_ISMPC(m) 0 -# endif -#endif - -#ifndef S_ISMPX /* AIX */ -# define S_ISMPX(m) 0 -#endif - -#ifndef S_ISNAM /* Xenix */ -# ifdef S_IFNAM -# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) -# else -# define S_ISNAM(m) 0 -# endif -#endif - -#ifndef S_ISNWK /* HP/UX */ -# ifdef S_IFNWK -# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) -# else -# define S_ISNWK(m) 0 -# endif -#endif - -#ifndef S_ISPORT /* Solaris 10 and up */ -# define S_ISPORT(m) 0 -#endif - -#ifndef S_ISREG -# ifdef S_IFREG -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -# else -# define S_ISREG(m) 0 -# endif -#endif - -#ifndef S_ISSOCK -# ifdef S_IFSOCK -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -# else -# define S_ISSOCK(m) 0 -# endif -#endif - - -#ifndef S_TYPEISMQ -# define S_TYPEISMQ(p) 0 -#endif - -#ifndef S_TYPEISTMO -# define S_TYPEISTMO(p) 0 -#endif - - -#ifndef S_TYPEISSEM -# ifdef S_INSEM -# define S_TYPEISSEM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSEM) -# else -# define S_TYPEISSEM(p) 0 -# endif -#endif - -#ifndef S_TYPEISSHM -# ifdef S_INSHD -# define S_TYPEISSHM(p) (S_ISNAM ((p)->st_mode) && (p)->st_rdev == S_INSHD) -# else -# define S_TYPEISSHM(p) 0 -# endif -#endif - -/* high performance ("contiguous data") */ -#ifndef S_ISCTG -# define S_ISCTG(p) 0 -#endif - -/* Cray DMF (data migration facility): off line, with data */ -#ifndef S_ISOFD -# define S_ISOFD(p) 0 -#endif - -/* Cray DMF (data migration facility): off line, with no data */ -#ifndef S_ISOFL -# define S_ISOFL(p) 0 -#endif - -/* 4.4BSD whiteout */ -#ifndef S_ISWHT -# define S_ISWHT(m) 0 -#endif - -/* If any of the following are undefined, - define them to their de facto standard values. */ -#if !S_ISUID -# define S_ISUID 04000 -#endif -#if !S_ISGID -# define S_ISGID 02000 -#endif - -/* S_ISVTX is a common extension to POSIX. */ -#ifndef S_ISVTX -# define S_ISVTX 01000 -#endif - -#if !S_IRUSR && S_IREAD -# define S_IRUSR S_IREAD -#endif -#if !S_IRUSR -# define S_IRUSR 00400 -#endif -#if !S_IRGRP -# define S_IRGRP (S_IRUSR >> 3) -#endif -#if !S_IROTH -# define S_IROTH (S_IRUSR >> 6) -#endif - -#if !S_IWUSR && S_IWRITE -# define S_IWUSR S_IWRITE -#endif -#if !S_IWUSR -# define S_IWUSR 00200 -#endif -#if !S_IWGRP -# define S_IWGRP (S_IWUSR >> 3) -#endif -#if !S_IWOTH -# define S_IWOTH (S_IWUSR >> 6) -#endif - -#if !S_IXUSR && S_IEXEC -# define S_IXUSR S_IEXEC -#endif -#if !S_IXUSR -# define S_IXUSR 00100 -#endif -#if !S_IXGRP -# define S_IXGRP (S_IXUSR >> 3) -#endif -#if !S_IXOTH -# define S_IXOTH (S_IXUSR >> 6) -#endif - -#if !S_IRWXU -# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#endif -#if !S_IRWXG -# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif -#if !S_IRWXO -# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -/* Although S_IXUGO and S_IRWXUGO are not specified by POSIX and are - not implemented in GNU/Linux, some Gnulib-using apps use the macros. */ -#if !S_IXUGO -# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) -#endif -#ifndef S_IRWXUGO -# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) -#endif - -/* Macros for futimens and utimensat. */ -#ifndef UTIME_NOW -# define UTIME_NOW (-1) -# define UTIME_OMIT (-2) -#endif - - -#if @GNULIB_CHMOD@ -# if @REPLACE_CHMOD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chmod -# define chmod rpl_chmod -# endif -_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chmod -# define chmod _chmod -# endif -/* Need to cast, because in mingw the last argument is 'int mode'. */ -_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); -# else -_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); -# endif -_GL_CXXALIASWARN (chmod); -#elif defined GNULIB_POSIXCHECK -# undef chmod -# if HAVE_RAW_DECL_CHMOD -_GL_WARN_ON_USE (chmod, "chmod has portability problems - " - "use gnulib module chmod for portability"); -# endif -#elif @GNULIB_MDA_CHMOD@ -/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::chmod always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chmod -# define chmod _chmod -# endif -/* Need to cast, because in mingw the last argument is 'int mode'. */ -_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); -# else -_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); -# endif -_GL_CXXALIASWARN (chmod); -#endif - - -#if @GNULIB_FCHMODAT@ -# if @REPLACE_FCHMODAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fchmodat -# define fchmodat rpl_fchmodat -# endif -_GL_FUNCDECL_RPL (fchmodat, int, - (int fd, char const *file, mode_t mode, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (fchmodat, int, - (int fd, char const *file, mode_t mode, int flag)); -# else -# if !@HAVE_FCHMODAT@ -_GL_FUNCDECL_SYS (fchmodat, int, - (int fd, char const *file, mode_t mode, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (fchmodat, int, - (int fd, char const *file, mode_t mode, int flag)); -# endif -_GL_CXXALIASWARN (fchmodat); -#elif defined GNULIB_POSIXCHECK -# undef fchmodat -# if HAVE_RAW_DECL_FCHMODAT -_GL_WARN_ON_USE (fchmodat, "fchmodat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -#if @GNULIB_FSTAT@ -# if @REPLACE_FSTAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fstat -# define fstat rpl_fstat -# endif -_GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); -# else -_GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (fstat); -# endif -#elif @GNULIB_OVERRIDES_STRUCT_STAT@ -# undef fstat -# define fstat fstat_used_without_requesting_gnulib_module_fstat -#elif @WINDOWS_64_BIT_ST_SIZE@ -/* Above, we define stat to _stati64. */ -# define fstat _fstati64 -#elif defined GNULIB_POSIXCHECK -# undef fstat -# if HAVE_RAW_DECL_FSTAT -_GL_WARN_ON_USE (fstat, "fstat has portability problems - " - "use gnulib module fstat for portability"); -# endif -#endif - - -#if @GNULIB_FSTATAT@ -# if @REPLACE_FSTATAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fstatat -# define fstatat rpl_fstatat -# endif -_GL_FUNCDECL_RPL (fstatat, int, - (int fd, char const *restrict name, struct stat *restrict st, - int flags) - _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_RPL (fstatat, int, - (int fd, char const *restrict name, struct stat *restrict st, - int flags)); -# else -# if !@HAVE_FSTATAT@ -_GL_FUNCDECL_SYS (fstatat, int, - (int fd, char const *restrict name, struct stat *restrict st, - int flags) - _GL_ARG_NONNULL ((2, 3))); -# endif -_GL_CXXALIAS_SYS (fstatat, int, - (int fd, char const *restrict name, struct stat *restrict st, - int flags)); -# endif -_GL_CXXALIASWARN (fstatat); -#elif @GNULIB_OVERRIDES_STRUCT_STAT@ -# undef fstatat -# define fstatat fstatat_used_without_requesting_gnulib_module_fstatat -#elif defined GNULIB_POSIXCHECK -# undef fstatat -# if HAVE_RAW_DECL_FSTATAT -_GL_WARN_ON_USE (fstatat, "fstatat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -#if @GNULIB_FUTIMENS@ -/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our futimens - implementation relies on futimesat, which on Solaris 10 makes an invocation - to futimens that is meant to invoke the libc's futimens(), not gnulib's - futimens(). */ -# if @REPLACE_FUTIMENS@ || (!@HAVE_FUTIMENS@ && defined __sun) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef futimens -# define futimens rpl_futimens -# endif -_GL_FUNCDECL_RPL (futimens, int, (int fd, struct timespec const times[2])); -_GL_CXXALIAS_RPL (futimens, int, (int fd, struct timespec const times[2])); -# else -# if !@HAVE_FUTIMENS@ -_GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec const times[2])); -# endif -_GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2])); -# endif -# if @HAVE_FUTIMENS@ -_GL_CXXALIASWARN (futimens); -# endif -#elif defined GNULIB_POSIXCHECK -# undef futimens -# if HAVE_RAW_DECL_FUTIMENS -_GL_WARN_ON_USE (futimens, "futimens is not portable - " - "use gnulib module futimens for portability"); -# endif -#endif - - -#if @GNULIB_GETUMASK@ -# if !@HAVE_GETUMASK@ -_GL_FUNCDECL_SYS (getumask, mode_t, (void)); -# endif -_GL_CXXALIAS_SYS (getumask, mode_t, (void)); -# if @HAVE_GETUMASK@ -_GL_CXXALIASWARN (getumask); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getumask -# if HAVE_RAW_DECL_GETUMASK -_GL_WARN_ON_USE (getumask, "getumask is not portable - " - "use gnulib module getumask for portability"); -# endif -#endif - - -#if @GNULIB_LCHMOD@ -/* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME - denotes a symbolic link. */ -# if !@HAVE_LCHMOD@ || defined __hpux -_GL_FUNCDECL_SYS (lchmod, int, (const char *filename, mode_t mode) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (lchmod, int, (const char *filename, mode_t mode)); -_GL_CXXALIASWARN (lchmod); -#elif defined GNULIB_POSIXCHECK -# undef lchmod -# if HAVE_RAW_DECL_LCHMOD -_GL_WARN_ON_USE (lchmod, "lchmod is unportable - " - "use gnulib module lchmod for portability"); -# endif -#endif - - -#if @GNULIB_MKDIR@ -# if @REPLACE_MKDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mkdir -# define mkdir rpl_mkdir -# endif -_GL_FUNCDECL_RPL (mkdir, int, (char const *name, mode_t mode) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); -# elif defined _WIN32 && !defined __CYGWIN__ -/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. - Additionally, it declares _mkdir (and depending on compile flags, an - alias mkdir), only in the nonstandard includes and , - which are included above. */ -# if !GNULIB_defined_rpl_mkdir -static int -rpl_mkdir (char const *name, mode_t mode) -{ - return _mkdir (name); -} -# define GNULIB_defined_rpl_mkdir 1 -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mkdir -# define mkdir rpl_mkdir -# endif -_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); -# else -_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); -# endif -_GL_CXXALIASWARN (mkdir); -#elif defined GNULIB_POSIXCHECK -# undef mkdir -# if HAVE_RAW_DECL_MKDIR -_GL_WARN_ON_USE (mkdir, "mkdir does not always support two parameters - " - "use gnulib module mkdir for portability"); -# endif -#elif @GNULIB_MDA_MKDIR@ -/* On native Windows, map 'mkdir' to '_mkdir', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::mkdir always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !GNULIB_defined_rpl_mkdir -static int -rpl_mkdir (char const *name, mode_t mode) -{ - return _mkdir (name); -} -# define GNULIB_defined_rpl_mkdir 1 -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mkdir -# define mkdir rpl_mkdir -# endif -_GL_CXXALIAS_RPL (mkdir, int, (char const *name, mode_t mode)); -# else -_GL_CXXALIAS_SYS (mkdir, int, (char const *name, mode_t mode)); -# endif -_GL_CXXALIASWARN (mkdir); -#endif - - -#if @GNULIB_MKDIRAT@ -# if !@HAVE_MKDIRAT@ -_GL_FUNCDECL_SYS (mkdirat, int, (int fd, char const *file, mode_t mode) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (mkdirat, int, (int fd, char const *file, mode_t mode)); -_GL_CXXALIASWARN (mkdirat); -#elif defined GNULIB_POSIXCHECK -# undef mkdirat -# if HAVE_RAW_DECL_MKDIRAT -_GL_WARN_ON_USE (mkdirat, "mkdirat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -#if @GNULIB_MKFIFO@ -# if @REPLACE_MKFIFO@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mkfifo -# define mkfifo rpl_mkfifo -# endif -_GL_FUNCDECL_RPL (mkfifo, int, (char const *file, mode_t mode) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mkfifo, int, (char const *file, mode_t mode)); -# else -# if !@HAVE_MKFIFO@ -_GL_FUNCDECL_SYS (mkfifo, int, (char const *file, mode_t mode) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkfifo, int, (char const *file, mode_t mode)); -# endif -_GL_CXXALIASWARN (mkfifo); -#elif defined GNULIB_POSIXCHECK -# undef mkfifo -# if HAVE_RAW_DECL_MKFIFO -_GL_WARN_ON_USE (mkfifo, "mkfifo is not portable - " - "use gnulib module mkfifo for portability"); -# endif -#endif - - -#if @GNULIB_MKFIFOAT@ -# if @REPLACE_MKFIFOAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mkfifoat -# define mkfifoat rpl_mkfifoat -# endif -_GL_FUNCDECL_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (mkfifoat, int, (int fd, char const *file, mode_t mode)); -# else -# if !@HAVE_MKFIFOAT@ -_GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode)); -# endif -_GL_CXXALIASWARN (mkfifoat); -#elif defined GNULIB_POSIXCHECK -# undef mkfifoat -# if HAVE_RAW_DECL_MKFIFOAT -_GL_WARN_ON_USE (mkfifoat, "mkfifoat is not portable - " - "use gnulib module mkfifoat for portability"); -# endif -#endif - - -#if @GNULIB_MKNOD@ -# if @REPLACE_MKNOD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mknod -# define mknod rpl_mknod -# endif -_GL_FUNCDECL_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mknod, int, (char const *file, mode_t mode, dev_t dev)); -# else -# if !@HAVE_MKNOD@ -_GL_FUNCDECL_SYS (mknod, int, (char const *file, mode_t mode, dev_t dev) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on OSF/1 5.1, the third parameter is '...'. */ -_GL_CXXALIAS_SYS_CAST (mknod, int, (char const *file, mode_t mode, dev_t dev)); -# endif -_GL_CXXALIASWARN (mknod); -#elif defined GNULIB_POSIXCHECK -# undef mknod -# if HAVE_RAW_DECL_MKNOD -_GL_WARN_ON_USE (mknod, "mknod is not portable - " - "use gnulib module mknod for portability"); -# endif -#endif - - -#if @GNULIB_MKNODAT@ -# if @REPLACE_MKNODAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mknodat -# define mknodat rpl_mknodat -# endif -_GL_FUNCDECL_RPL (mknodat, int, - (int fd, char const *file, mode_t mode, dev_t dev) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (mknodat, int, - (int fd, char const *file, mode_t mode, dev_t dev)); -# else -# if !@HAVE_MKNODAT@ -_GL_FUNCDECL_SYS (mknodat, int, - (int fd, char const *file, mode_t mode, dev_t dev) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (mknodat, int, - (int fd, char const *file, mode_t mode, dev_t dev)); -# endif -_GL_CXXALIASWARN (mknodat); -#elif defined GNULIB_POSIXCHECK -# undef mknodat -# if HAVE_RAW_DECL_MKNODAT -_GL_WARN_ON_USE (mknodat, "mknodat is not portable - " - "use gnulib module mkfifoat for portability"); -# endif -#endif - - -#if @GNULIB_STAT@ -# if @REPLACE_STAT@ -# if !@GNULIB_OVERRIDES_STRUCT_STAT@ - /* We can't use the object-like #define stat rpl_stat, because of - struct stat. This means that rpl_stat will not be used if the user - does (stat)(a,b). Oh well. */ -# if defined _AIX && defined stat && defined _LARGE_FILES - /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, - so we have to replace stat64() instead of stat(). */ -# undef stat64 -# define stat64(name, st) rpl_stat (name, st) -# elif @WINDOWS_64_BIT_ST_SIZE@ - /* Above, we define stat to _stati64. */ -# if defined __MINGW32__ && defined _stati64 -# ifndef _USE_32BIT_TIME_T - /* The system headers define _stati64 to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) -# endif -# elif defined _MSC_VER && defined _stati64 -# ifdef _USE_32BIT_TIME_T - /* The system headers define _stati64 to _stat32i64. */ -# undef _stat32i64 -# define _stat32i64(name, st) rpl_stat (name, st) -# else - /* The system headers define _stati64 to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) -# endif -# else -# undef _stati64 -# define _stati64(name, st) rpl_stat (name, st) -# endif -# elif defined __MINGW32__ && defined stat -# ifdef _USE_32BIT_TIME_T - /* The system headers define stat to _stat32i64. */ -# undef _stat32i64 -# define _stat32i64(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) -# endif -# elif defined _MSC_VER && defined stat -# ifdef _USE_32BIT_TIME_T - /* The system headers define stat to _stat32. */ -# undef _stat32 -# define _stat32(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64i32. */ -# undef _stat64i32 -# define _stat64i32(name, st) rpl_stat (name, st) -# endif -# else /* !(_AIX || __MINGW32__ || _MSC_VER) */ -# undef stat -# define stat(name, st) rpl_stat (name, st) -# endif /* !_LARGE_FILES */ -# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */ -_GL_EXTERN_C int stat (const char *restrict name, struct stat *restrict buf) - _GL_ARG_NONNULL ((1, 2)); -# endif -#elif @GNULIB_OVERRIDES_STRUCT_STAT@ -/* see above: - #define stat stat_used_without_requesting_gnulib_module_stat - */ -#elif defined GNULIB_POSIXCHECK -# undef stat -# if HAVE_RAW_DECL_STAT -_GL_WARN_ON_USE (stat, "stat is unportable - " - "use gnulib module stat for portability"); -# endif -#endif - - -#if @GNULIB_LSTAT@ -# if ! @HAVE_LSTAT@ -/* mingw does not support symlinks, therefore it does not have lstat. But - without links, stat does just fine. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define lstat stat -# endif -_GL_CXXALIAS_RPL_1 (lstat, stat, int, - (const char *restrict name, struct stat *restrict buf)); -# elif @REPLACE_LSTAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef lstat -# define lstat rpl_lstat -# endif -_GL_FUNCDECL_RPL (lstat, int, - (const char *restrict name, struct stat *restrict buf) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (lstat, int, - (const char *restrict name, struct stat *restrict buf)); -# else -_GL_CXXALIAS_SYS (lstat, int, - (const char *restrict name, struct stat *restrict buf)); -# endif -# if @HAVE_LSTAT@ -_GL_CXXALIASWARN (lstat); -# endif -#elif @GNULIB_OVERRIDES_STRUCT_STAT@ -# undef lstat -# define lstat lstat_used_without_requesting_gnulib_module_lstat -#elif defined GNULIB_POSIXCHECK -# undef lstat -# if HAVE_RAW_DECL_LSTAT -_GL_WARN_ON_USE (lstat, "lstat is unportable - " - "use gnulib module lstat for portability"); -# endif -#endif - - -#if @GNULIB_MDA_UMASK@ -/* On native Windows, map 'umask' to '_umask', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::umask always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef umask -# define umask _umask -# endif -/* Need to cast, because in mingw the last argument is 'int mode'. */ -_GL_CXXALIAS_MDA_CAST (umask, mode_t, (mode_t mask)); -# else -_GL_CXXALIAS_SYS (umask, mode_t, (mode_t mask)); -# endif -_GL_CXXALIASWARN (umask); -#endif - - -#if @GNULIB_UTIMENSAT@ -/* Use the rpl_ prefix also on Solaris <= 9, because on Solaris 9 our utimensat - implementation relies on futimesat, which on Solaris 10 makes an invocation - to utimensat that is meant to invoke the libc's utimensat(), not gnulib's - utimensat(). */ -# if @REPLACE_UTIMENSAT@ || (!@HAVE_UTIMENSAT@ && defined __sun) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef utimensat -# define utimensat rpl_utimensat -# endif -_GL_FUNCDECL_RPL (utimensat, int, (int fd, char const *name, - struct timespec const times[2], int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (utimensat, int, (int fd, char const *name, - struct timespec const times[2], int flag)); -# else -# if !@HAVE_UTIMENSAT@ -_GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name, - struct timespec const times[2], int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name, - struct timespec const times[2], int flag)); -# endif -# if @HAVE_UTIMENSAT@ -_GL_CXXALIASWARN (utimensat); -# endif -#elif defined GNULIB_POSIXCHECK -# undef utimensat -# if HAVE_RAW_DECL_UTIMENSAT -_GL_WARN_ON_USE (utimensat, "utimensat is not portable - " - "use gnulib module utimensat for portability"); -# endif -#endif - - -#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ -#endif /* _@GUARD_PREFIX@_SYS_STAT_H */ -#endif diff --git a/xcompile/lib/sys_time.in.h b/xcompile/lib/sys_time.in.h deleted file mode 100644 index e833d551677..00000000000 --- a/xcompile/lib/sys_time.in.h +++ /dev/null @@ -1,224 +0,0 @@ -/* Provide a more complete sys/time.h. - - Copyright (C) 2007-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef _@GUARD_PREFIX@_SYS_TIME_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* On Cygwin and on many BSDish systems, includes itself - recursively via . - Simply delegate to the system's header in this case; it is a no-op. - Without this extra ifdef, the C++ gettimeofday declaration below - would be a forward declaration in gnulib's nested . */ -#if defined _CYGWIN_SYS_TIME_H || defined _SYS_TIME_H || defined _SYS_TIME_H_ -# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ -#else - -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_SYS_TIME_H@ -# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@ -#endif - -#ifndef _@GUARD_PREFIX@_SYS_TIME_H -#define _@GUARD_PREFIX@_SYS_TIME_H - -#if ! @HAVE_SYS_TIME_H@ -# include -#endif - -/* On native Windows with MSVC, get the 'struct timeval' type. - Also, on native Windows with a 64-bit time_t, where we are overriding the - 'struct timeval' type, get all declarations of system functions whose - signature contains 'struct timeval'. */ -#if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H -# define _GL_INCLUDING_WINSOCK2_H -# include -# undef _GL_INCLUDING_WINSOCK2_H -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@ - -# if @REPLACE_STRUCT_TIMEVAL@ -# define timeval rpl_timeval -# endif - -# if !GNULIB_defined_struct_timeval -struct timeval -{ - time_t tv_sec; - long int tv_usec; -}; -# define GNULIB_defined_struct_timeval 1 -# endif - -#endif - -#ifdef __cplusplus -} -#endif - -#if @GNULIB_GETTIMEOFDAY@ -# if @REPLACE_GETTIMEOFDAY@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gettimeofday -# define gettimeofday rpl_gettimeofday -# endif -_GL_FUNCDECL_RPL (gettimeofday, int, - (struct timeval *restrict, void *restrict) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (gettimeofday, int, - (struct timeval *restrict, void *restrict)); -# else -# if !@HAVE_GETTIMEOFDAY@ -_GL_FUNCDECL_SYS (gettimeofday, int, - (struct timeval *restrict, void *restrict) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on glibc systems, by default, the second argument is - struct timezone *. */ -_GL_CXXALIAS_SYS_CAST (gettimeofday, int, - (struct timeval *restrict, void *restrict)); -# endif -_GL_CXXALIASWARN (gettimeofday); -# if defined __cplusplus && defined GNULIB_NAMESPACE -namespace GNULIB_NAMESPACE { - typedef ::timeval -# undef timeval - timeval; -# if @REPLACE_STRUCT_TIMEVAL@ -# define timeval rpl_timeval - typedef ::timeval timeval; -# endif -} -# endif -#elif defined GNULIB_POSIXCHECK -# undef gettimeofday -# if HAVE_RAW_DECL_GETTIMEOFDAY -_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - " - "use gnulib module gettimeofday for portability"); -# endif -#endif - -/* Hide some function declarations from . */ - -#if defined _MSC_VER && @HAVE_WINSOCK2_H@ -# if !defined _@GUARD_PREFIX@_UNISTD_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef close -# define close close_used_without_including_unistd_h -# elif !defined __clang__ - _GL_WARN_ON_USE (close, - "close() used without including "); -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gethostname -# define gethostname gethostname_used_without_including_unistd_h -# else - _GL_WARN_ON_USE (gethostname, - "gethostname() used without including "); -# endif -# endif -# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef socket -# define socket socket_used_without_including_sys_socket_h -# undef connect -# define connect connect_used_without_including_sys_socket_h -# undef accept -# define accept accept_used_without_including_sys_socket_h -# undef bind -# define bind bind_used_without_including_sys_socket_h -# undef getpeername -# define getpeername getpeername_used_without_including_sys_socket_h -# undef getsockname -# define getsockname getsockname_used_without_including_sys_socket_h -# undef getsockopt -# define getsockopt getsockopt_used_without_including_sys_socket_h -# undef listen -# define listen listen_used_without_including_sys_socket_h -# undef recv -# define recv recv_used_without_including_sys_socket_h -# undef send -# define send send_used_without_including_sys_socket_h -# undef recvfrom -# define recvfrom recvfrom_used_without_including_sys_socket_h -# undef sendto -# define sendto sendto_used_without_including_sys_socket_h -# undef setsockopt -# define setsockopt setsockopt_used_without_including_sys_socket_h -# undef shutdown -# define shutdown shutdown_used_without_including_sys_socket_h -# else - _GL_WARN_ON_USE (socket, - "socket() used without including "); - _GL_WARN_ON_USE (connect, - "connect() used without including "); - _GL_WARN_ON_USE (accept, - "accept() used without including "); - _GL_WARN_ON_USE (bind, - "bind() used without including "); - _GL_WARN_ON_USE (getpeername, - "getpeername() used without including "); - _GL_WARN_ON_USE (getsockname, - "getsockname() used without including "); - _GL_WARN_ON_USE (getsockopt, - "getsockopt() used without including "); - _GL_WARN_ON_USE (listen, - "listen() used without including "); - _GL_WARN_ON_USE (recv, - "recv() used without including "); - _GL_WARN_ON_USE (send, - "send() used without including "); - _GL_WARN_ON_USE (recvfrom, - "recvfrom() used without including "); - _GL_WARN_ON_USE (sendto, - "sendto() used without including "); - _GL_WARN_ON_USE (setsockopt, - "setsockopt() used without including "); - _GL_WARN_ON_USE (shutdown, - "shutdown() used without including "); -# endif -# endif -# if !defined _@GUARD_PREFIX@_SYS_SELECT_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef select -# define select select_used_without_including_sys_select_h -# else - _GL_WARN_ON_USE (select, - "select() used without including "); -# endif -# endif -#endif - -#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ -#endif /* _CYGWIN_SYS_TIME_H */ -#endif /* _@GUARD_PREFIX@_SYS_TIME_H */ diff --git a/xcompile/lib/sys_types.in.h b/xcompile/lib/sys_types.in.h deleted file mode 100644 index 082a6c674de..00000000000 --- a/xcompile/lib/sys_types.in.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Provide a more complete sys/types.h. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if defined _WIN32 && !defined __CYGWIN__ \ - && (defined __need_off_t || defined __need___off64_t \ - || defined __need_ssize_t || defined __need_time_t) - -/* Special invocation convention inside mingw header files. */ - -#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _@GUARD_PREFIX@_SYS_TYPES_H - -/* The include_next requires a split double-inclusion guard. */ -# define _GL_INCLUDING_SYS_TYPES_H -#@INCLUDE_NEXT@ @NEXT_SYS_TYPES_H@ -# undef _GL_INCLUDING_SYS_TYPES_H - -#ifndef _@GUARD_PREFIX@_SYS_TYPES_H -#define _@GUARD_PREFIX@_SYS_TYPES_H - -/* Override off_t if Large File Support is requested on native Windows. */ -#if @WINDOWS_64_BIT_OFF_T@ -/* Same as int64_t in . */ -# if defined _MSC_VER -# define off_t __int64 -# else -# define off_t long long int -# endif -/* Indicator, for gnulib internal purposes. */ -# define _GL_WINDOWS_64_BIT_OFF_T 1 -#endif - -/* Override dev_t and ino_t if distinguishable inodes support is requested - on native Windows. */ -#if @WINDOWS_STAT_INODES@ - -# if @WINDOWS_STAT_INODES@ == 2 -/* Experimental, not useful in Windows 10. */ - -/* Define dev_t to a 64-bit type. */ -# if !defined GNULIB_defined_dev_t -typedef unsigned long long int rpl_dev_t; -# undef dev_t -# define dev_t rpl_dev_t -# define GNULIB_defined_dev_t 1 -# endif - -/* Define ino_t to a 128-bit type. */ -# if !defined GNULIB_defined_ino_t -/* MSVC does not have a 128-bit integer type. - GCC has a 128-bit integer type __int128, but only on 64-bit targets. */ -typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t; -# undef ino_t -# define ino_t rpl_ino_t -# define GNULIB_defined_ino_t 1 -# endif - -# else /* @WINDOWS_STAT_INODES@ == 1 */ - -/* Define ino_t to a 64-bit type. */ -# if !defined GNULIB_defined_ino_t -typedef unsigned long long int rpl_ino_t; -# undef ino_t -# define ino_t rpl_ino_t -# define GNULIB_defined_ino_t 1 -# endif - -# endif - -/* Indicator, for gnulib internal purposes. */ -# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@ - -#endif - -/* MSVC 9 defines size_t in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (defined _WIN32 && ! defined __CYGWIN__) && ! defined __GLIBC__ -# include -#endif - -#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ -#endif /* _@GUARD_PREFIX@_SYS_TYPES_H */ -#endif /* __need_XXX */ diff --git a/xcompile/lib/tempname.c b/xcompile/lib/tempname.c deleted file mode 100644 index bf362db6e17..00000000000 --- a/xcompile/lib/tempname.c +++ /dev/null @@ -1,286 +0,0 @@ -/* Copyright (C) 1991-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#if !_LIBC -# include -# include "tempname.h" -#endif - -#include - -#include -#ifndef TMP_MAX -# define TMP_MAX 238328 -#endif -#ifndef __GT_FILE -# define __GT_FILE 0 -# define __GT_DIR 1 -# define __GT_NOCREATE 2 -#endif -#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ - || GT_NOCREATE != __GT_NOCREATE) -# error report this to bug-gnulib@gnu.org -#endif - -#include -#include - -#include -#include -#include -#include -#include - -#if _LIBC -# define struct_stat64 struct __stat64_t64 -#else -# define struct_stat64 struct stat -# define __gen_tempname gen_tempname -# define __mkdir mkdir -# define __open open -# define __lstat64_time64(file, buf) lstat (file, buf) -# define __getrandom getrandom -# define __clock_gettime64 clock_gettime -# define __timespec64 timespec -#endif - -/* Use getrandom if it works, falling back on a 64-bit linear - congruential generator that starts with Var's value - mixed in with a clock's low-order bits if available. */ -typedef uint_fast64_t random_value; -#define RANDOM_VALUE_MAX UINT_FAST64_MAX -#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */ -#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) - -/* Return the result of mixing the entropy from R and S. - Assume that R and S are not particularly random, - and that the result should look randomish to an untrained eye. */ - -static random_value -mix_random_values (random_value r, random_value s) -{ - /* As this code is used only when high-quality randomness is neither - available nor necessary, there is no need for fancier polynomials - such as those in the Linux kernel's 'random' driver. */ - return (2862933555777941757 * r + 3037000493) ^ s; -} - -/* Set *R to a random value. - Return true if *R is set to high-quality value taken from getrandom. - Otherwise return false, falling back to a low-quality *R that might - depend on S. - - This function returns false only when getrandom fails. - On GNU systems this should happen only early in the boot process, - when the fallback should be good enough for programs using tempname - because any attacker likely has root privileges already. */ - -static bool -random_bits (random_value *r, random_value s) -{ - /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ - if (__getrandom (r, sizeof *r, GRND_NONBLOCK) == sizeof *r) - return true; - - /* If getrandom did not work, use ersatz entropy based on low-order - clock bits. On GNU systems getrandom should fail only - early in booting, when ersatz should be good enough. - Do not use ASLR-based entropy, as that would leak ASLR info into - the resulting file name which is typically public. - - Of course we are in a state of sin here. */ - - random_value v = s; - -#if _LIBC || (defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME) - struct __timespec64 tv; - __clock_gettime64 (CLOCK_REALTIME, &tv); - v = mix_random_values (v, tv.tv_sec); - v = mix_random_values (v, tv.tv_nsec); -#endif - - *r = mix_random_values (v, clock ()); - return false; -} - -#if _LIBC -static int try_tempname_len (char *, int, void *, int (*) (char *, void *), - size_t); -#endif - -static int -try_file (char *tmpl, void *flags) -{ - int *openflags = flags; - return __open (tmpl, - (*openflags & ~O_ACCMODE) - | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); -} - -static int -try_dir (char *tmpl, _GL_UNUSED void *flags) -{ - return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); -} - -static int -try_nocreate (char *tmpl, _GL_UNUSED void *flags) -{ - struct_stat64 st; - - if (__lstat64_time64 (tmpl, &st) == 0 || errno == EOVERFLOW) - __set_errno (EEXIST); - return errno == ENOENT ? 0 : -1; -} - -/* These are the characters used in temporary file names. */ -static const char letters[] = -"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s, - possibly with a suffix). - The name constructed does not exist at the time of the call to - this function. TMPL is overwritten with the result. - - KIND may be one of: - __GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - __GT_FILE: create the file using open(O_CREAT|O_EXCL) - and return a read-write fd. The file is mode 0600. - __GT_DIR: create a directory, which will be mode 0700. - - */ -#ifdef _LIBC -static -#endif -int -gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, - size_t x_suffix_len) -{ - static int (*const tryfunc[]) (char *, void *) = - { - [__GT_FILE] = try_file, - [__GT_DIR] = try_dir, - [__GT_NOCREATE] = try_nocreate - }; - return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind], - x_suffix_len); -} - -#ifdef _LIBC -static -#endif -int -try_tempname_len (char *tmpl, int suffixlen, void *args, - int (*tryfunc) (char *, void *), size_t x_suffix_len) -{ - size_t len; - char *XXXXXX; - unsigned int count; - int fd = -1; - int save_errno = errno; - - /* A lower bound on the number of temporary files to attempt to - generate. The maximum total number of temporary file names that - can exist for a given template is 62**6. It should never be - necessary to try all of these combinations. Instead if a reasonable - number of names is tried (we define reasonable as 62**3) fail to - give the system administrator the chance to remove the problems. - This value requires that X_SUFFIX_LEN be at least 3. */ -#define ATTEMPTS_MIN (62 * 62 * 62) - - /* The number of times to attempt to generate a temporary file. To - conform to POSIX, this must be no smaller than TMP_MAX. */ -#if ATTEMPTS_MIN < TMP_MAX - unsigned int attempts = TMP_MAX; -#else - unsigned int attempts = ATTEMPTS_MIN; -#endif - - /* A random variable. */ - random_value v = 0; - - /* A value derived from the random variable, and how many random - base-62 digits can currently be extracted from VDIGBUF. */ - random_value vdigbuf; - int vdigits = 0; - - /* Least biased value for V. If V is less than this, V can generate - BASE_62_DIGITS unbiased digits. Otherwise the digits are biased. */ - random_value const biased_min - = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; - - len = strlen (tmpl); - if (len < x_suffix_len + suffixlen - || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len) - { - __set_errno (EINVAL); - return -1; - } - - /* This is where the Xs start. */ - XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; - - for (count = 0; count < attempts; ++count) - { - for (size_t i = 0; i < x_suffix_len; i++) - { - if (vdigits == 0) - { - /* Worry about bias only if the bits are high quality. */ - while (random_bits (&v, v) && biased_min <= v) - continue; - - vdigbuf = v; - vdigits = BASE_62_DIGITS; - } - - XXXXXX[i] = letters[vdigbuf % 62]; - vdigbuf /= 62; - vdigits--; - } - - fd = tryfunc (tmpl, args); - if (fd >= 0) - { - __set_errno (save_errno); - return fd; - } - else if (errno != EEXIST) - return -1; - } - - /* We got out of the loop because we ran out of combinations to try. */ - __set_errno (EEXIST); - return -1; -} - -int -__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) -{ - return gen_tempname_len (tmpl, suffixlen, flags, kind, 6); -} - -#if !_LIBC -int -try_tempname (char *tmpl, int suffixlen, void *args, - int (*tryfunc) (char *, void *)) -{ - return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6); -} -#endif diff --git a/xcompile/lib/tempname.h b/xcompile/lib/tempname.h deleted file mode 100644 index 36a51381548..00000000000 --- a/xcompile/lib/tempname.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Create a temporary file or directory. - - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* header written by Eric Blake */ - -#ifndef GL_TEMPNAME_H -# define GL_TEMPNAME_H - -# include - -# ifdef __GT_FILE -# define GT_FILE __GT_FILE -# define GT_DIR __GT_DIR -# define GT_NOCREATE __GT_NOCREATE -# else -# define GT_FILE 0 -# define GT_DIR 1 -# define GT_NOCREATE 2 -# endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). - The name constructed does not exist at the time of the call to - gen_tempname. TMPL is overwritten with the result. - - KIND may be one of: - GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - GT_FILE: create a large file using open(O_CREAT|O_EXCL) - and return a read-write fd. The file is mode 0600. - GT_DIR: create a directory, which will be mode 0700. - - */ -extern int gen_tempname (char *tmpl, int suffixlen, int flags, int kind); -/* Similar, except X_SUFFIX_LEN gives the number of Xs. */ -extern int gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, - size_t x_suffix_len); - -/* Similar to gen_tempname, but TRYFUNC is called for each temporary - name to try. If TRYFUNC returns a non-negative number, TRY_GEN_TEMPNAME - returns with this value. Otherwise, if errno is set to EEXIST, another - name is tried, or else TRY_GEN_TEMPNAME returns -1. */ -extern int try_tempname (char *tmpl, int suffixlen, void *args, - int (*tryfunc) (char *, void *)); -/* Similar, except X_SUFFIX_LEN gives the number of Xs. */ -extern int try_tempname_len (char *tmpl, int suffixlen, void *args, - int (*tryfunc) (char *, void *), - size_t x_suffix_len); - -#ifdef __cplusplus -} -#endif - -#endif /* GL_TEMPNAME_H */ diff --git a/xcompile/lib/time-internal.h b/xcompile/lib/time-internal.h deleted file mode 100644 index 51423c94ca9..00000000000 --- a/xcompile/lib/time-internal.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Time internal interface - - Copyright 2015-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -/* A time zone rule. */ -struct tm_zone -{ - /* More abbreviations, should they be needed. Their TZ_IS_SET - members are zero. */ - struct tm_zone *next; - -#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE - /* Copies of recent strings taken from tzname[0] and tzname[1]. - The copies are in ABBRS, so that they survive tzset. Null if unknown. */ - char *tzname_copy[2]; -#endif - - /* If nonzero, the rule represents the TZ environment variable set - to the first "abbreviation" (this may be the empty string). - Otherwise, it represents an unset TZ. */ - char tz_is_set; - - /* A sequence of null-terminated strings packed next to each other. - The strings are followed by an extra null byte. If TZ_IS_SET, - there must be at least one string and the first string (which is - actually a TZ environment value) may be empty. Otherwise all - strings must be nonempty. - - Abbreviations are stored here because otherwise the values of - tm_zone and/or tzname would be dead after changing TZ and calling - tzset. Abbreviations never move once allocated, and are live - until tzfree is called. */ - char abbrs[FLEXIBLE_ARRAY_MEMBER]; -}; diff --git a/xcompile/lib/time.in.h b/xcompile/lib/time.in.h deleted file mode 100644 index 50c9b30b6b3..00000000000 --- a/xcompile/lib/time.in.h +++ /dev/null @@ -1,457 +0,0 @@ -/* A more-standard . - - Copyright (C) 2007-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -/* Don't get in the way of glibc when it includes time.h merely to - declare a few standard symbols, rather than to declare all the - symbols. (However, skip this for MinGW as it treats __need_time_t - incompatibly.) Also, Solaris 8 eventually includes itself - recursively; if that is happening, just include the system - without adding our own declarations. */ -#if (((defined __need_time_t || defined __need_clock_t \ - || defined __need_timespec) \ - && !defined __MINGW32__) \ - || defined _@GUARD_PREFIX@_TIME_H) - -# @INCLUDE_NEXT@ @NEXT_TIME_H@ - -#else - -# define _@GUARD_PREFIX@_TIME_H - -/* mingw's provides the functions asctime_r, ctime_r, gmtime_r, - localtime_r only if or has been included before. */ -# if defined __MINGW32__ -# include -# endif - -# @INCLUDE_NEXT@ @NEXT_TIME_H@ - -/* NetBSD 5.0 mis-defines NULL. */ -# include - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Some systems don't define struct timespec (e.g., AIX 4.1). - Or they define it with the wrong member names or define it in - (e.g., FreeBSD circa 1997). Stock Mingw prior to 3.0 does not define it, - but the pthreads-win32 library defines it in . */ -# if ! @TIME_H_DEFINES_STRUCT_TIMESPEC@ -# if @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ -# include -# elif @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ -# include -# elif @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ -# include -# else - -# ifdef __cplusplus -extern "C" { -# endif - -# if !GNULIB_defined_struct_timespec -# undef timespec -# define timespec rpl_timespec -struct timespec -{ - time_t tv_sec; - long int tv_nsec; -}; -# define GNULIB_defined_struct_timespec 1 -# endif - -# ifdef __cplusplus -} -# endif - -# endif -# endif - -# if !GNULIB_defined_struct_time_t_must_be_integral -/* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html - requires time_t to be an integer type, even though C99 permits floating - point. We don't know of any implementation that uses floating - point, and it is much easier to write code that doesn't have to - worry about that corner case, so we force the issue. */ -struct __time_t_must_be_integral { - unsigned int __floating_time_t_unsupported : (time_t) 1; -}; -# define GNULIB_defined_struct_time_t_must_be_integral 1 -# endif - -/* Define TIME_UTC, a positive integer constant used for timespec_get(). */ -# if ! @TIME_H_DEFINES_TIME_UTC@ -# if !GNULIB_defined_TIME_UTC -# define TIME_UTC 1 -# define GNULIB_defined_TIME_UTC 1 -# endif -# endif - -/* Set *TS to the current time, and return BASE. - Upon failure, return 0. */ -# if @GNULIB_TIMESPEC_GET@ -# if ! @HAVE_TIMESPEC_GET@ -_GL_FUNCDECL_SYS (timespec_get, int, (struct timespec *ts, int base) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (timespec_get, int, (struct timespec *ts, int base)); -_GL_CXXALIASWARN (timespec_get); -# endif - -/* Set *TS to the current time resolution, and return BASE. - Upon failure, return 0. */ -# if @GNULIB_TIMESPEC_GETRES@ -# if ! @HAVE_TIMESPEC_GETRES@ -_GL_FUNCDECL_SYS (timespec_getres, int, (struct timespec *ts, int base) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (timespec_getres, int, (struct timespec *ts, int base)); -_GL_CXXALIASWARN (timespec_getres); -# endif - -/* Sleep for at least RQTP seconds unless interrupted, If interrupted, - return -1 and store the remaining time into RMTP. See - . */ -# if @GNULIB_NANOSLEEP@ -# if @REPLACE_NANOSLEEP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define nanosleep rpl_nanosleep -# endif -_GL_FUNCDECL_RPL (nanosleep, int, - (struct timespec const *__rqtp, struct timespec *__rmtp) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (nanosleep, int, - (struct timespec const *__rqtp, struct timespec *__rmtp)); -# else -# if ! @HAVE_NANOSLEEP@ -_GL_FUNCDECL_SYS (nanosleep, int, - (struct timespec const *__rqtp, struct timespec *__rmtp) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (nanosleep, int, - (struct timespec const *__rqtp, struct timespec *__rmtp)); -# endif -_GL_CXXALIASWARN (nanosleep); -# endif - -/* Initialize time conversion information. */ -# if @GNULIB_TZSET@ -# if @REPLACE_TZSET@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef tzset -# define tzset rpl_tzset -# endif -_GL_FUNCDECL_RPL (tzset, void, (void)); -_GL_CXXALIAS_RPL (tzset, void, (void)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef tzset -# define tzset _tzset -# endif -_GL_CXXALIAS_MDA (tzset, void, (void)); -# else -_GL_CXXALIAS_SYS (tzset, void, (void)); -# endif -_GL_CXXALIASWARN (tzset); -# elif @GNULIB_MDA_TZSET@ -/* On native Windows, map 'tzset' to '_tzset', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::tzset always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef tzset -# define tzset _tzset -# endif -_GL_CXXALIAS_MDA (tzset, void, (void)); -# else -_GL_CXXALIAS_SYS (tzset, void, (void)); -# endif -_GL_CXXALIASWARN (tzset); -# endif - -/* Return the 'time_t' representation of TP and normalize TP. */ -# if @GNULIB_MKTIME@ -# if @REPLACE_MKTIME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mktime rpl_mktime -# endif -_GL_FUNCDECL_RPL (mktime, time_t, (struct tm *__tp) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp)); -# else -_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (mktime); -# endif -# endif - -/* Convert TIMER to RESULT, assuming local time and UTC respectively. See - and - . */ -# if @GNULIB_TIME_R@ -# if @REPLACE_LOCALTIME_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef localtime_r -# define localtime_r rpl_localtime_r -# endif -_GL_FUNCDECL_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (localtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result)); -# else -# if ! @HAVE_DECL_LOCALTIME_R@ -_GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (localtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result)); -# endif -# if @HAVE_DECL_LOCALTIME_R@ -_GL_CXXALIASWARN (localtime_r); -# endif -# if @REPLACE_LOCALTIME_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gmtime_r -# define gmtime_r rpl_gmtime_r -# endif -_GL_FUNCDECL_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (gmtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result)); -# else -# if ! @HAVE_DECL_LOCALTIME_R@ -_GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer, - struct tm *restrict __result)); -# endif -# if @HAVE_DECL_LOCALTIME_R@ -_GL_CXXALIASWARN (gmtime_r); -# endif -# endif - -/* Convert TIMER to RESULT, assuming local time and UTC respectively. See - and - . */ -# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@ -# if @REPLACE_LOCALTIME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef localtime -# define localtime rpl_localtime -# endif -_GL_FUNCDECL_RPL (localtime, struct tm *, (time_t const *__timer) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer)); -# else -_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (localtime); -# endif -# endif - -# if 0 || @REPLACE_GMTIME@ -# if @REPLACE_GMTIME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gmtime -# define gmtime rpl_gmtime -# endif -_GL_FUNCDECL_RPL (gmtime, struct tm *, (time_t const *__timer) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (gmtime, struct tm *, (time_t const *__timer)); -# else -_GL_CXXALIAS_SYS (gmtime, struct tm *, (time_t const *__timer)); -# endif -_GL_CXXALIASWARN (gmtime); -# endif - -/* Parse BUF as a timestamp, assuming FORMAT specifies its layout, and store - the resulting broken-down time into TM. See - . */ -# if @GNULIB_STRPTIME@ -# if ! @HAVE_STRPTIME@ -_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf, - char const *restrict __format, - struct tm *restrict __tm) - _GL_ARG_NONNULL ((1, 2, 3))); -# endif -_GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf, - char const *restrict __format, - struct tm *restrict __tm)); -_GL_CXXALIASWARN (strptime); -# endif - -/* Convert *TP to a date and time string. See - . */ -# if @GNULIB_CTIME@ -# if @REPLACE_CTIME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define ctime rpl_ctime -# endif -_GL_ATTRIBUTE_DEPRECATED -_GL_FUNCDECL_RPL (ctime, char *, (time_t const *__tp) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp)); -# else -_GL_CXXALIAS_SYS (ctime, char *, (time_t const *__tp)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (ctime); -# endif -# endif - -/* Convert *TP to a date and time string. See - . */ -# if @GNULIB_STRFTIME@ -# if @REPLACE_STRFTIME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strftime rpl_strftime -# endif -_GL_FUNCDECL_RPL (strftime, size_t, - (char *restrict __buf, size_t __bufsize, - const char *restrict __fmt, const struct tm *restrict __tp) - _GL_ARG_NONNULL ((1, 3, 4))); -_GL_CXXALIAS_RPL (strftime, size_t, - (char *restrict __buf, size_t __bufsize, - const char *restrict __fmt, const struct tm *restrict __tp)); -# else -_GL_CXXALIAS_SYS (strftime, size_t, - (char *restrict __buf, size_t __bufsize, - const char *restrict __fmt, const struct tm *restrict __tp)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (strftime); -# endif -# endif - -# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@ -/* Functions that use a first-class time zone data type, instead of - relying on an implicit global time zone. - Inspired by NetBSD. */ - -/* Represents a time zone. - (timezone_t) NULL stands for UTC. */ -typedef struct tm_zone *timezone_t; - -/* tzalloc (name) - Returns a time zone object for the given time zone NAME. This object - represents the time zone that other functions would use it the TZ - environment variable was set to NAME. - If NAME is NULL, the result represents the time zone that other functions - would use it the TZ environment variable was unset. - May return NULL if NAME is invalid (this is platform dependent) or - upon memory allocation failure. */ -_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name)); -_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name)); - -/* tzfree (tz) - Frees a time zone object. - The argument must have been returned by tzalloc(). */ -_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz)); -_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz)); - -/* localtime_rz (tz, &t, &result) - Converts an absolute time T to a broken-down time RESULT, assuming the - time zone TZ. - This function is like 'localtime_r', but relies on the argument TZ instead - of an implicit global time zone. */ -_GL_FUNCDECL_SYS (localtime_rz, struct tm *, - (timezone_t __tz, time_t const *restrict __timer, - struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_SYS (localtime_rz, struct tm *, - (timezone_t __tz, time_t const *restrict __timer, - struct tm *restrict __result)); - -/* mktime_z (tz, &tm) - Normalizes the broken-down time TM and converts it to an absolute time, - assuming the time zone TZ. Returns the absolute time. - This function is like 'mktime', but relies on the argument TZ instead - of an implicit global time zone. */ -_GL_FUNCDECL_SYS (mktime_z, time_t, - (timezone_t __tz, struct tm *restrict __tm) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_SYS (mktime_z, time_t, - (timezone_t __tz, struct tm *restrict __tm)); - -/* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z' - in the 'tm_zone' member of 'struct tm') are valid as long as - - the 'struct tm' argument is not destroyed or overwritten, - and - - the 'timezone_t' argument is not freed through tzfree(). */ - -# endif - -/* Convert TM to a time_t value, assuming UTC. */ -# if @GNULIB_TIMEGM@ -# if @REPLACE_TIMEGM@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef timegm -# define timegm rpl_timegm -# endif -_GL_FUNCDECL_RPL (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (timegm, time_t, (struct tm *__tm)); -# else -# if ! @HAVE_TIMEGM@ -_GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm)); -# endif -_GL_CXXALIASWARN (timegm); -# endif - -/* Encourage applications to avoid unsafe functions that can overrun - buffers when given outlandish struct tm values. Portable - applications should use strftime (or even sprintf) instead. */ -# if defined GNULIB_POSIXCHECK -# undef asctime -_GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - " - "better use strftime (or even sprintf) instead"); -# endif -# if defined GNULIB_POSIXCHECK -# undef asctime_r -# if HAVE_RAW_DECL_ASCTIME_R -_GL_WARN_ON_USE (asctime_r, "asctime_r can overrun buffers in some cases - " - "better use strftime (or even sprintf) instead"); -# endif -# endif -# if defined GNULIB_POSIXCHECK -# undef ctime -_GL_WARN_ON_USE (ctime, "ctime can overrun buffers in some cases - " - "better use strftime (or even sprintf) instead"); -# endif -# if defined GNULIB_POSIXCHECK -# undef ctime_r -# if HAVE_RAW_DECL_CTIME_R -_GL_WARN_ON_USE (ctime_r, "ctime_r can overrun buffers in some cases - " - "better use strftime (or even sprintf) instead"); -# endif -# endif - -#endif diff --git a/xcompile/lib/time_r.c b/xcompile/lib/time_r.c deleted file mode 100644 index 97be4fd0544..00000000000 --- a/xcompile/lib/time_r.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Reentrant time functions like localtime_r. - - Copyright (C) 2003, 2006-2007, 2010-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include - -#include - -static struct tm * -copy_tm_result (struct tm *dest, struct tm const *src) -{ - if (! src) - return 0; - *dest = *src; - return dest; -} - - -struct tm * -gmtime_r (time_t const * restrict t, struct tm * restrict tp) -{ - return copy_tm_result (tp, gmtime (t)); -} - -struct tm * -localtime_r (time_t const * restrict t, struct tm * restrict tp) -{ - return copy_tm_result (tp, localtime (t)); -} diff --git a/xcompile/lib/time_rz.c b/xcompile/lib/time_rz.c deleted file mode 100644 index da0d57b8b1a..00000000000 --- a/xcompile/lib/time_rz.c +++ /dev/null @@ -1,316 +0,0 @@ -/* Time zone functions such as tzalloc and localtime_rz - - Copyright 2015-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -/* Although this module is not thread-safe, any races should be fairly - rare and reasonably benign. For complete thread-safety, use a C - library with a working timezone_t type, so that this module is not - needed. */ - -#include - -#include - -#include -#include -#include -#include - -#include "flexmember.h" -#include "idx.h" -#include "time-internal.h" - -/* The approximate size to use for small allocation requests. This is - the largest "small" request for the GNU C library malloc. */ -enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; - -/* Minimum size of the ABBRS member of struct tm_zone. ABBRS is larger - only in the unlikely case where an abbreviation longer than this is - used. */ -enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; - -/* Magic cookie timezone_t value, for local time. It differs from - NULL and from all other timezone_t values. Only the address - matters; the pointer is never dereferenced. */ -static timezone_t const local_tz = (timezone_t) 1; - -/* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this - includes its trailing null byte). Append an extra null byte to - mark the end of ABBRS. */ -static void -extend_abbrs (char *abbrs, char const *abbr, size_t abbr_size) -{ - memcpy (abbrs, abbr, abbr_size); - abbrs[abbr_size] = '\0'; -} - -/* Return a newly allocated time zone for NAME, or NULL on failure. - A null NAME stands for wall clock time (which is like unset TZ). */ -timezone_t -tzalloc (char const *name) -{ - size_t name_size = name ? strlen (name) + 1 : 0; - size_t abbr_size = name_size < ABBR_SIZE_MIN ? ABBR_SIZE_MIN : name_size + 1; - timezone_t tz = malloc (FLEXSIZEOF (struct tm_zone, abbrs, abbr_size)); - if (tz) - { - tz->next = NULL; -#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE - tz->tzname_copy[0] = tz->tzname_copy[1] = NULL; -#endif - tz->tz_is_set = !!name; - tz->abbrs[0] = '\0'; - if (name) - extend_abbrs (tz->abbrs, name, name_size); - } - return tz; -} - -/* Save into TZ any nontrivial time zone abbreviation used by TM, and - update *TM (if HAVE_STRUCT_TM_TM_ZONE) or *TZ (if - !HAVE_STRUCT_TM_TM_ZONE && HAVE_TZNAME) if they use the abbreviation. - Return true if successful, false (setting errno) otherwise. */ -static bool -save_abbr (timezone_t tz, struct tm *tm) -{ -#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME - char const *zone = NULL; - char *zone_copy = (char *) ""; - -# if HAVE_TZNAME - int tzname_index = -1; -# endif - -# if HAVE_STRUCT_TM_TM_ZONE - zone = tm->tm_zone; -# endif - -# if HAVE_TZNAME - if (! (zone && *zone) && 0 <= tm->tm_isdst) - { - tzname_index = tm->tm_isdst != 0; - zone = tzname[tzname_index]; - } -# endif - - /* No need to replace null zones, or zones within the struct tm. */ - if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1))) - return true; - - if (*zone) - { - zone_copy = tz->abbrs; - - while (strcmp (zone_copy, zone) != 0) - { - if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set))) - { - idx_t zone_size = strlen (zone) + 1; - if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy) - extend_abbrs (zone_copy, zone, zone_size); - else - { - tz = tz->next = tzalloc (zone); - if (!tz) - return false; - tz->tz_is_set = 0; - zone_copy = tz->abbrs; - } - break; - } - - zone_copy += strlen (zone_copy) + 1; - if (!*zone_copy && tz->next) - { - tz = tz->next; - zone_copy = tz->abbrs; - } - } - } - - /* Replace the zone name so that its lifetime matches that of TZ. */ -# if HAVE_STRUCT_TM_TM_ZONE - tm->tm_zone = zone_copy; -# else - if (0 <= tzname_index) - tz->tzname_copy[tzname_index] = zone_copy; -# endif -#endif - - return true; -} - -/* Free a time zone. */ -void -tzfree (timezone_t tz) -{ - if (tz != local_tz) - while (tz) - { - timezone_t next = tz->next; - free (tz); - tz = next; - } -} - -/* Get and set the TZ environment variable. These functions can be - overridden by programs like Emacs that manage their own environment. */ - -#ifndef getenv_TZ -static char * -getenv_TZ (void) -{ - return getenv ("TZ"); -} -#endif - -#ifndef setenv_TZ -static int -setenv_TZ (char const *tz) -{ - return tz ? setenv ("TZ", tz, 1) : unsetenv ("TZ"); -} -#endif - -/* Change the environment to match the specified timezone_t value. - Return true if successful, false (setting errno) otherwise. */ -static bool -change_env (timezone_t tz) -{ - if (setenv_TZ (tz->tz_is_set ? tz->abbrs : NULL) != 0) - return false; - tzset (); - return true; -} - -/* Temporarily set the time zone to TZ, which must not be null. - Return LOCAL_TZ if the time zone setting is already correct. - Otherwise return a newly allocated time zone representing the old - setting, or NULL (setting errno) on failure. */ -static timezone_t -set_tz (timezone_t tz) -{ - char *env_tz = getenv_TZ (); - if (env_tz - ? tz->tz_is_set && strcmp (tz->abbrs, env_tz) == 0 - : !tz->tz_is_set) - return local_tz; - else - { - timezone_t old_tz = tzalloc (env_tz); - if (!old_tz) - return old_tz; - if (! change_env (tz)) - { - int saved_errno = errno; - tzfree (old_tz); - errno = saved_errno; - return NULL; - } - return old_tz; - } -} - -/* Restore an old setting returned by set_tz. It must not be null. - Return true (preserving errno) if successful, false (setting errno) - otherwise. */ -static bool -revert_tz (timezone_t tz) -{ - if (tz == local_tz) - return true; - else - { - int saved_errno = errno; - bool ok = change_env (tz); - if (!ok) - saved_errno = errno; - tzfree (tz); - errno = saved_errno; - return ok; - } -} - -/* Use time zone TZ to compute localtime_r (T, TM). */ -struct tm * -localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) -{ -#ifdef HAVE_LOCALTIME_INFLOOP_BUG - /* The -67768038400665599 comes from: - https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html - On affected platforms the greatest POSIX-compatible time_t value - that could return nonnull is 67768036191766798 (when - TZ="XXX24:59:59" it resolves to the year 2**31 - 1 + 1900, on - 12-31 at 23:59:59), so test for that too while we're in the - neighborhood. */ - if (! (-67768038400665599 <= *t && *t <= 67768036191766798)) - { - errno = EOVERFLOW; - return NULL; - } -#endif - - if (!tz) - return gmtime_r (t, tm); - else - { - timezone_t old_tz = set_tz (tz); - if (old_tz) - { - bool abbr_saved = localtime_r (t, tm) && save_abbr (tz, tm); - if (revert_tz (old_tz) && abbr_saved) - return tm; - } - return NULL; - } -} - -/* Use time zone TZ to compute mktime (TM). */ -time_t -mktime_z (timezone_t tz, struct tm *tm) -{ - if (!tz) - return timegm (tm); - else - { - timezone_t old_tz = set_tz (tz); - if (old_tz) - { - struct tm tm_1; - tm_1.tm_sec = tm->tm_sec; - tm_1.tm_min = tm->tm_min; - tm_1.tm_hour = tm->tm_hour; - tm_1.tm_mday = tm->tm_mday; - tm_1.tm_mon = tm->tm_mon; - tm_1.tm_year = tm->tm_year; - tm_1.tm_yday = -1; - tm_1.tm_isdst = tm->tm_isdst; - time_t t = mktime (&tm_1); - bool ok = 0 <= tm_1.tm_yday; -#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME - ok = ok && save_abbr (tz, &tm_1); -#endif - if (revert_tz (old_tz) && ok) - { - *tm = tm_1; - return t; - } - } - return -1; - } -} diff --git a/xcompile/lib/timegm.c b/xcompile/lib/timegm.c deleted file mode 100644 index b47025a0545..00000000000 --- a/xcompile/lib/timegm.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Convert UTC calendar time to simple time. Like mktime but assumes UTC. - - Copyright (C) 1994-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -#include "mktime-internal.h" - -__time64_t -__timegm64 (struct tm *tmp) -{ - static mktime_offset_t gmtime_offset; - tmp->tm_isdst = 0; - return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset); -} - -#if defined _LIBC && __TIMESIZE != 64 - -libc_hidden_def (__timegm64) - -time_t -timegm (struct tm *tmp) -{ - struct tm tm = *tmp; - __time64_t t = __timegm64 (&tm); - if (in_time_t_range (t)) - { - *tmp = tm; - return t; - } - else - { - __set_errno (EOVERFLOW); - return -1; - } -} - -#endif diff --git a/xcompile/lib/timespec-add.c b/xcompile/lib/timespec-add.c deleted file mode 100644 index cb3017803b4..00000000000 --- a/xcompile/lib/timespec-add.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Add two struct timespec values. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -/* Return the sum of two timespec values A and B. On overflow, return - an extremal value. This assumes 0 <= tv_nsec < TIMESPEC_HZ. */ - -#include -#include "timespec.h" - -#include "intprops.h" - -struct timespec -timespec_add (struct timespec a, struct timespec b) -{ - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec + b.tv_nsec; - int nsd = ns - TIMESPEC_HZ; - int rns = ns; - - if (0 <= nsd) - { - rns = nsd; - time_t bs1; - if (!INT_ADD_WRAPV (bs, 1, &bs1)) - bs = bs1; - else if (rs < 0) - rs++; - else - goto high_overflow; - } - - if (INT_ADD_WRAPV (rs, bs, &rs)) - { - if (bs < 0) - { - rs = TYPE_MINIMUM (time_t); - rns = 0; - } - else - { - high_overflow: - rs = TYPE_MAXIMUM (time_t); - rns = TIMESPEC_HZ - 1; - } - } - - return make_timespec (rs, rns); -} diff --git a/xcompile/lib/timespec-sub.c b/xcompile/lib/timespec-sub.c deleted file mode 100644 index 822c2831089..00000000000 --- a/xcompile/lib/timespec-sub.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Subtract two struct timespec values. - - Copyright (C) 2011-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Paul Eggert. */ - -/* Return the difference between two timespec values A and B. On - overflow, return an extremal value. This assumes 0 <= tv_nsec < - TIMESPEC_HZ. */ - -#include -#include "timespec.h" - -#include "intprops.h" - -struct timespec -timespec_sub (struct timespec a, struct timespec b) -{ - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec - b.tv_nsec; - int rns = ns; - - if (ns < 0) - { - rns = ns + TIMESPEC_HZ; - time_t bs1; - if (!INT_ADD_WRAPV (bs, 1, &bs1)) - bs = bs1; - else if (- TYPE_SIGNED (time_t) < rs) - rs--; - else - goto low_overflow; - } - - if (INT_SUBTRACT_WRAPV (rs, bs, &rs)) - { - if (0 < bs) - { - low_overflow: - rs = TYPE_MINIMUM (time_t); - rns = 0; - } - else - { - rs = TYPE_MAXIMUM (time_t); - rns = TIMESPEC_HZ - 1; - } - } - - return make_timespec (rs, rns); -} diff --git a/xcompile/lib/timespec.c b/xcompile/lib/timespec.c deleted file mode 100644 index 5f7ffbdd45f..00000000000 --- a/xcompile/lib/timespec.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Inline functions for . - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define _GL_TIMESPEC_INLINE _GL_EXTERN_INLINE -#include "timespec.h" diff --git a/xcompile/lib/timespec.h b/xcompile/lib/timespec.h deleted file mode 100644 index ba78647f09a..00000000000 --- a/xcompile/lib/timespec.h +++ /dev/null @@ -1,102 +0,0 @@ -/* timespec -- System time interface - - Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2023 Free Software - Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -#if ! defined TIMESPEC_H -#define TIMESPEC_H - -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_TIMESPEC_INLINE -# define _GL_TIMESPEC_INLINE _GL_INLINE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include "arg-nonnull.h" - -/* Inverse resolution of timespec timestamps (in units per second), - and log base 10 of the inverse resolution. */ - -enum { TIMESPEC_HZ = 1000000000 }; -enum { LOG10_TIMESPEC_HZ = 9 }; - -/* Obsolescent names for backward compatibility. - They are misnomers, because TIMESPEC_RESOLUTION is not a resolution. */ - -enum { TIMESPEC_RESOLUTION = TIMESPEC_HZ }; -enum { LOG10_TIMESPEC_RESOLUTION = LOG10_TIMESPEC_HZ }; - -/* Return a timespec with seconds S and nanoseconds NS. */ - -_GL_TIMESPEC_INLINE struct timespec -make_timespec (time_t s, long int ns) -{ - struct timespec r; - r.tv_sec = s; - r.tv_nsec = ns; - return r; -} - -/* Return negative, zero, positive if A < B, A == B, A > B, respectively. */ - -_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE -timespec_cmp (struct timespec a, struct timespec b) -{ - return 2 * _GL_CMP (a.tv_sec, b.tv_sec) + _GL_CMP (a.tv_nsec, b.tv_nsec); -} - -/* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be - nonnegative. */ -_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE -timespec_sign (struct timespec a) -{ - return _GL_CMP (a.tv_sec, 0) + (!a.tv_sec & !!a.tv_nsec); -} - -struct timespec timespec_add (struct timespec, struct timespec) - _GL_ATTRIBUTE_CONST; -struct timespec timespec_sub (struct timespec, struct timespec) - _GL_ATTRIBUTE_CONST; -struct timespec dtotimespec (double) - _GL_ATTRIBUTE_CONST; - -/* Return an approximation to A, of type 'double'. */ -_GL_TIMESPEC_INLINE double -timespectod (struct timespec a) -{ - return a.tv_sec + a.tv_nsec / 1e9; -} - -long int gettime_res (void); -struct timespec current_timespec (void); -void gettime (struct timespec *) _GL_ARG_NONNULL ((1)); -int settime (struct timespec const *) _GL_ARG_NONNULL ((1)); - -#ifdef __cplusplus -} -#endif - -_GL_INLINE_HEADER_END - -#endif diff --git a/xcompile/lib/u64.c b/xcompile/lib/u64.c deleted file mode 100644 index ca088b45463..00000000000 --- a/xcompile/lib/u64.c +++ /dev/null @@ -1,22 +0,0 @@ -/* uint64_t-like operations that work even on hosts lacking uint64_t - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define _GL_U64_INLINE _GL_EXTERN_INLINE -#include "u64.h" -typedef int dummy; diff --git a/xcompile/lib/u64.h b/xcompile/lib/u64.h deleted file mode 100644 index 0353ad4d9af..00000000000 --- a/xcompile/lib/u64.h +++ /dev/null @@ -1,179 +0,0 @@ -/* uint64_t-like operations that work even on hosts lacking uint64_t - - Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_U64_INLINE -# define _GL_U64_INLINE _GL_INLINE -#endif - -/* Return X rotated left by N bits, where 0 < N < 64. */ -#define u64rol(x, n) u64or (u64shl (x, n), u64shr (x, 64 - n)) - -#ifdef UINT64_MAX - -/* Native implementations are trivial. See below for comments on what - these operations do. */ -typedef uint64_t u64; -# define u64hilo(hi, lo) ((u64) (((u64) (hi) << 32) + (lo))) -# define u64init(hi, lo) u64hilo (hi, lo) -# define u64lo(x) ((u64) (x)) -# define u64size(x) u64lo (x) -# define u64lt(x, y) ((x) < (y)) -# define u64and(x, y) ((x) & (y)) -# define u64or(x, y) ((x) | (y)) -# define u64xor(x, y) ((x) ^ (y)) -# define u64plus(x, y) ((x) + (y)) -# define u64shl(x, n) ((x) << (n)) -# define u64shr(x, n) ((x) >> (n)) - -#else - -/* u64 is a 64-bit unsigned integer value. - u64init (HI, LO), is like u64hilo (HI, LO), but for use in - initializer contexts. */ -# ifdef WORDS_BIGENDIAN -typedef struct { uint32_t hi, lo; } u64; -# define u64init(hi, lo) { hi, lo } -# else -typedef struct { uint32_t lo, hi; } u64; -# define u64init(hi, lo) { lo, hi } -# endif - -/* Given the high and low-order 32-bit quantities HI and LO, return a u64 - value representing (HI << 32) + LO. */ -_GL_U64_INLINE u64 -u64hilo (uint32_t hi, uint32_t lo) -{ - u64 r; - r.hi = hi; - r.lo = lo; - return r; -} - -/* Return a u64 value representing LO. */ -_GL_U64_INLINE u64 -u64lo (uint32_t lo) -{ - u64 r; - r.hi = 0; - r.lo = lo; - return r; -} - -/* Return a u64 value representing SIZE. */ -_GL_U64_INLINE u64 -u64size (size_t size) -{ - u64 r; - r.hi = size >> 31 >> 1; - r.lo = size; - return r; -} - -/* Return X < Y. */ -_GL_U64_INLINE int -u64lt (u64 x, u64 y) -{ - return x.hi < y.hi || (x.hi == y.hi && x.lo < y.lo); -} - -/* Return X & Y. */ -_GL_U64_INLINE u64 -u64and (u64 x, u64 y) -{ - u64 r; - r.hi = x.hi & y.hi; - r.lo = x.lo & y.lo; - return r; -} - -/* Return X | Y. */ -_GL_U64_INLINE u64 -u64or (u64 x, u64 y) -{ - u64 r; - r.hi = x.hi | y.hi; - r.lo = x.lo | y.lo; - return r; -} - -/* Return X ^ Y. */ -_GL_U64_INLINE u64 -u64xor (u64 x, u64 y) -{ - u64 r; - r.hi = x.hi ^ y.hi; - r.lo = x.lo ^ y.lo; - return r; -} - -/* Return X + Y. */ -_GL_U64_INLINE u64 -u64plus (u64 x, u64 y) -{ - u64 r; - r.lo = x.lo + y.lo; - r.hi = x.hi + y.hi + (r.lo < x.lo); - return r; -} - -/* Return X << N. */ -_GL_U64_INLINE u64 -u64shl (u64 x, int n) -{ - u64 r; - if (n < 32) - { - r.hi = (x.hi << n) | (x.lo >> (32 - n)); - r.lo = x.lo << n; - } - else - { - r.hi = x.lo << (n - 32); - r.lo = 0; - } - return r; -} - -/* Return X >> N. */ -_GL_U64_INLINE u64 -u64shr (u64 x, int n) -{ - u64 r; - if (n < 32) - { - r.hi = x.hi >> n; - r.lo = (x.hi << (32 - n)) | (x.lo >> n); - } - else - { - r.hi = 0; - r.lo = x.hi >> (n - 32); - } - return r; -} - -#endif - -_GL_INLINE_HEADER_END diff --git a/xcompile/lib/unistd.c b/xcompile/lib/unistd.c deleted file mode 100644 index be7a8255033..00000000000 --- a/xcompile/lib/unistd.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Inline functions for . - - Copyright (C) 2012-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#include - -#define _GL_UNISTD_INLINE _GL_EXTERN_INLINE -#include "unistd.h" -typedef int dummy; diff --git a/xcompile/lib/unistd.in.h b/xcompile/lib/unistd.in.h deleted file mode 100644 index 4812fdb1120..00000000000 --- a/xcompile/lib/unistd.in.h +++ /dev/null @@ -1,2329 +0,0 @@ -/* Substitute for and wrapper around . - Copyright (C) 2003-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef _@GUARD_PREFIX@_UNISTD_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif -@PRAGMA_COLUMNS@ - -#if @HAVE_UNISTD_H@ && defined _GL_INCLUDING_UNISTD_H -/* Special invocation convention: - - On Mac OS X 10.3.9 we have a sequence of nested includes - -> -> -> - In this situation, the functions are not yet declared, therefore we cannot - provide the C++ aliases. */ - -#@INCLUDE_NEXT@ @NEXT_UNISTD_H@ - -#else -/* Normal invocation convention. */ - -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_UNISTD_H@ -# define _GL_INCLUDING_UNISTD_H -# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ -# undef _GL_INCLUDING_UNISTD_H -#endif - -/* Get all possible declarations of gethostname(). */ -#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ - && !defined _GL_INCLUDING_WINSOCK2_H -# define _GL_INCLUDING_WINSOCK2_H -# include -# undef _GL_INCLUDING_WINSOCK2_H -#endif - -#if !defined _@GUARD_PREFIX@_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H -#define _@GUARD_PREFIX@_UNISTD_H - -/* NetBSD 5.0 mis-defines NULL. Also get size_t. */ -/* But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ -# include -#endif - -/* mingw doesn't define the SEEK_* or *_FILENO macros in . */ -/* MSVC declares 'unlink' in , not in . We must include - it before we #define unlink rpl_unlink. */ -/* Cygwin 1.7.1 declares symlinkat in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \ - || ((@GNULIB_UNLINK@ || defined GNULIB_POSIXCHECK) \ - && (defined _WIN32 && ! defined __CYGWIN__)) \ - || ((@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK) \ - && defined __CYGWIN__)) \ - && ! defined __GLIBC__ -# include -#endif - -/* Cygwin 1.7.1 and Android 4.3 declare unlinkat in , not in - . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \ - && (defined __CYGWIN__ || defined __ANDROID__) \ - && ! defined __GLIBC__ -# include -#endif - -/* mingw fails to declare _exit in . */ -/* mingw, MSVC, BeOS, Haiku declare environ in , not in - . */ -/* Solaris declares getcwd not only in but also in . */ -/* OSF Tru64 Unix cannot see gnulib rpl_strtod when system is - included here. */ -/* But avoid namespace pollution on glibc systems. */ -#if !defined __GLIBC__ && !defined __osf__ -# define __need_system_stdlib_h -# include -# undef __need_system_stdlib_h -#endif - -/* Native Windows platforms declare _chdir, _getcwd, _rmdir in - and/or , not in . - They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(), - _lseek(), _read(), _unlink(), _write() in . */ -#if defined _WIN32 && !defined __CYGWIN__ -# include -# include -#endif - -/* Native Windows platforms declare _execl*, _execv* in . */ -#if defined _WIN32 && !defined __CYGWIN__ -# include -#endif - -/* AIX and OSF/1 5.1 declare getdomainname in , not in . - NonStop Kernel declares gethostname in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if ((@GNULIB_GETDOMAINNAME@ && (defined _AIX || defined __osf__)) \ - || (@GNULIB_GETHOSTNAME@ && defined __TANDEM)) \ - && !defined __GLIBC__ -# include -#endif - -/* Mac OS X 10.13, Solaris 11.4, and Android 9.0 declare getentropy in - , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_GETENTROPY@ || defined GNULIB_POSIXCHECK) \ - && ((defined __APPLE__ && defined __MACH__) || defined __sun \ - || defined __ANDROID__) \ - && @UNISTD_H_HAVE_SYS_RANDOM_H@ \ - && !defined __GLIBC__ -# include -#endif - -/* Android 4.3 declares fchownat in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_FCHOWNAT@ || defined GNULIB_POSIXCHECK) && defined __ANDROID__ \ - && !defined __GLIBC__ -# include -#endif - -/* MSVC defines off_t in . - May also define off_t to a 64-bit type on native Windows. */ -/* Get off_t, ssize_t, mode_t. */ -#include - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Get getopt(), optarg, optind, opterr, optopt. */ -#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT -# include -# include -#endif - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_UNISTD_INLINE -# define _GL_UNISTD_INLINE _GL_INLINE -#endif - -/* Hide some function declarations from . */ - -#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ -# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef socket -# define socket socket_used_without_including_sys_socket_h -# undef connect -# define connect connect_used_without_including_sys_socket_h -# undef accept -# define accept accept_used_without_including_sys_socket_h -# undef bind -# define bind bind_used_without_including_sys_socket_h -# undef getpeername -# define getpeername getpeername_used_without_including_sys_socket_h -# undef getsockname -# define getsockname getsockname_used_without_including_sys_socket_h -# undef getsockopt -# define getsockopt getsockopt_used_without_including_sys_socket_h -# undef listen -# define listen listen_used_without_including_sys_socket_h -# undef recv -# define recv recv_used_without_including_sys_socket_h -# undef send -# define send send_used_without_including_sys_socket_h -# undef recvfrom -# define recvfrom recvfrom_used_without_including_sys_socket_h -# undef sendto -# define sendto sendto_used_without_including_sys_socket_h -# undef setsockopt -# define setsockopt setsockopt_used_without_including_sys_socket_h -# undef shutdown -# define shutdown shutdown_used_without_including_sys_socket_h -# else - _GL_WARN_ON_USE (socket, - "socket() used without including "); - _GL_WARN_ON_USE (connect, - "connect() used without including "); - _GL_WARN_ON_USE (accept, - "accept() used without including "); - _GL_WARN_ON_USE (bind, - "bind() used without including "); - _GL_WARN_ON_USE (getpeername, - "getpeername() used without including "); - _GL_WARN_ON_USE (getsockname, - "getsockname() used without including "); - _GL_WARN_ON_USE (getsockopt, - "getsockopt() used without including "); - _GL_WARN_ON_USE (listen, - "listen() used without including "); - _GL_WARN_ON_USE (recv, - "recv() used without including "); - _GL_WARN_ON_USE (send, - "send() used without including "); - _GL_WARN_ON_USE (recvfrom, - "recvfrom() used without including "); - _GL_WARN_ON_USE (sendto, - "sendto() used without including "); - _GL_WARN_ON_USE (setsockopt, - "setsockopt() used without including "); - _GL_WARN_ON_USE (shutdown, - "shutdown() used without including "); -# endif -# endif -# if !defined _@GUARD_PREFIX@_SYS_SELECT_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef select -# define select select_used_without_including_sys_select_h -# else - _GL_WARN_ON_USE (select, - "select() used without including "); -# endif -# endif -#endif - - -/* OS/2 EMX lacks these macros. */ -#ifndef STDIN_FILENO -# define STDIN_FILENO 0 -#endif -#ifndef STDOUT_FILENO -# define STDOUT_FILENO 1 -#endif -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - -/* Ensure *_OK macros exist. */ -#ifndef F_OK -# define F_OK 0 -# define X_OK 1 -# define W_OK 2 -# define R_OK 4 -#endif - - -/* Declare overridden functions. */ - - -#if @GNULIB_ACCESS@ -# if @REPLACE_ACCESS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef access -# define access rpl_access -# endif -_GL_FUNCDECL_RPL (access, int, (const char *file, int mode) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (access, int, (const char *file, int mode)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef access -# define access _access -# endif -_GL_CXXALIAS_MDA (access, int, (const char *file, int mode)); -# else -_GL_CXXALIAS_SYS (access, int, (const char *file, int mode)); -# endif -_GL_CXXALIASWARN (access); -#elif defined GNULIB_POSIXCHECK -# undef access -# if HAVE_RAW_DECL_ACCESS -/* The access() function is a security risk. */ -_GL_WARN_ON_USE (access, "access does not always support X_OK - " - "use gnulib module access for portability; " - "also, this function is a security risk - " - "use the gnulib module faccessat instead"); -# endif -#elif @GNULIB_MDA_ACCESS@ -/* On native Windows, map 'access' to '_access', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::access always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef access -# define access _access -# endif -_GL_CXXALIAS_MDA (access, int, (const char *file, int mode)); -# else -_GL_CXXALIAS_SYS (access, int, (const char *file, int mode)); -# endif -_GL_CXXALIASWARN (access); -#endif - - -#if @GNULIB_CHDIR@ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chdir -# define chdir _chdir -# endif -_GL_CXXALIAS_MDA (chdir, int, (const char *file)); -# else -_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIASWARN (chdir); -#elif defined GNULIB_POSIXCHECK -# undef chdir -# if HAVE_RAW_DECL_CHDIR -_GL_WARN_ON_USE (chown, "chdir is not always in - " - "use gnulib module chdir for portability"); -# endif -#elif @GNULIB_MDA_CHDIR@ -/* On native Windows, map 'chdir' to '_chdir', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::chdir always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chdir -# define chdir _chdir -# endif -_GL_CXXALIAS_MDA (chdir, int, (const char *file)); -# else -_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIASWARN (chdir); -#endif - - -#if @GNULIB_CHOWN@ -/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE - to GID (if GID is not -1). Follow symbolic links. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_DUP2@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup2 rpl_dup2 -# endif -_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd)); -_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef dup2 -# define dup2 _dup2 -# endif -_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd)); -# else -_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); -# endif -_GL_CXXALIASWARN (dup2); -#elif defined GNULIB_POSIXCHECK -# undef dup2 -# if HAVE_RAW_DECL_DUP2 -_GL_WARN_ON_USE (dup2, "dup2 is unportable - " - "use gnulib module dup2 for portability"); -# endif -#elif @GNULIB_MDA_DUP2@ -/* On native Windows, map 'dup2' to '_dup2', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::dup2 always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef dup2 -# define dup2 _dup2 -# endif -_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd)); -# else -_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); -# endif -_GL_CXXALIASWARN (dup2); -#endif - - -#if @GNULIB_DUP3@ -/* Copy the file descriptor OLDFD into file descriptor NEWFD, with the - specified flags. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - Close NEWFD first if it is open. - Return newfd if successful, otherwise -1 and errno set. - See the Linux man page at - . */ -# if @HAVE_DUP3@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup3 rpl_dup3 -# endif -_GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags)); -_GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags)); -# else -_GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags)); -_GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags)); -# endif -_GL_CXXALIASWARN (dup3); -#elif defined GNULIB_POSIXCHECK -# undef dup3 -# if HAVE_RAW_DECL_DUP3 -_GL_WARN_ON_USE (dup3, "dup3 is unportable - " - "use gnulib module dup3 for portability"); -# endif -#endif - - -#if @GNULIB_ENVIRON@ -# if defined __CYGWIN__ && !defined __i386__ -/* The 'environ' variable is defined in a DLL. Therefore its declaration needs - the '__declspec(dllimport)' attribute, but the system's lacks it. - This leads to a link error on 64-bit Cygwin when the option - -Wl,--disable-auto-import is in use. */ -_GL_EXTERN_C __declspec(dllimport) char **environ; -# endif -# if !@HAVE_DECL_ENVIRON@ -/* Set of environment variables and values. An array of strings of the form - "VARIABLE=VALUE", terminated with a NULL. */ -# if defined __APPLE__ && defined __MACH__ -# include -# if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR -# define _GL_USE_CRT_EXTERNS -# endif -# endif -# ifdef _GL_USE_CRT_EXTERNS -# include -# define environ (*_NSGetEnviron ()) -# else -# ifdef __cplusplus -extern "C" { -# endif -extern char **environ; -# ifdef __cplusplus -} -# endif -# endif -# endif -#elif defined GNULIB_POSIXCHECK -# if HAVE_RAW_DECL_ENVIRON -_GL_UNISTD_INLINE char *** -_GL_WARN_ON_USE_ATTRIBUTE ("environ is unportable - " - "use gnulib module environ for portability") -rpl_environ (void) -{ - return &environ; -} -# undef environ -# define environ (*rpl_environ ()) -# endif -#endif - - -#if @GNULIB_EUIDACCESS@ -/* Like access(), except that it uses the effective user id and group id of - the current process. */ -# if !@HAVE_EUIDACCESS@ -_GL_FUNCDECL_SYS (euidaccess, int, (const char *filename, int mode) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (euidaccess, int, (const char *filename, int mode)); -_GL_CXXALIASWARN (euidaccess); -# if defined GNULIB_POSIXCHECK -/* Like access(), this function is a security risk. */ -_GL_WARN_ON_USE (euidaccess, "the euidaccess function is a security risk - " - "use the gnulib module faccessat instead"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef euidaccess -# if HAVE_RAW_DECL_EUIDACCESS -_GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - " - "use gnulib module euidaccess for portability"); -# endif -#endif - - -#if @GNULIB_EXECL@ -# if @REPLACE_EXECL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execl -# define execl rpl_execl -# endif -_GL_FUNCDECL_RPL (execl, int, (const char *program, const char *arg, ...) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (execl, int, (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execl); -#elif defined GNULIB_POSIXCHECK -# undef execl -# if HAVE_RAW_DECL_EXECL -_GL_WARN_ON_USE (execl, "execl behaves very differently on mingw - " - "use gnulib module execl for portability"); -# endif -#elif @GNULIB_MDA_EXECL@ -/* On native Windows, map 'execl' to '_execl', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execl always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execl -# define execl _execl -# endif -_GL_CXXALIAS_MDA (execl, intptr_t, (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execl); -#endif - -#if @GNULIB_EXECLE@ -# if @REPLACE_EXECLE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execle -# define execle rpl_execle -# endif -_GL_FUNCDECL_RPL (execle, int, (const char *program, const char *arg, ...) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (execle, int, (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execle); -#elif defined GNULIB_POSIXCHECK -# undef execle -# if HAVE_RAW_DECL_EXECLE -_GL_WARN_ON_USE (execle, "execle behaves very differently on mingw - " - "use gnulib module execle for portability"); -# endif -#elif @GNULIB_MDA_EXECLE@ -/* On native Windows, map 'execle' to '_execle', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execle always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execle -# define execle _execle -# endif -_GL_CXXALIAS_MDA (execle, intptr_t, - (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execle); -#endif - -#if @GNULIB_EXECLP@ -# if @REPLACE_EXECLP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execlp -# define execlp rpl_execlp -# endif -_GL_FUNCDECL_RPL (execlp, int, (const char *program, const char *arg, ...) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (execlp, int, (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execlp); -#elif defined GNULIB_POSIXCHECK -# undef execlp -# if HAVE_RAW_DECL_EXECLP -_GL_WARN_ON_USE (execlp, "execlp behaves very differently on mingw - " - "use gnulib module execlp for portability"); -# endif -#elif @GNULIB_MDA_EXECLP@ -/* On native Windows, map 'execlp' to '_execlp', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execlp always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execlp -# define execlp _execlp -# endif -_GL_CXXALIAS_MDA (execlp, intptr_t, - (const char *program, const char *arg, ...)); -# else -_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...)); -# endif -_GL_CXXALIASWARN (execlp); -#endif - - -#if @GNULIB_EXECV@ -# if @REPLACE_EXECV@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execv -# define execv rpl_execv -# endif -_GL_FUNCDECL_RPL (execv, int, (const char *program, char * const *argv) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (execv, int, (const char *program, char * const *argv)); -# else -_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv)); -# endif -_GL_CXXALIASWARN (execv); -#elif defined GNULIB_POSIXCHECK -# undef execv -# if HAVE_RAW_DECL_EXECV -_GL_WARN_ON_USE (execv, "execv behaves very differently on mingw - " - "use gnulib module execv for portability"); -# endif -#elif @GNULIB_MDA_EXECV@ -/* On native Windows, map 'execv' to '_execv', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execv always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execv -# define execv _execv -# endif -_GL_CXXALIAS_MDA_CAST (execv, intptr_t, - (const char *program, char * const *argv)); -# else -_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv)); -# endif -_GL_CXXALIASWARN (execv); -#endif - -#if @GNULIB_EXECVE@ -# if @REPLACE_EXECVE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execve -# define execve rpl_execve -# endif -_GL_FUNCDECL_RPL (execve, int, - (const char *program, char * const *argv, char * const *env) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (execve, int, - (const char *program, char * const *argv, char * const *env)); -# else -_GL_CXXALIAS_SYS (execve, int, - (const char *program, char * const *argv, char * const *env)); -# endif -_GL_CXXALIASWARN (execve); -#elif defined GNULIB_POSIXCHECK -# undef execve -# if HAVE_RAW_DECL_EXECVE -_GL_WARN_ON_USE (execve, "execve behaves very differently on mingw - " - "use gnulib module execve for portability"); -# endif -#elif @GNULIB_MDA_EXECVE@ -/* On native Windows, map 'execve' to '_execve', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execve always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execve -# define execve _execve -# endif -_GL_CXXALIAS_MDA_CAST (execve, intptr_t, - (const char *program, char * const *argv, - char * const *env)); -# else -_GL_CXXALIAS_SYS (execve, int, - (const char *program, char * const *argv, char * const *env)); -# endif -_GL_CXXALIASWARN (execve); -#endif - -#if @GNULIB_EXECVP@ -# if @REPLACE_EXECVP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execvp -# define execvp rpl_execvp -# endif -_GL_FUNCDECL_RPL (execvp, int, (const char *program, char * const *argv) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (execvp, int, (const char *program, char * const *argv)); -# else -_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv)); -# endif -_GL_CXXALIASWARN (execvp); -#elif defined GNULIB_POSIXCHECK -# undef execvp -# if HAVE_RAW_DECL_EXECVP -_GL_WARN_ON_USE (execvp, "execvp behaves very differently on mingw - " - "use gnulib module execvp for portability"); -# endif -#elif @GNULIB_MDA_EXECVP@ -/* On native Windows, map 'execvp' to '_execvp', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execvp always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execvp -# define execvp _execvp -# endif -_GL_CXXALIAS_MDA_CAST (execvp, intptr_t, - (const char *program, char * const *argv)); -# else -_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv)); -# endif -_GL_CXXALIASWARN (execvp); -#endif - -#if @GNULIB_EXECVPE@ -# if @REPLACE_EXECVPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execvpe -# define execvpe rpl_execvpe -# endif -_GL_FUNCDECL_RPL (execvpe, int, - (const char *program, char * const *argv, char * const *env) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (execvpe, int, - (const char *program, char * const *argv, char * const *env)); -# else -# if !@HAVE_DECL_EXECVPE@ -_GL_FUNCDECL_SYS (execvpe, int, - (const char *program, char * const *argv, char * const *env) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (execvpe, int, - (const char *program, char * const *argv, char * const *env)); -# endif -_GL_CXXALIASWARN (execvpe); -#elif defined GNULIB_POSIXCHECK -# undef execvpe -# if HAVE_RAW_DECL_EXECVPE -_GL_WARN_ON_USE (execvpe, "execvpe behaves very differently on mingw - " - "use gnulib module execvpe for portability"); -# endif -#elif @GNULIB_MDA_EXECVPE@ -/* On native Windows, map 'execvpe' to '_execvpe', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::execvpe on all platforms that have - it. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef execvpe -# define execvpe _execvpe -# endif -_GL_CXXALIAS_MDA_CAST (execvpe, intptr_t, - (const char *program, char * const *argv, - char * const *env)); -# elif @HAVE_EXECVPE@ -# if !@HAVE_DECL_EXECVPE@ -_GL_FUNCDECL_SYS (execvpe, int, - (const char *program, char * const *argv, char * const *env) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (execvpe, int, - (const char *program, char * const *argv, char * const *env)); -# endif -# if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_EXECVPE@ -_GL_CXXALIASWARN (execvpe); -# endif -#endif - - -#if @GNULIB_FACCESSAT@ -# if @REPLACE_FACCESSAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef faccessat -# define faccessat rpl_faccessat -# endif -_GL_FUNCDECL_RPL (faccessat, int, - (int fd, char const *name, int mode, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (faccessat, int, - (int fd, char const *name, int mode, int flag)); -# else -# if !@HAVE_FACCESSAT@ -_GL_FUNCDECL_SYS (faccessat, int, - (int fd, char const *file, int mode, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (faccessat, int, - (int fd, char const *file, int mode, int flag)); -# endif -_GL_CXXALIASWARN (faccessat); -#elif defined GNULIB_POSIXCHECK -# undef faccessat -# if HAVE_RAW_DECL_FACCESSAT -_GL_WARN_ON_USE (faccessat, "faccessat is not portable - " - "use gnulib module faccessat for portability"); -# endif -#endif - - -#if @GNULIB_FCHDIR@ -/* Change the process' current working directory to the directory on which - the given file descriptor is open. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if ! @HAVE_FCHDIR@ -_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); - -/* Gnulib internal hooks needed to maintain the fchdir metadata. */ -_GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) - _GL_ARG_NONNULL ((2)); -_GL_EXTERN_C void _gl_unregister_fd (int fd); -_GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); -_GL_EXTERN_C const char *_gl_directory_name (int fd); - -# else -# if !@HAVE_DECL_FCHDIR@ -_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); -# endif -# endif -_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); -_GL_CXXALIASWARN (fchdir); -#elif defined GNULIB_POSIXCHECK -# undef fchdir -# if HAVE_RAW_DECL_FCHDIR -_GL_WARN_ON_USE (fchdir, "fchdir is unportable - " - "use gnulib module fchdir for portability"); -# endif -#endif - - -#if @GNULIB_FCHOWNAT@ -# if @REPLACE_FCHOWNAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fchownat -# define fchownat rpl_fchownat -# endif -_GL_FUNCDECL_RPL (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag)); -# else -# if !@HAVE_FCHOWNAT@ -_GL_FUNCDECL_SYS (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag)); -# endif -_GL_CXXALIASWARN (fchownat); -#elif defined GNULIB_POSIXCHECK -# undef fchownat -# if HAVE_RAW_DECL_FCHOWNAT -_GL_WARN_ON_USE (fchownat, "fchownat is not portable - " - "use gnulib module fchownat for portability"); -# endif -#endif - - -#if @GNULIB_FDATASYNC@ -/* Synchronize changes to a file. - Return 0 if successful, otherwise -1 and errno set. - See POSIX:2008 specification - . */ -# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@ -_GL_FUNCDECL_SYS (fdatasync, int, (int fd)); -# endif -_GL_CXXALIAS_SYS (fdatasync, int, (int fd)); -_GL_CXXALIASWARN (fdatasync); -#elif defined GNULIB_POSIXCHECK -# undef fdatasync -# if HAVE_RAW_DECL_FDATASYNC -_GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - " - "use gnulib module fdatasync for portability"); -# endif -#endif - - -#if @GNULIB_FSYNC@ -/* Synchronize changes, including metadata, to a file. - Return 0 if successful, otherwise -1 and errno set. - See POSIX:2008 specification - . */ -# if !@HAVE_FSYNC@ -_GL_FUNCDECL_SYS (fsync, int, (int fd)); -# endif -_GL_CXXALIAS_SYS (fsync, int, (int fd)); -_GL_CXXALIASWARN (fsync); -#elif defined GNULIB_POSIXCHECK -# undef fsync -# if HAVE_RAW_DECL_FSYNC -_GL_WARN_ON_USE (fsync, "fsync is unportable - " - "use gnulib module fsync for portability"); -# endif -#endif - - -#if @GNULIB_FTRUNCATE@ -/* Change the size of the file to which FD is opened to become equal to LENGTH. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_FTRUNCATE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef ftruncate -# define ftruncate rpl_ftruncate -# endif -_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length)); -_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length)); -# else -# if !@HAVE_FTRUNCATE@ -_GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); -# endif -_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); -# endif -_GL_CXXALIASWARN (ftruncate); -#elif defined GNULIB_POSIXCHECK -# undef ftruncate -# if HAVE_RAW_DECL_FTRUNCATE -_GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " - "use gnulib module ftruncate for portability"); -# endif -#endif - - -#if @GNULIB_GETCWD@ -/* Get the name of the current working directory, and put it in SIZE bytes - of BUF. - Return BUF if successful, or NULL if the directory couldn't be determined - or SIZE was too small. - See the POSIX:2008 specification - . - Additionally, the gnulib module 'getcwd' guarantees the following GNU - extension: If BUF is NULL, an array is allocated with 'malloc'; the array - is SIZE bytes long, unless SIZE == 0, in which case it is as big as - necessary. */ -# if @REPLACE_GETCWD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getcwd rpl_getcwd -# endif -_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size)); -_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getcwd -# define getcwd _getcwd -# endif -_GL_CXXALIAS_MDA (getcwd, char *, (char *buf, size_t size)); -# else -/* Need to cast, because on mingw, the second parameter is - int size. */ -_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); -# endif -_GL_CXXALIASWARN (getcwd); -#elif defined GNULIB_POSIXCHECK -# undef getcwd -# if HAVE_RAW_DECL_GETCWD -_GL_WARN_ON_USE (getcwd, "getcwd is unportable - " - "use gnulib module getcwd for portability"); -# endif -#elif @GNULIB_MDA_GETCWD@ -/* On native Windows, map 'getcwd' to '_getcwd', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::getcwd always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getcwd -# define getcwd _getcwd -# endif -/* Need to cast, because on mingw, the second parameter is either - 'int size' or 'size_t size'. */ -_GL_CXXALIAS_MDA_CAST (getcwd, char *, (char *buf, size_t size)); -# else -_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); -# endif -_GL_CXXALIASWARN (getcwd); -#endif - - -#if @GNULIB_GETDOMAINNAME@ -/* Return the NIS domain name of the machine. - WARNING! The NIS domain name is unrelated to the fully qualified host name - of the machine. It is also unrelated to email addresses. - WARNING! The NIS domain name is usually the empty string or "(none)" when - not using NIS. - - Put up to LEN bytes of the NIS domain name into NAME. - Null terminate it if the name is shorter than LEN. - If the NIS domain name is longer than LEN, set errno = EINVAL and return -1. - Return 0 if successful, otherwise set errno and return -1. */ -# if @REPLACE_GETDOMAINNAME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getdomainname -# define getdomainname rpl_getdomainname -# endif -_GL_FUNCDECL_RPL (getdomainname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (getdomainname, int, (char *name, size_t len)); -# else -# if !@HAVE_DECL_GETDOMAINNAME@ -_GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (getdomainname, int, (char *name, size_t len)); -# endif -# if __GLIBC__ >= 2 -_GL_CXXALIASWARN (getdomainname); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getdomainname -# if HAVE_RAW_DECL_GETDOMAINNAME -_GL_WARN_ON_USE (getdomainname, "getdomainname is unportable - " - "use gnulib module getdomainname for portability"); -# endif -#endif - - -#if @GNULIB_GETDTABLESIZE@ -/* Return the maximum number of file descriptors in the current process. - In POSIX, this is same as sysconf (_SC_OPEN_MAX). */ -# if @REPLACE_GETDTABLESIZE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getdtablesize -# define getdtablesize rpl_getdtablesize -# endif -_GL_FUNCDECL_RPL (getdtablesize, int, (void)); -_GL_CXXALIAS_RPL (getdtablesize, int, (void)); -# else -# if !@HAVE_GETDTABLESIZE@ -_GL_FUNCDECL_SYS (getdtablesize, int, (void)); -# endif -/* Need to cast, because on AIX, the parameter list is - (...). */ -_GL_CXXALIAS_SYS_CAST (getdtablesize, int, (void)); -# endif -_GL_CXXALIASWARN (getdtablesize); -#elif defined GNULIB_POSIXCHECK -# undef getdtablesize -# if HAVE_RAW_DECL_GETDTABLESIZE -_GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - " - "use gnulib module getdtablesize for portability"); -# endif -#endif - - -#if @GNULIB_GETENTROPY@ -/* Fill a buffer with random bytes. */ -# if !@HAVE_GETENTROPY@ -_GL_FUNCDECL_SYS (getentropy, int, (void *buffer, size_t length)); -# endif -_GL_CXXALIAS_SYS (getentropy, int, (void *buffer, size_t length)); -_GL_CXXALIASWARN (getentropy); -#elif defined GNULIB_POSIXCHECK -# undef getentropy -# if HAVE_RAW_DECL_GETENTROPY -_GL_WARN_ON_USE (getentropy, "getentropy is unportable - " - "use gnulib module getentropy for portability"); -# endif -#endif - - -#if @GNULIB_GETGROUPS@ -/* Return the supplemental groups that the current process belongs to. - It is unspecified whether the effective group id is in the list. - If N is 0, return the group count; otherwise, N describes how many - entries are available in GROUPS. Return -1 and set errno if N is - not 0 and not large enough. Fails with ENOSYS on some systems. */ -# if @REPLACE_GETGROUPS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getgroups -# define getgroups rpl_getgroups -# endif -_GL_FUNCDECL_RPL (getgroups, int, (int n, gid_t *groups)); -_GL_CXXALIAS_RPL (getgroups, int, (int n, gid_t *groups)); -# else -# if !@HAVE_GETGROUPS@ -_GL_FUNCDECL_SYS (getgroups, int, (int n, gid_t *groups)); -# endif -_GL_CXXALIAS_SYS (getgroups, int, (int n, gid_t *groups)); -# endif -_GL_CXXALIASWARN (getgroups); -#elif defined GNULIB_POSIXCHECK -# undef getgroups -# if HAVE_RAW_DECL_GETGROUPS -_GL_WARN_ON_USE (getgroups, "getgroups is unportable - " - "use gnulib module getgroups for portability"); -# endif -#endif - - -#if @GNULIB_GETHOSTNAME@ -/* Return the standard host name of the machine. - WARNING! The host name may or may not be fully qualified. - - Put up to LEN bytes of the host name into NAME. - Null terminate it if the name is shorter than LEN. - If the host name is longer than LEN, set errno = EINVAL and return -1. - Return 0 if successful, otherwise set errno and return -1. */ -# if @UNISTD_H_HAVE_WINSOCK2_H@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gethostname -# define gethostname rpl_gethostname -# endif -_GL_FUNCDECL_RPL (gethostname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); -# else -# if !@HAVE_GETHOSTNAME@ -_GL_FUNCDECL_SYS (gethostname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on Solaris 10 and OSF/1 5.1 systems, the second - parameter is - int len. */ -_GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); -# endif -_GL_CXXALIASWARN (gethostname); -#elif @UNISTD_H_HAVE_WINSOCK2_H@ -# undef gethostname -# define gethostname gethostname_used_without_requesting_gnulib_module_gethostname -#elif defined GNULIB_POSIXCHECK -# undef gethostname -# if HAVE_RAW_DECL_GETHOSTNAME -_GL_WARN_ON_USE (gethostname, "gethostname is unportable - " - "use gnulib module gethostname for portability"); -# endif -#endif - - -#if @GNULIB_GETLOGIN@ -/* Returns the user's login name, or NULL if it cannot be found. Upon error, - returns NULL with errno set. - - See . - - Most programs don't need to use this function, because the information is - available through environment variables: - ${LOGNAME-$USER} on Unix platforms, - $USERNAME on native Windows platforms. - */ -# if !@HAVE_DECL_GETLOGIN@ -_GL_FUNCDECL_SYS (getlogin, char *, (void)); -# endif -_GL_CXXALIAS_SYS (getlogin, char *, (void)); -_GL_CXXALIASWARN (getlogin); -#elif defined GNULIB_POSIXCHECK -# undef getlogin -# if HAVE_RAW_DECL_GETLOGIN -_GL_WARN_ON_USE (getlogin, "getlogin is unportable - " - "use gnulib module getlogin for portability"); -# endif -#endif - - -#if @GNULIB_GETLOGIN_R@ -/* Copies the user's login name to NAME. - The array pointed to by NAME has room for SIZE bytes. - - Returns 0 if successful. Upon error, an error number is returned, or -1 in - the case that the login name cannot be found but no specific error is - provided (this case is hopefully rare but is left open by the POSIX spec). - - See . - - Most programs don't need to use this function, because the information is - available through environment variables: - ${LOGNAME-$USER} on Unix platforms, - $USERNAME on native Windows platforms. - */ -# if @REPLACE_GETLOGIN_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getlogin_r rpl_getlogin_r -# endif -_GL_FUNCDECL_RPL (getlogin_r, int, (char *name, size_t size) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (getlogin_r, int, (char *name, size_t size)); -# else -# if !@HAVE_DECL_GETLOGIN_R@ -_GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on Solaris 10 systems, the second argument is - int size. */ -_GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size)); -# endif -_GL_CXXALIASWARN (getlogin_r); -#elif defined GNULIB_POSIXCHECK -# undef getlogin_r -# if HAVE_RAW_DECL_GETLOGIN_R -_GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - " - "use gnulib module getlogin_r for portability"); -# endif -#endif - - -#if @GNULIB_GETPAGESIZE@ -# if @REPLACE_GETPAGESIZE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getpagesize rpl_getpagesize -# endif -_GL_FUNCDECL_RPL (getpagesize, int, (void)); -_GL_CXXALIAS_RPL (getpagesize, int, (void)); -# else -/* On HP-UX, getpagesize exists, but it is not declared in even if - the compiler options -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 are used. */ -# if defined __hpux -_GL_FUNCDECL_SYS (getpagesize, int, (void)); -# endif -# if !@HAVE_GETPAGESIZE@ -# if !defined getpagesize -/* This is for POSIX systems. */ -# if !defined _gl_getpagesize && defined _SC_PAGESIZE -# if ! (defined __VMS && __VMS_VER < 70000000) -# define _gl_getpagesize() sysconf (_SC_PAGESIZE) -# endif -# endif -/* This is for older VMS. */ -# if !defined _gl_getpagesize && defined __VMS -# ifdef __ALPHA -# define _gl_getpagesize() 8192 -# else -# define _gl_getpagesize() 512 -# endif -# endif -/* This is for BeOS. */ -# if !defined _gl_getpagesize && @HAVE_OS_H@ -# include -# if defined B_PAGE_SIZE -# define _gl_getpagesize() B_PAGE_SIZE -# endif -# endif -/* This is for AmigaOS4.0. */ -# if !defined _gl_getpagesize && defined __amigaos4__ -# define _gl_getpagesize() 2048 -# endif -/* This is for older Unix systems. */ -# if !defined _gl_getpagesize && @HAVE_SYS_PARAM_H@ -# include -# ifdef EXEC_PAGESIZE -# define _gl_getpagesize() EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define CLSIZE 1 -# endif -# define _gl_getpagesize() (NBPG * CLSIZE) -# else -# ifdef NBPC -# define _gl_getpagesize() NBPC -# endif -# endif -# endif -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getpagesize() _gl_getpagesize () -# else -# if !GNULIB_defined_getpagesize_function -_GL_UNISTD_INLINE int -getpagesize () -{ - return _gl_getpagesize (); -} -# define GNULIB_defined_getpagesize_function 1 -# endif -# endif -# endif -# endif -/* Need to cast, because on Cygwin 1.5.x systems, the return type is size_t. */ -_GL_CXXALIAS_SYS_CAST (getpagesize, int, (void)); -# endif -# if @HAVE_DECL_GETPAGESIZE@ -_GL_CXXALIASWARN (getpagesize); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getpagesize -# if HAVE_RAW_DECL_GETPAGESIZE -_GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - " - "use gnulib module getpagesize for portability"); -# endif -#endif - - -#if @GNULIB_GETPASS@ -/* Function getpass() from module 'getpass': - Read a password from /dev/tty or stdin. - Function getpass() from module 'getpass-gnu': - Read a password of arbitrary length from /dev/tty or stdin. */ -# if (@GNULIB_GETPASS@ && @REPLACE_GETPASS@) \ - || (@GNULIB_GETPASS_GNU@ && @REPLACE_GETPASS_FOR_GETPASS_GNU@) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getpass -# define getpass rpl_getpass -# endif -_GL_FUNCDECL_RPL (getpass, char *, (const char *prompt) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (getpass, char *, (const char *prompt)); -# else -# if !@HAVE_GETPASS@ -_GL_FUNCDECL_SYS (getpass, char *, (const char *prompt) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (getpass, char *, (const char *prompt)); -# endif -_GL_CXXALIASWARN (getpass); -#elif defined GNULIB_POSIXCHECK -# undef getpass -# if HAVE_RAW_DECL_GETPASS -_GL_WARN_ON_USE (getpass, "getpass is unportable - " - "use gnulib module getpass or getpass-gnu for portability"); -# endif -#endif - - -#if @GNULIB_MDA_GETPID@ -/* On native Windows, map 'getpid' to '_getpid', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::getpid always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getpid -# define getpid _getpid -# endif -_GL_CXXALIAS_MDA (getpid, int, (void)); -# else -_GL_CXXALIAS_SYS (getpid, pid_t, (void)); -# endif -_GL_CXXALIASWARN (getpid); -#endif - - -#if @GNULIB_GETUSERSHELL@ -/* Return the next valid login shell on the system, or NULL when the end of - the list has been reached. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (getusershell, char *, (void)); -# endif -_GL_CXXALIAS_SYS (getusershell, char *, (void)); -_GL_CXXALIASWARN (getusershell); -#elif defined GNULIB_POSIXCHECK -# undef getusershell -# if HAVE_RAW_DECL_GETUSERSHELL -_GL_WARN_ON_USE (getusershell, "getusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - -#if @GNULIB_GETUSERSHELL@ -/* Rewind to pointer that is advanced at each getusershell() call. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (setusershell, void, (void)); -# endif -_GL_CXXALIAS_SYS (setusershell, void, (void)); -_GL_CXXALIASWARN (setusershell); -#elif defined GNULIB_POSIXCHECK -# undef setusershell -# if HAVE_RAW_DECL_SETUSERSHELL -_GL_WARN_ON_USE (setusershell, "setusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - -#if @GNULIB_GETUSERSHELL@ -/* Free the pointer that is advanced at each getusershell() call and - associated resources. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (endusershell, void, (void)); -# endif -_GL_CXXALIAS_SYS (endusershell, void, (void)); -_GL_CXXALIASWARN (endusershell); -#elif defined GNULIB_POSIXCHECK -# undef endusershell -# if HAVE_RAW_DECL_ENDUSERSHELL -_GL_WARN_ON_USE (endusershell, "endusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - - -#if @GNULIB_GROUP_MEMBER@ -/* Determine whether group id is in calling user's group list. */ -# if !@HAVE_GROUP_MEMBER@ -_GL_FUNCDECL_SYS (group_member, int, (gid_t gid)); -# endif -_GL_CXXALIAS_SYS (group_member, int, (gid_t gid)); -_GL_CXXALIASWARN (group_member); -#elif defined GNULIB_POSIXCHECK -# undef group_member -# if HAVE_RAW_DECL_GROUP_MEMBER -_GL_WARN_ON_USE (group_member, "group_member is unportable - " - "use gnulib module group-member for portability"); -# endif -#endif - - -#if @GNULIB_ISATTY@ -# if @REPLACE_ISATTY@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef isatty -# define isatty rpl_isatty -# endif -# define GNULIB_defined_isatty 1 -_GL_FUNCDECL_RPL (isatty, int, (int fd)); -_GL_CXXALIAS_RPL (isatty, int, (int fd)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef isatty -# define isatty _isatty -# endif -_GL_CXXALIAS_MDA (isatty, int, (int fd)); -# else -_GL_CXXALIAS_SYS (isatty, int, (int fd)); -# endif -_GL_CXXALIASWARN (isatty); -#elif defined GNULIB_POSIXCHECK -# undef isatty -# if HAVE_RAW_DECL_ISATTY -_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - " - "use gnulib module isatty for portability"); -# endif -#elif @GNULIB_MDA_ISATTY@ -/* On native Windows, map 'isatty' to '_isatty', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::isatty always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef isatty -# define isatty _isatty -# endif -_GL_CXXALIAS_MDA (isatty, int, (int fd)); -# else -_GL_CXXALIAS_SYS (isatty, int, (int fd)); -# endif -_GL_CXXALIASWARN (isatty); -#endif - - -#if @GNULIB_LCHOWN@ -/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE - to GID (if GID is not -1). Do not follow symbolic links. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_LCHOWN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef lchown -# define lchown rpl_lchown -# endif -_GL_FUNCDECL_RPL (lchown, int, (char const *file, uid_t owner, gid_t group) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (lchown, int, (char const *file, uid_t owner, gid_t group)); -# else -# if !@HAVE_LCHOWN@ -_GL_FUNCDECL_SYS (lchown, int, (char const *file, uid_t owner, gid_t group) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (lchown, int, (char const *file, uid_t owner, gid_t group)); -# endif -_GL_CXXALIASWARN (lchown); -#elif defined GNULIB_POSIXCHECK -# undef lchown -# if HAVE_RAW_DECL_LCHOWN -_GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " - "use gnulib module lchown for portability"); -# endif -#endif - - -#if @GNULIB_LINK@ -/* Create a new hard link for an existing file. - Return 0 if successful, otherwise -1 and errno set. - See POSIX:2008 specification - . */ -# if @REPLACE_LINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define link rpl_link -# endif -_GL_FUNCDECL_RPL (link, int, (const char *path1, const char *path2) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (link, int, (const char *path1, const char *path2)); -# else -# if !@HAVE_LINK@ -_GL_FUNCDECL_SYS (link, int, (const char *path1, const char *path2) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (link, int, (const char *path1, const char *path2)); -# endif -_GL_CXXALIASWARN (link); -#elif defined GNULIB_POSIXCHECK -# undef link -# if HAVE_RAW_DECL_LINK -_GL_WARN_ON_USE (link, "link is unportable - " - "use gnulib module link for portability"); -# endif -#endif - - -#if @GNULIB_LINKAT@ -/* Create a new hard link for an existing file, relative to two - directories. FLAG controls whether symlinks are followed. - Return 0 if successful, otherwise -1 and errno set. */ -# if @REPLACE_LINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef linkat -# define linkat rpl_linkat -# endif -_GL_FUNCDECL_RPL (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag) - _GL_ARG_NONNULL ((2, 4))); -_GL_CXXALIAS_RPL (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag)); -# else -# if !@HAVE_LINKAT@ -_GL_FUNCDECL_SYS (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag) - _GL_ARG_NONNULL ((2, 4))); -# endif -_GL_CXXALIAS_SYS (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag)); -# endif -_GL_CXXALIASWARN (linkat); -#elif defined GNULIB_POSIXCHECK -# undef linkat -# if HAVE_RAW_DECL_LINKAT -_GL_WARN_ON_USE (linkat, "linkat is unportable - " - "use gnulib module linkat for portability"); -# endif -#endif - - -#if @GNULIB_LSEEK@ -/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. - Return the new offset if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_LSEEK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define lseek rpl_lseek -# endif -_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence)); -_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef lseek -# define lseek _lseek -# endif -_GL_CXXALIAS_MDA (lseek, off_t, (int fd, off_t offset, int whence)); -# else -_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); -# endif -_GL_CXXALIASWARN (lseek); -#elif defined GNULIB_POSIXCHECK -# undef lseek -# if HAVE_RAW_DECL_LSEEK -_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " - "systems - use gnulib module lseek for portability"); -# endif -#elif @GNULIB_MDA_LSEEK@ -/* On native Windows, map 'lseek' to '_lseek', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::lseek always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef lseek -# define lseek _lseek -# endif -_GL_CXXALIAS_MDA (lseek, long, (int fd, long offset, int whence)); -# else -_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); -# endif -_GL_CXXALIASWARN (lseek); -#endif - - -#if @GNULIB_PIPE@ -/* Create a pipe, defaulting to O_BINARY mode. - Store the read-end as fd[0] and the write-end as fd[1]. - Return 0 upon success, or -1 with errno set upon failure. */ -# if !@HAVE_PIPE@ -_GL_FUNCDECL_SYS (pipe, int, (int fd[2]) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (pipe, int, (int fd[2])); -_GL_CXXALIASWARN (pipe); -#elif defined GNULIB_POSIXCHECK -# undef pipe -# if HAVE_RAW_DECL_PIPE -_GL_WARN_ON_USE (pipe, "pipe is unportable - " - "use gnulib module pipe-posix for portability"); -# endif -#endif - - -#if @GNULIB_PIPE2@ -/* Create a pipe, applying the given flags when opening the read-end of the - pipe and the write-end of the pipe. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - Store the read-end as fd[0] and the write-end as fd[1]. - Return 0 upon success, or -1 with errno set upon failure. - See also the Linux man page at - . */ -# if @HAVE_PIPE2@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define pipe2 rpl_pipe2 -# endif -_GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags)); -# else -_GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags)); -# endif -_GL_CXXALIASWARN (pipe2); -#elif defined GNULIB_POSIXCHECK -# undef pipe2 -# if HAVE_RAW_DECL_PIPE2 -_GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " - "use gnulib module pipe2 for portability"); -# endif -#endif - - -#if @GNULIB_PREAD@ -/* Read at most BUFSIZE bytes from FD into BUF, starting at OFFSET. - Return the number of bytes placed into BUF if successful, otherwise - set errno and return -1. 0 indicates EOF. - See the POSIX:2008 specification - . */ -# if @REPLACE_PREAD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef pread -# define pread rpl_pread -# endif -_GL_FUNCDECL_RPL (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset)); -# else -# if !@HAVE_PREAD@ -_GL_FUNCDECL_SYS (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset)); -# endif -_GL_CXXALIASWARN (pread); -#elif defined GNULIB_POSIXCHECK -# undef pread -# if HAVE_RAW_DECL_PREAD -_GL_WARN_ON_USE (pread, "pread is unportable - " - "use gnulib module pread for portability"); -# endif -#endif - - -#if @GNULIB_PWRITE@ -/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. - Return the number of bytes written if successful, otherwise - set errno and return -1. 0 indicates nothing written. See the - POSIX:2008 specification - . */ -# if @REPLACE_PWRITE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef pwrite -# define pwrite rpl_pwrite -# endif -_GL_FUNCDECL_RPL (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset)); -# else -# if !@HAVE_PWRITE@ -_GL_FUNCDECL_SYS (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset)); -# endif -_GL_CXXALIASWARN (pwrite); -#elif defined GNULIB_POSIXCHECK -# undef pwrite -# if HAVE_RAW_DECL_PWRITE -_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " - "use gnulib module pwrite for portability"); -# endif -#endif - - -#if @GNULIB_READ@ -/* Read up to COUNT bytes from file descriptor FD into the buffer starting - at BUF. See the POSIX:2008 specification - . */ -# if @REPLACE_READ@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef read -# define read rpl_read -# endif -_GL_FUNCDECL_RPL (read, ssize_t, (int fd, void *buf, size_t count) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef read -# define read _read -# endif -_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, size_t count)); -# else -_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count)); -# endif -_GL_CXXALIASWARN (read); -#elif @GNULIB_MDA_READ@ -/* On native Windows, map 'read' to '_read', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::read always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef read -# define read _read -# endif -# ifdef __MINGW32__ -_GL_CXXALIAS_MDA (read, int, (int fd, void *buf, unsigned int count)); -# else -_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, unsigned int count)); -# endif -# else -_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count)); -# endif -_GL_CXXALIASWARN (read); -#endif - - -#if @GNULIB_READLINK@ -/* Read the contents of the symbolic link FILE and place the first BUFSIZE - bytes of it into BUF. Return the number of bytes placed into BUF if - successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_READLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define readlink rpl_readlink -# endif -_GL_FUNCDECL_RPL (readlink, ssize_t, - (const char *restrict file, - char *restrict buf, size_t bufsize) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (readlink, ssize_t, - (const char *restrict file, - char *restrict buf, size_t bufsize)); -# else -# if !@HAVE_READLINK@ -_GL_FUNCDECL_SYS (readlink, ssize_t, - (const char *restrict file, - char *restrict buf, size_t bufsize) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (readlink, ssize_t, - (const char *restrict file, - char *restrict buf, size_t bufsize)); -# endif -_GL_CXXALIASWARN (readlink); -#elif defined GNULIB_POSIXCHECK -# undef readlink -# if HAVE_RAW_DECL_READLINK -_GL_WARN_ON_USE (readlink, "readlink is unportable - " - "use gnulib module readlink for portability"); -# endif -#endif - - -#if @GNULIB_READLINKAT@ -# if @REPLACE_READLINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define readlinkat rpl_readlinkat -# endif -_GL_FUNCDECL_RPL (readlinkat, ssize_t, - (int fd, char const *restrict file, - char *restrict buf, size_t len) - _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_RPL (readlinkat, ssize_t, - (int fd, char const *restrict file, - char *restrict buf, size_t len)); -# else -# if !@HAVE_READLINKAT@ -_GL_FUNCDECL_SYS (readlinkat, ssize_t, - (int fd, char const *restrict file, - char *restrict buf, size_t len) - _GL_ARG_NONNULL ((2, 3))); -# endif -_GL_CXXALIAS_SYS (readlinkat, ssize_t, - (int fd, char const *restrict file, - char *restrict buf, size_t len)); -# endif -_GL_CXXALIASWARN (readlinkat); -#elif defined GNULIB_POSIXCHECK -# undef readlinkat -# if HAVE_RAW_DECL_READLINKAT -_GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " - "use gnulib module readlinkat for portability"); -# endif -#endif - - -#if @GNULIB_RMDIR@ -/* Remove the directory DIR. */ -# if @REPLACE_RMDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define rmdir rpl_rmdir -# endif -_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (rmdir, int, (char const *name)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef rmdir -# define rmdir _rmdir -# endif -_GL_CXXALIAS_MDA (rmdir, int, (char const *name)); -# else -_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); -# endif -_GL_CXXALIASWARN (rmdir); -#elif defined GNULIB_POSIXCHECK -# undef rmdir -# if HAVE_RAW_DECL_RMDIR -_GL_WARN_ON_USE (rmdir, "rmdir is unportable - " - "use gnulib module rmdir for portability"); -# endif -#elif @GNULIB_MDA_RMDIR@ -/* On native Windows, map 'rmdir' to '_rmdir', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::rmdir always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef rmdir -# define rmdir _rmdir -# endif -_GL_CXXALIAS_MDA (rmdir, int, (char const *name)); -# else -_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); -# endif -_GL_CXXALIASWARN (rmdir); -#endif - - -#if @GNULIB_SETHOSTNAME@ -/* Set the host name of the machine. - The host name may or may not be fully qualified. - - Put LEN bytes of NAME into the host name. - Return 0 if successful, otherwise, set errno and return -1. - - Platforms with no ability to set the hostname return -1 and set - errno = ENOSYS. */ -# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@ -_GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5 - and FreeBSD 6.4 the second parameter is int. On Solaris 11 - 2011-10, the first parameter is not const. */ -_GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len)); -_GL_CXXALIASWARN (sethostname); -#elif defined GNULIB_POSIXCHECK -# undef sethostname -# if HAVE_RAW_DECL_SETHOSTNAME -_GL_WARN_ON_USE (sethostname, "sethostname is unportable - " - "use gnulib module sethostname for portability"); -# endif -#endif - - -#if @GNULIB_SLEEP@ -/* Pause the execution of the current thread for N seconds. - Returns the number of seconds left to sleep. - See the POSIX:2008 specification - . */ -# if @REPLACE_SLEEP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef sleep -# define sleep rpl_sleep -# endif -_GL_FUNCDECL_RPL (sleep, unsigned int, (unsigned int n)); -_GL_CXXALIAS_RPL (sleep, unsigned int, (unsigned int n)); -# else -# if !@HAVE_SLEEP@ -_GL_FUNCDECL_SYS (sleep, unsigned int, (unsigned int n)); -# endif -_GL_CXXALIAS_SYS (sleep, unsigned int, (unsigned int n)); -# endif -_GL_CXXALIASWARN (sleep); -#elif defined GNULIB_POSIXCHECK -# undef sleep -# if HAVE_RAW_DECL_SLEEP -_GL_WARN_ON_USE (sleep, "sleep is unportable - " - "use gnulib module sleep for portability"); -# endif -#endif - - -#if @GNULIB_MDA_SWAB@ -/* On native Windows, map 'swab' to '_swab', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::swab always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef swab -# define swab _swab -# endif -/* Need to cast, because in old mingw the arguments are - (const char *from, char *to, size_t n). */ -_GL_CXXALIAS_MDA_CAST (swab, void, (char *from, char *to, int n)); -# else -# if defined __hpux /* HP-UX */ -_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, int n)); -# elif defined __sun && (defined __SunOS_5_10 || defined __XOPEN_OR_POSIX) && !defined _XPG4 /* Solaris */ -_GL_CXXALIAS_SYS (swab, void, (const char *from, char *to, ssize_t n)); -# else -_GL_CXXALIAS_SYS (swab, void, (const void *from, void *to, ssize_t n)); -# endif -# endif -_GL_CXXALIASWARN (swab); -#endif - - -#if @GNULIB_SYMLINK@ -# if @REPLACE_SYMLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef symlink -# define symlink rpl_symlink -# endif -_GL_FUNCDECL_RPL (symlink, int, (char const *contents, char const *file) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (symlink, int, (char const *contents, char const *file)); -# else -# if !@HAVE_SYMLINK@ -_GL_FUNCDECL_SYS (symlink, int, (char const *contents, char const *file) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (symlink, int, (char const *contents, char const *file)); -# endif -_GL_CXXALIASWARN (symlink); -#elif defined GNULIB_POSIXCHECK -# undef symlink -# if HAVE_RAW_DECL_SYMLINK -_GL_WARN_ON_USE (symlink, "symlink is not portable - " - "use gnulib module symlink for portability"); -# endif -#endif - - -#if @GNULIB_SYMLINKAT@ -# if @REPLACE_SYMLINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef symlinkat -# define symlinkat rpl_symlinkat -# endif -_GL_FUNCDECL_RPL (symlinkat, int, - (char const *contents, int fd, char const *file) - _GL_ARG_NONNULL ((1, 3))); -_GL_CXXALIAS_RPL (symlinkat, int, - (char const *contents, int fd, char const *file)); -# else -# if !@HAVE_SYMLINKAT@ -_GL_FUNCDECL_SYS (symlinkat, int, - (char const *contents, int fd, char const *file) - _GL_ARG_NONNULL ((1, 3))); -# endif -_GL_CXXALIAS_SYS (symlinkat, int, - (char const *contents, int fd, char const *file)); -# endif -_GL_CXXALIASWARN (symlinkat); -#elif defined GNULIB_POSIXCHECK -# undef symlinkat -# if HAVE_RAW_DECL_SYMLINKAT -_GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " - "use gnulib module symlinkat for portability"); -# endif -#endif - - -#if @GNULIB_TRUNCATE@ -/* Change the size of the file designated by FILENAME to become equal to LENGTH. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2008 specification - . */ -# if @REPLACE_TRUNCATE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef truncate -# define truncate rpl_truncate -# endif -_GL_FUNCDECL_RPL (truncate, int, (const char *filename, off_t length) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (truncate, int, (const char *filename, off_t length)); -# else -# if !@HAVE_DECL_TRUNCATE@ -_GL_FUNCDECL_SYS (truncate, int, (const char *filename, off_t length) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (truncate, int, (const char *filename, off_t length)); -# endif -_GL_CXXALIASWARN (truncate); -#elif defined GNULIB_POSIXCHECK -# undef truncate -# if HAVE_RAW_DECL_TRUNCATE -_GL_WARN_ON_USE (truncate, "truncate is unportable - " - "use gnulib module truncate for portability"); -# endif -#endif - - -#if @GNULIB_TTYNAME_R@ -/* Store at most BUFLEN characters of the pathname of the terminal FD is - open on in BUF. Return 0 on success, otherwise an error number. */ -# if @REPLACE_TTYNAME_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef ttyname_r -# define ttyname_r rpl_ttyname_r -# endif -_GL_FUNCDECL_RPL (ttyname_r, int, - (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (ttyname_r, int, - (int fd, char *buf, size_t buflen)); -# else -# if !@HAVE_DECL_TTYNAME_R@ -_GL_FUNCDECL_SYS (ttyname_r, int, - (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (ttyname_r, int, - (int fd, char *buf, size_t buflen)); -# endif -_GL_CXXALIASWARN (ttyname_r); -#elif defined GNULIB_POSIXCHECK -# undef ttyname_r -# if HAVE_RAW_DECL_TTYNAME_R -_GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - " - "use gnulib module ttyname_r for portability"); -# endif -#endif - - -#if @GNULIB_UNLINK@ -# if @REPLACE_UNLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlink -# define unlink rpl_unlink -# endif -_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (unlink, int, (char const *file)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlink -# define unlink _unlink -# endif -_GL_CXXALIAS_MDA (unlink, int, (char const *file)); -# else -_GL_CXXALIAS_SYS (unlink, int, (char const *file)); -# endif -_GL_CXXALIASWARN (unlink); -#elif defined GNULIB_POSIXCHECK -# undef unlink -# if HAVE_RAW_DECL_UNLINK -_GL_WARN_ON_USE (unlink, "unlink is not portable - " - "use gnulib module unlink for portability"); -# endif -#elif @GNULIB_MDA_UNLINK@ -/* On native Windows, map 'unlink' to '_unlink', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::unlink always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlink -# define unlink _unlink -# endif -_GL_CXXALIAS_MDA (unlink, int, (char const *file)); -# else -_GL_CXXALIAS_SYS (unlink, int, (char const *file)); -# endif -_GL_CXXALIASWARN (unlink); -#endif - - -#if @GNULIB_UNLINKAT@ -# if @REPLACE_UNLINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlinkat -# define unlinkat rpl_unlinkat -# endif -_GL_FUNCDECL_RPL (unlinkat, int, (int fd, char const *file, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (unlinkat, int, (int fd, char const *file, int flag)); -# else -# if !@HAVE_UNLINKAT@ -_GL_FUNCDECL_SYS (unlinkat, int, (int fd, char const *file, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (unlinkat, int, (int fd, char const *file, int flag)); -# endif -_GL_CXXALIASWARN (unlinkat); -#elif defined GNULIB_POSIXCHECK -# undef unlinkat -# if HAVE_RAW_DECL_UNLINKAT -_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " - "use gnulib module unlinkat for portability"); -# endif -#endif - - -#if @GNULIB_USLEEP@ -/* Pause the execution of the current thread for N microseconds. - Returns 0 on completion, or -1 on range error. - See the POSIX:2001 specification - . */ -# if @REPLACE_USLEEP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef usleep -# define usleep rpl_usleep -# endif -_GL_FUNCDECL_RPL (usleep, int, (useconds_t n)); -_GL_CXXALIAS_RPL (usleep, int, (useconds_t n)); -# else -# if !@HAVE_USLEEP@ -_GL_FUNCDECL_SYS (usleep, int, (useconds_t n)); -# endif -/* Need to cast, because on Haiku, the first parameter is - unsigned int n. */ -_GL_CXXALIAS_SYS_CAST (usleep, int, (useconds_t n)); -# endif -_GL_CXXALIASWARN (usleep); -#elif defined GNULIB_POSIXCHECK -# undef usleep -# if HAVE_RAW_DECL_USLEEP -_GL_WARN_ON_USE (usleep, "usleep is unportable - " - "use gnulib module usleep for portability"); -# endif -#endif - - -#if @GNULIB_WRITE@ -/* Write up to COUNT bytes starting at BUF to file descriptor FD. - See the POSIX:2008 specification - . */ -# if @REPLACE_WRITE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef write -# define write rpl_write -# endif -_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); -# elif defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef write -# define write _write -# endif -_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, size_t count)); -# else -_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count)); -# endif -_GL_CXXALIASWARN (write); -#elif @GNULIB_MDA_WRITE@ -/* On native Windows, map 'write' to '_write', so that -loldnames is not - required. In C++ with GNULIB_NAMESPACE, avoid differences between - platforms by defining GNULIB_NAMESPACE::write always. */ -# if defined _WIN32 && !defined __CYGWIN__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef write -# define write _write -# endif -# ifdef __MINGW32__ -_GL_CXXALIAS_MDA (write, int, (int fd, const void *buf, unsigned int count)); -# else -_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, unsigned int count)); -# endif -# else -_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count)); -# endif -_GL_CXXALIASWARN (write); -#endif - -_GL_INLINE_HEADER_END - -#endif /* _@GUARD_PREFIX@_UNISTD_H */ -#endif /* _GL_INCLUDING_UNISTD_H */ -#endif /* _@GUARD_PREFIX@_UNISTD_H */ diff --git a/xcompile/lib/unlocked-io.h b/xcompile/lib/unlocked-io.h deleted file mode 100644 index fdef624ab9c..00000000000 --- a/xcompile/lib/unlocked-io.h +++ /dev/null @@ -1,136 +0,0 @@ -/* Prefer faster, non-thread-safe stdio functions if available. - - Copyright (C) 2001-2004, 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* Written by Jim Meyering. */ - -#ifndef UNLOCKED_IO_H -# define UNLOCKED_IO_H 1 - -/* These are wrappers for functions/macros from the GNU C library, and - from other C libraries supporting POSIX's optional thread-safe functions. - - The standard I/O functions are thread-safe. These *_unlocked ones are - more efficient but not thread-safe. That they're not thread-safe is - fine since all of the applications in this package are single threaded. - - Also, some code that is shared with the GNU C library may invoke - the *_unlocked functions directly. On hosts that lack those - functions, invoke the non-thread-safe versions instead. */ - -# include - -# if HAVE_DECL_CLEARERR_UNLOCKED || defined clearerr_unlocked -# undef clearerr -# define clearerr(x) clearerr_unlocked (x) -# else -# define clearerr_unlocked(x) clearerr (x) -# endif - -# if HAVE_DECL_FEOF_UNLOCKED || defined feof_unlocked -# undef feof -# define feof(x) feof_unlocked (x) -# else -# define feof_unlocked(x) feof (x) -# endif - -# if HAVE_DECL_FERROR_UNLOCKED || defined ferror_unlocked -# undef ferror -# define ferror(x) ferror_unlocked (x) -# else -# define ferror_unlocked(x) ferror (x) -# endif - -# if HAVE_DECL_FFLUSH_UNLOCKED || defined fflush_unlocked -# undef fflush -# define fflush(x) fflush_unlocked (x) -# else -# define fflush_unlocked(x) fflush (x) -# endif - -# if HAVE_DECL_FGETS_UNLOCKED || defined fgets_unlocked -# undef fgets -# define fgets(x,y,z) fgets_unlocked (x,y,z) -# else -# define fgets_unlocked(x,y,z) fgets (x,y,z) -# endif - -# if HAVE_DECL_FPUTC_UNLOCKED || defined fputc_unlocked -# undef fputc -# define fputc(x,y) fputc_unlocked (x,y) -# else -# define fputc_unlocked(x,y) fputc (x,y) -# endif - -# if HAVE_DECL_FPUTS_UNLOCKED || defined fputs_unlocked -# undef fputs -# define fputs(x,y) fputs_unlocked (x,y) -# else -# define fputs_unlocked(x,y) fputs (x,y) -# endif - -# if HAVE_DECL_FREAD_UNLOCKED || defined fread_unlocked -# undef fread -# define fread(w,x,y,z) fread_unlocked (w,x,y,z) -# else -# define fread_unlocked(w,x,y,z) fread (w,x,y,z) -# endif - -# if HAVE_DECL_FWRITE_UNLOCKED || defined fwrite_unlocked -# undef fwrite -# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z) -# else -# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) -# endif - -# if HAVE_DECL_GETC_UNLOCKED || defined get_unlocked -# undef getc -# define getc(x) getc_unlocked (x) -# else -# define getc_unlocked(x) getc (x) -# endif - -# if HAVE_DECL_GETCHAR_UNLOCKED || defined getchar_unlocked -# undef getchar -# define getchar() getchar_unlocked () -# else -# define getchar_unlocked() getchar () -# endif - -# if HAVE_DECL_PUTC_UNLOCKED || defined putc_unlocked -# undef putc -# define putc(x,y) putc_unlocked (x,y) -# else -# define putc_unlocked(x,y) putc (x,y) -# endif - -# if HAVE_DECL_PUTCHAR_UNLOCKED || defined putchar_unlocked -# undef putchar -# define putchar(x) putchar_unlocked (x) -# else -# define putchar_unlocked(x) putchar (x) -# endif - -# undef flockfile -# define flockfile(x) ((void) 0) - -# undef ftrylockfile -# define ftrylockfile(x) 0 - -# undef funlockfile -# define funlockfile(x) ((void) 0) - -#endif /* UNLOCKED_IO_H */ diff --git a/xcompile/lib/utimens.c b/xcompile/lib/utimens.c deleted file mode 100644 index 4c5377eca0f..00000000000 --- a/xcompile/lib/utimens.c +++ /dev/null @@ -1,646 +0,0 @@ -/* Set file access and modification times. - - Copyright (C) 2003-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -/* derived from a function in touch.c */ - -#include - -#define _GL_UTIMENS_INLINE _GL_EXTERN_INLINE -#include "utimens.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "stat-time.h" -#include "timespec.h" - -/* On native Windows, use SetFileTime; but avoid this when compiling - GNU Emacs, which arranges for this in some other way and which - defines WIN32_LEAN_AND_MEAN itself. */ - -#if defined _WIN32 && ! defined __CYGWIN__ && ! defined EMACS_CONFIGURATION -# define USE_SETFILETIME -# define WIN32_LEAN_AND_MEAN -# include -# if GNULIB_MSVC_NOTHROW -# include "msvc-nothrow.h" -# else -# include -# endif -#endif - -/* Avoid recursion with rpl_futimens or rpl_utimensat. */ -#undef futimens -#if !HAVE_NEARLY_WORKING_UTIMENSAT -# undef utimensat -#endif - -/* Solaris 9 mistakenly succeeds when given a non-directory with a - trailing slash. Force the use of rpl_stat for a fix. */ -#ifndef REPLACE_FUNC_STAT_FILE -# define REPLACE_FUNC_STAT_FILE 0 -#endif - -#if HAVE_UTIMENSAT || HAVE_FUTIMENS -/* Cache variables for whether the utimensat syscall works; used to - avoid calling the syscall if we know it will just fail with ENOSYS, - and to avoid unnecessary work in massaging timestamps if the - syscall will work. Multiple variables are needed, to distinguish - between the following scenarios on Linux: - utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS - kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW - kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec - kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT - utimensat completely works - For each cache variable: 0 = unknown, 1 = yes, -1 = no. */ -static int utimensat_works_really; -static int lutimensat_works_really; -#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ - -/* Validate the requested timestamps. Return 0 if the resulting - timespec can be used for utimensat (after possibly modifying it to - work around bugs in utimensat). Return a positive value if the - timespec needs further adjustment based on stat results: 1 if any - adjustment is needed for utimes, and 2 if any adjustment is needed - for Linux utimensat. Return -1, with errno set to EINVAL, if - timespec is out of range. */ -static int -validate_timespec (struct timespec timespec[2]) -{ - int result = 0; - int utime_omit_count = 0; - if ((timespec[0].tv_nsec != UTIME_NOW - && timespec[0].tv_nsec != UTIME_OMIT - && ! (0 <= timespec[0].tv_nsec - && timespec[0].tv_nsec < TIMESPEC_HZ)) - || (timespec[1].tv_nsec != UTIME_NOW - && timespec[1].tv_nsec != UTIME_OMIT - && ! (0 <= timespec[1].tv_nsec - && timespec[1].tv_nsec < TIMESPEC_HZ))) - { - errno = EINVAL; - return -1; - } - /* Work around Linux kernel 2.6.25 bug, where utimensat fails with - EINVAL if tv_sec is not 0 when using the flag values of tv_nsec. - Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT - fails to bump ctime. */ - if (timespec[0].tv_nsec == UTIME_NOW - || timespec[0].tv_nsec == UTIME_OMIT) - { - timespec[0].tv_sec = 0; - result = 1; - if (timespec[0].tv_nsec == UTIME_OMIT) - utime_omit_count++; - } - if (timespec[1].tv_nsec == UTIME_NOW - || timespec[1].tv_nsec == UTIME_OMIT) - { - timespec[1].tv_sec = 0; - result = 1; - if (timespec[1].tv_nsec == UTIME_OMIT) - utime_omit_count++; - } - return result + (utime_omit_count == 1); -} - -/* Normalize any UTIME_NOW or UTIME_OMIT values in (*TS)[0] and (*TS)[1], - using STATBUF to obtain the current timestamps of the file. If - both times are UTIME_NOW, set *TS to NULL (as this can avoid some - permissions issues). If both times are UTIME_OMIT, return true - (nothing further beyond the prior collection of STATBUF is - necessary); otherwise return false. */ -static bool -update_timespec (struct stat const *statbuf, struct timespec **ts) -{ - struct timespec *timespec = *ts; - if (timespec[0].tv_nsec == UTIME_OMIT - && timespec[1].tv_nsec == UTIME_OMIT) - return true; - if (timespec[0].tv_nsec == UTIME_NOW - && timespec[1].tv_nsec == UTIME_NOW) - { - *ts = NULL; - return false; - } - - if (timespec[0].tv_nsec == UTIME_OMIT) - timespec[0] = get_stat_atime (statbuf); - else if (timespec[0].tv_nsec == UTIME_NOW) - gettime (×pec[0]); - - if (timespec[1].tv_nsec == UTIME_OMIT) - timespec[1] = get_stat_mtime (statbuf); - else if (timespec[1].tv_nsec == UTIME_NOW) - gettime (×pec[1]); - - return false; -} - -/* Set the access and modification timestamps of FD (a.k.a. FILE) to be - TIMESPEC[0] and TIMESPEC[1], respectively. - FD must be either negative -- in which case it is ignored -- - or a file descriptor that is open on FILE. - If FD is nonnegative, then FILE can be NULL, which means - use just futimes (or equivalent) instead of utimes (or equivalent), - and fail if on an old system without futimes (or equivalent). - If TIMESPEC is null, set the timestamps to the current time. - Return 0 on success, -1 (setting errno) on failure. */ - -int -fdutimens (int fd, char const *file, struct timespec const timespec[2]) -{ - struct timespec adjusted_timespec[2]; - struct timespec *ts = timespec ? adjusted_timespec : NULL; - int adjustment_needed = 0; - struct stat st; - - if (ts) - { - adjusted_timespec[0] = timespec[0]; - adjusted_timespec[1] = timespec[1]; - adjustment_needed = validate_timespec (ts); - } - if (adjustment_needed < 0) - return -1; - - /* Require that at least one of FD or FILE are potentially valid, to avoid - a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather - than failing. */ - if (fd < 0 && !file) - { - errno = EBADF; - return -1; - } - - /* Some Linux-based NFS clients are buggy, and mishandle timestamps - of files in NFS file systems in some cases. We have no - configure-time test for this, but please see - for references to - some of the problems with Linux 2.6.16. If this affects you, - compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to - help in some cases, albeit at a cost in performance. But you - really should upgrade your kernel to a fixed version, since the - problem affects many applications. */ - -#if HAVE_BUGGY_NFS_TIME_STAMPS - if (fd < 0) - sync (); - else - fsync (fd); -#endif - - /* POSIX 2008 added two interfaces to set file timestamps with - nanosecond resolution; newer Linux implements both functions via - a single syscall. We provide a fallback for ENOSYS (for example, - compiling against Linux 2.6.25 kernel headers and glibc 2.7, but - running on Linux 2.6.18 kernel). */ -#if HAVE_UTIMENSAT || HAVE_FUTIMENS - if (0 <= utimensat_works_really) - { - int result; -# if __linux__ || __sun - /* As recently as Linux kernel 2.6.32 (Dec 2009), several file - systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, - but work if both times are either explicitly specified or - UTIME_NOW. Work around it with a preparatory [f]stat prior - to calling futimens/utimensat; fortunately, there is not much - timing impact due to the extra syscall even on file systems - where UTIME_OMIT would have worked. - - The same bug occurs in Solaris 11.1 (Apr 2013). - - FIXME: Simplify this for Linux in 2016 and for Solaris in - 2024, when file system bugs are no longer common. */ - if (adjustment_needed == 2) - { - if (fd < 0 ? stat (file, &st) : fstat (fd, &st)) - return -1; - if (ts[0].tv_nsec == UTIME_OMIT) - ts[0] = get_stat_atime (&st); - else if (ts[1].tv_nsec == UTIME_OMIT) - ts[1] = get_stat_mtime (&st); - /* Note that st is good, in case utimensat gives ENOSYS. */ - adjustment_needed++; - } -# endif -# if HAVE_UTIMENSAT - if (fd < 0) - { -# if defined __APPLE__ && defined __MACH__ - size_t len = strlen (file); - if (len > 0 && file[len - 1] == '/') - { - struct stat statbuf; - if (stat (file, &statbuf) < 0) - return -1; - if (!S_ISDIR (statbuf.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } -# endif - result = utimensat (AT_FDCWD, file, ts, 0); -# ifdef __linux__ - /* Work around a kernel bug: - https://bugzilla.redhat.com/show_bug.cgi?id=442352 - https://bugzilla.redhat.com/show_bug.cgi?id=449910 - It appears that utimensat can mistakenly return 280 rather - than -1 upon ENOSYS failure. - FIXME: remove in 2010 or whenever the offending kernels - are no longer in common use. */ - if (0 < result) - errno = ENOSYS; -# endif /* __linux__ */ - if (result == 0 || errno != ENOSYS) - { - utimensat_works_really = 1; - return result; - } - } -# endif /* HAVE_UTIMENSAT */ -# if HAVE_FUTIMENS - if (0 <= fd) - { - result = futimens (fd, ts); -# ifdef __linux__ - /* Work around the same bug as above. */ - if (0 < result) - errno = ENOSYS; -# endif /* __linux__ */ - if (result == 0 || errno != ENOSYS) - { - utimensat_works_really = 1; - return result; - } - } -# endif /* HAVE_FUTIMENS */ - } - utimensat_works_really = -1; - lutimensat_works_really = -1; -#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */ - -#ifdef USE_SETFILETIME - /* On native Windows, use SetFileTime(). See - - */ - if (0 <= fd) - { - HANDLE handle; - FILETIME current_time; - FILETIME last_access_time; - FILETIME last_write_time; - - handle = (HANDLE) _get_osfhandle (fd); - if (handle == INVALID_HANDLE_VALUE) - { - errno = EBADF; - return -1; - } - - if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW) - { - /* GetSystemTimeAsFileTime - . - It would be overkill to use - GetSystemTimePreciseAsFileTime - . */ - GetSystemTimeAsFileTime (¤t_time); - } - - if (ts == NULL || ts[0].tv_nsec == UTIME_NOW) - { - last_access_time = current_time; - } - else if (ts[0].tv_nsec == UTIME_OMIT) - { - last_access_time.dwLowDateTime = 0; - last_access_time.dwHighDateTime = 0; - } - else - { - ULONGLONG time_since_16010101 = - (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL; - last_access_time.dwLowDateTime = (DWORD) time_since_16010101; - last_access_time.dwHighDateTime = time_since_16010101 >> 32; - } - - if (ts == NULL || ts[1].tv_nsec == UTIME_NOW) - { - last_write_time = current_time; - } - else if (ts[1].tv_nsec == UTIME_OMIT) - { - last_write_time.dwLowDateTime = 0; - last_write_time.dwHighDateTime = 0; - } - else - { - ULONGLONG time_since_16010101 = - (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL; - last_write_time.dwLowDateTime = (DWORD) time_since_16010101; - last_write_time.dwHighDateTime = time_since_16010101 >> 32; - } - - if (SetFileTime (handle, NULL, &last_access_time, &last_write_time)) - return 0; - else - { - DWORD sft_error = GetLastError (); - #if 0 - fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error); - #endif - switch (sft_error) - { - case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */ - errno = EACCES; /* not specified by POSIX */ - break; - default: - errno = EINVAL; - break; - } - return -1; - } - } -#endif - - /* The platform lacks an interface to set file timestamps with - nanosecond resolution, so do the best we can, discarding any - fractional part of the timestamp. */ - - if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0)) - { - if (adjustment_needed != 3 - && (fd < 0 ? stat (file, &st) : fstat (fd, &st))) - return -1; - if (ts && update_timespec (&st, &ts)) - return 0; - } - - { -#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES - struct timeval timeval[2]; - struct timeval *t; - if (ts) - { - timeval[0].tv_sec = ts[0].tv_sec; - timeval[0].tv_usec = ts[0].tv_nsec / 1000; - timeval[1].tv_sec = ts[1].tv_sec; - timeval[1].tv_usec = ts[1].tv_nsec / 1000; - t = timeval; - } - else - t = NULL; - - if (fd < 0) - { -# if HAVE_FUTIMESAT - return futimesat (AT_FDCWD, file, t); -# endif - } - else - { - /* If futimesat or futimes fails here, don't try to speed things - up by returning right away. glibc can incorrectly fail with - errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0 - in high security mode doesn't allow ordinary users to read - /proc/self, so glibc incorrectly fails with errno == EACCES. - If errno == EIO, EPERM, or EROFS, it's probably safe to fail - right away, but these cases are rare enough that they're not - worth optimizing, and who knows what other messed-up systems - are out there? So play it safe and fall back on the code - below. */ - -# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES -# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG -# undef futimes -# define futimes(fd, t) futimesat (fd, NULL, t) -# endif - if (futimes (fd, t) == 0) - { -# if __linux__ && __GLIBC__ - /* Work around a longstanding glibc bug, still present as - of 2010-12-27. On older Linux kernels that lack both - utimensat and utimes, glibc's futimes rounds instead of - truncating when falling back on utime. The same bug - occurs in futimesat with a null 2nd arg. */ - if (t) - { - bool abig = 500000 <= t[0].tv_usec; - bool mbig = 500000 <= t[1].tv_usec; - if ((abig | mbig) && fstat (fd, &st) == 0) - { - /* If these two subtractions overflow, they'll - track the overflows inside the buggy glibc. */ - time_t adiff = st.st_atime - t[0].tv_sec; - time_t mdiff = st.st_mtime - t[1].tv_sec; - - struct timeval *tt = NULL; - struct timeval truncated_timeval[2]; - truncated_timeval[0] = t[0]; - truncated_timeval[1] = t[1]; - if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0) - { - tt = truncated_timeval; - tt[0].tv_usec = 0; - } - if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0) - { - tt = truncated_timeval; - tt[1].tv_usec = 0; - } - if (tt) - futimes (fd, tt); - } - } -# endif - - return 0; - } -# endif - } -#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */ - - if (!file) - { -#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \ - || (HAVE_WORKING_UTIMES && HAVE_FUTIMES)) - errno = ENOSYS; -#endif - return -1; - } - -#ifdef USE_SETFILETIME - return _gl_utimens_windows (file, ts); -#elif HAVE_WORKING_UTIMES - return utimes (file, t); -#else - { - struct utimbuf utimbuf; - struct utimbuf *ut; - if (ts) - { - utimbuf.actime = ts[0].tv_sec; - utimbuf.modtime = ts[1].tv_sec; - ut = &utimbuf; - } - else - ut = NULL; - - return utime (file, ut); - } -#endif /* !HAVE_WORKING_UTIMES */ - } -} - -/* Set the access and modification timestamps of FILE to be - TIMESPEC[0] and TIMESPEC[1], respectively. */ -int -utimens (char const *file, struct timespec const timespec[2]) -{ - return fdutimens (-1, file, timespec); -} - -/* Set the access and modification timestamps of FILE to be - TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing - symlinks. Fail with ENOSYS if the platform does not support - changing symlink timestamps, but FILE was a symlink. */ -int -lutimens (char const *file, struct timespec const timespec[2]) -{ - struct timespec adjusted_timespec[2]; - struct timespec *ts = timespec ? adjusted_timespec : NULL; - int adjustment_needed = 0; - struct stat st; - - if (ts) - { - adjusted_timespec[0] = timespec[0]; - adjusted_timespec[1] = timespec[1]; - adjustment_needed = validate_timespec (ts); - } - if (adjustment_needed < 0) - return -1; - - /* The Linux kernel did not support symlink timestamps until - utimensat, in version 2.6.22, so we don't need to mimic - fdutimens' worry about buggy NFS clients. But we do have to - worry about bogus return values. */ - -#if HAVE_UTIMENSAT - if (0 <= lutimensat_works_really) - { - int result; -# if __linux__ || __sun - /* As recently as Linux kernel 2.6.32 (Dec 2009), several file - systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, - but work if both times are either explicitly specified or - UTIME_NOW. Work around it with a preparatory lstat prior to - calling utimensat; fortunately, there is not much timing - impact due to the extra syscall even on file systems where - UTIME_OMIT would have worked. - - The same bug occurs in Solaris 11.1 (Apr 2013). - - FIXME: Simplify this for Linux in 2016 and for Solaris in - 2024, when file system bugs are no longer common. */ - if (adjustment_needed == 2) - { - if (lstat (file, &st)) - return -1; - if (ts[0].tv_nsec == UTIME_OMIT) - ts[0] = get_stat_atime (&st); - else if (ts[1].tv_nsec == UTIME_OMIT) - ts[1] = get_stat_mtime (&st); - /* Note that st is good, in case utimensat gives ENOSYS. */ - adjustment_needed++; - } -# endif - result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW); -# ifdef __linux__ - /* Work around a kernel bug: - https://bugzilla.redhat.com/show_bug.cgi?id=442352 - https://bugzilla.redhat.com/show_bug.cgi?id=449910 - It appears that utimensat can mistakenly return 280 rather - than -1 upon ENOSYS failure. - FIXME: remove in 2010 or whenever the offending kernels - are no longer in common use. */ - if (0 < result) - errno = ENOSYS; -# endif - if (result == 0 || errno != ENOSYS) - { - utimensat_works_really = 1; - lutimensat_works_really = 1; - return result; - } - } - lutimensat_works_really = -1; -#endif /* HAVE_UTIMENSAT */ - - /* The platform lacks an interface to set file timestamps with - nanosecond resolution, so do the best we can, discarding any - fractional part of the timestamp. */ - - if (adjustment_needed || REPLACE_FUNC_STAT_FILE) - { - if (adjustment_needed != 3 && lstat (file, &st)) - return -1; - if (ts && update_timespec (&st, &ts)) - return 0; - } - - /* On Linux, lutimes is a thin wrapper around utimensat, so there is - no point trying lutimes if utimensat failed with ENOSYS. */ -#if HAVE_LUTIMES && !HAVE_UTIMENSAT - { - struct timeval timeval[2]; - struct timeval *t; - int result; - if (ts) - { - timeval[0].tv_sec = ts[0].tv_sec; - timeval[0].tv_usec = ts[0].tv_nsec / 1000; - timeval[1].tv_sec = ts[1].tv_sec; - timeval[1].tv_usec = ts[1].tv_nsec / 1000; - t = timeval; - } - else - t = NULL; - - result = lutimes (file, t); - if (result == 0 || errno != ENOSYS) - return result; - } -#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */ - - /* Out of luck for symlinks, but we still handle regular files. */ - if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st)) - return -1; - if (!S_ISLNK (st.st_mode)) - return fdutimens (-1, file, ts); - errno = ENOSYS; - return -1; -} diff --git a/xcompile/lib/utimens.h b/xcompile/lib/utimens.h deleted file mode 100644 index a7056981f32..00000000000 --- a/xcompile/lib/utimens.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Set file access and modification times. - - Copyright 2012-2023 Free Software Foundation, Inc. - - This file 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 3 of the - License, or (at your option) any later version. - - This file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert. */ - -#include -int fdutimens (int, char const *, struct timespec const [2]); -int utimens (char const *, struct timespec const [2]); -int lutimens (char const *, struct timespec const [2]); - -#if GNULIB_FDUTIMENSAT -# include -# include - -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." -#endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GL_UTIMENS_INLINE -# define _GL_UTIMENS_INLINE _GL_INLINE -#endif - -int fdutimensat (int fd, int dir, char const *name, struct timespec const [2], - int atflag); - -/* Using this function makes application code slightly more readable. */ -_GL_UTIMENS_INLINE int -lutimensat (int dir, char const *file, struct timespec const times[2]) -{ - return utimensat (dir, file, times, AT_SYMLINK_NOFOLLOW); -} - -_GL_INLINE_HEADER_END - -#endif diff --git a/xcompile/lib/utimensat.c b/xcompile/lib/utimensat.c deleted file mode 100644 index 5cff11cd0a9..00000000000 --- a/xcompile/lib/utimensat.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Set the access and modification time of a file relative to directory fd. - Copyright (C) 2009-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . */ - -/* written by Eric Blake */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include -#include - -#include "stat-time.h" -#include "timespec.h" -#include "utimens.h" - -#if HAVE_NEARLY_WORKING_UTIMENSAT - -/* Use the original utimensat(), but correct the trailing slash handling. */ -int -rpl_utimensat (int fd, char const *file, struct timespec const times[2], - int flag) -# undef utimensat -{ - size_t len = strlen (file); - if (len && file[len - 1] == '/') - { - struct stat st; - if (fstatat (fd, file, &st, flag & AT_SYMLINK_NOFOLLOW) < 0) - return -1; - if (!S_ISDIR (st.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } - - return utimensat (fd, file, times, flag); -} - -#else - -# if HAVE_UTIMENSAT - -/* If we have a native utimensat, but are compiling this file, then - utimensat was defined to rpl_utimensat by our replacement - sys/stat.h. We assume the native version might fail with ENOSYS, - or succeed without properly affecting ctime (as is the case when - using newer glibc but older Linux kernel). In this scenario, - rpl_utimensat checks whether the native version is usable, and - local_utimensat provides the fallback manipulation. */ - -static int local_utimensat (int, char const *, struct timespec const[2], int); -# define AT_FUNC_NAME local_utimensat - -/* Like utimensat, but work around native bugs. */ - -int -rpl_utimensat (int fd, char const *file, struct timespec const times[2], - int flag) -# undef utimensat -{ -# if defined __linux__ || defined __sun - struct timespec ts[2]; -# endif - - /* See comments in utimens.c for details. */ - static int utimensat_works_really; /* 0 = unknown, 1 = yes, -1 = no. */ - if (0 <= utimensat_works_really) - { - int result; -# if defined __linux__ || defined __sun - struct stat st; - /* As recently as Linux kernel 2.6.32 (Dec 2009), several file - systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT, - but work if both times are either explicitly specified or - UTIME_NOW. Work around it with a preparatory [l]stat prior - to calling utimensat; fortunately, there is not much timing - impact due to the extra syscall even on file systems where - UTIME_OMIT would have worked. - - The same bug occurs in Solaris 11.1 (Apr 2013). - - FIXME: Simplify this in 2024, when these file system bugs are - no longer common on Gnulib target platforms. */ - if (times && (times[0].tv_nsec == UTIME_OMIT - || times[1].tv_nsec == UTIME_OMIT)) - { - if (fstatat (fd, file, &st, flag)) - return -1; - if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) - return 0; - if (times[0].tv_nsec == UTIME_OMIT) - ts[0] = get_stat_atime (&st); - else - ts[0] = times[0]; - if (times[1].tv_nsec == UTIME_OMIT) - ts[1] = get_stat_mtime (&st); - else - ts[1] = times[1]; - times = ts; - } -# ifdef __hppa__ - /* Linux kernel 2.6.22.19 on hppa does not reject invalid tv_nsec - values. */ - else if (times - && ((times[0].tv_nsec != UTIME_NOW - && ! (0 <= times[0].tv_nsec - && times[0].tv_nsec < TIMESPEC_HZ)) - || (times[1].tv_nsec != UTIME_NOW - && ! (0 <= times[1].tv_nsec - && times[1].tv_nsec < TIMESPEC_HZ)))) - { - errno = EINVAL; - return -1; - } -# endif -# endif -# if defined __APPLE__ && defined __MACH__ - /* macOS 10.13 does not reject invalid tv_nsec values either. */ - if (times - && ((times[0].tv_nsec != UTIME_OMIT - && times[0].tv_nsec != UTIME_NOW - && ! (0 <= times[0].tv_nsec - && times[0].tv_nsec < TIMESPEC_HZ)) - || (times[1].tv_nsec != UTIME_OMIT - && times[1].tv_nsec != UTIME_NOW - && ! (0 <= times[1].tv_nsec - && times[1].tv_nsec < TIMESPEC_HZ)))) - { - errno = EINVAL; - return -1; - } - size_t len = strlen (file); - if (len > 0 && file[len - 1] == '/') - { - struct stat statbuf; - if (fstatat (fd, file, &statbuf, 0) < 0) - return -1; - if (!S_ISDIR (statbuf.st_mode)) - { - errno = ENOTDIR; - return -1; - } - } -# endif - result = utimensat (fd, file, times, flag); - /* Linux kernel 2.6.25 has a bug where it returns EINVAL for - UTIME_NOW or UTIME_OMIT with non-zero tv_sec, which - local_utimensat works around. Meanwhile, EINVAL for a bad - flag is indeterminate whether the native utimensat works, but - local_utimensat will also reject it. */ - if (result == -1 && errno == EINVAL && (flag & ~AT_SYMLINK_NOFOLLOW)) - return result; - if (result == 0 || (errno != ENOSYS && errno != EINVAL)) - { - utimensat_works_really = 1; - return result; - } - } - /* No point in trying openat/futimens, since on Linux, futimens is - implemented with the same syscall as utimensat. Only avoid the - native utimensat due to an ENOSYS failure; an EINVAL error was - data-dependent, and the next caller may pass valid data. */ - if (0 <= utimensat_works_really && errno == ENOSYS) - utimensat_works_really = -1; - return local_utimensat (fd, file, times, flag); -} - -# else /* !HAVE_UTIMENSAT */ - -# define AT_FUNC_NAME utimensat - -# endif /* !HAVE_UTIMENSAT */ - -/* Set the access and modification timestamps of FILE to be - TIMESPEC[0] and TIMESPEC[1], respectively; relative to directory - FD. If flag is AT_SYMLINK_NOFOLLOW, change the times of a symlink, - or fail with ENOSYS if not possible. If TIMESPEC is null, set the - timestamps to the current time. If possible, do it without - changing the working directory. Otherwise, resort to using - save_cwd/fchdir, then utimens/restore_cwd. If either the save_cwd - or the restore_cwd fails, then give a diagnostic and exit nonzero. - Return 0 on success, -1 (setting errno) on failure. */ - -/* AT_FUNC_NAME is now utimensat or local_utimensat. */ -# define AT_FUNC_F1 lutimens -# define AT_FUNC_F2 utimens -# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW -# define AT_FUNC_POST_FILE_PARAM_DECLS , struct timespec const ts[2], int flag -# define AT_FUNC_POST_FILE_ARGS , ts -# include "at-func.c" -# undef AT_FUNC_NAME -# undef AT_FUNC_F1 -# undef AT_FUNC_F2 -# undef AT_FUNC_USE_F1_COND -# undef AT_FUNC_POST_FILE_PARAM_DECLS -# undef AT_FUNC_POST_FILE_ARGS - -#endif /* !HAVE_NEARLY_WORKING_UTIMENSAT */ diff --git a/xcompile/lib/verify.h b/xcompile/lib/verify.h deleted file mode 100644 index b63cb264321..00000000000 --- a/xcompile/lib/verify.h +++ /dev/null @@ -1,350 +0,0 @@ -/* Compile-time assert-like macros. - - Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ - -#ifndef _GL_VERIFY_H -#define _GL_VERIFY_H - - -/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC) - works as per C11. This is supported by GCC 4.6.0+ and by clang 4+. - - Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as - per C23. This is supported by GCC 9.1+. - - Support compilers claiming conformance to the relevant standard, - and also support GCC when not pedantic. If we were willing to slow - 'configure' down we could also use it with other compilers, but - since this affects only the quality of diagnostics, why bother? */ -#ifndef __cplusplus -# if (201112 <= __STDC_VERSION__ \ - || (!defined __STRICT_ANSI__ \ - && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__))) -# define _GL_HAVE__STATIC_ASSERT 1 -# endif -# if (202311 <= __STDC_VERSION__ \ - || (!defined __STRICT_ANSI__ && 9 <= __GNUC__)) -# define _GL_HAVE__STATIC_ASSERT1 1 -# endif -#endif - -/* FreeBSD 9.1 , included by and lots of other - system headers, defines a conflicting _Static_assert that is no - better than ours; override it. */ -#ifndef _GL_HAVE__STATIC_ASSERT -# include -# undef _Static_assert -#endif - -/* Each of these macros verifies that its argument R is nonzero. To - be portable, R should be an integer constant expression. Unlike - assert (R), there is no run-time overhead. - - If _Static_assert works, verify (R) uses it directly. Similarly, - _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct - that is an operand of sizeof. - - The code below uses several ideas for C++ compilers, and for C - compilers that do not support _Static_assert: - - * The first step is ((R) ? 1 : -1). Given an expression R, of - integral or boolean or floating-point type, this yields an - expression of integral type, whose value is later verified to be - constant and nonnegative. - - * Next this expression W is wrapped in a type - struct _gl_verify_type { - unsigned int _gl_verify_error_if_negative: W; - }. - If W is negative, this yields a compile-time error. No compiler can - deal with a bit-field of negative size. - - One might think that an array size check would have the same - effect, that is, that the type struct { unsigned int dummy[W]; } - would work as well. However, inside a function, some compilers - (such as C++ compilers and GNU C) allow local parameters and - variables inside array size expressions. With these compilers, - an array size check would not properly diagnose this misuse of - the verify macro: - - void function (int n) { verify (n < 0); } - - * For the verify macro, the struct _gl_verify_type will need to - somehow be embedded into a declaration. To be portable, this - declaration must declare an object, a constant, a function, or a - typedef name. If the declared entity uses the type directly, - such as in - - struct dummy {...}; - typedef struct {...} dummy; - extern struct {...} *dummy; - extern void dummy (struct {...} *); - extern struct {...} *dummy (void); - - two uses of the verify macro would yield colliding declarations - if the entity names are not disambiguated. A workaround is to - attach the current line number to the entity name: - - #define _GL_CONCAT0(x, y) x##y - #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) - extern struct {...} * _GL_CONCAT (dummy, __LINE__); - - But this has the problem that two invocations of verify from - within the same macro would collide, since the __LINE__ value - would be the same for both invocations. (The GCC __COUNTER__ - macro solves this problem, but is not portable.) - - A solution is to use the sizeof operator. It yields a number, - getting rid of the identity of the type. Declarations like - - extern int dummy [sizeof (struct {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - - can be repeated. - - * Should the implementation use a named struct or an unnamed struct? - Which of the following alternatives can be used? - - extern int dummy [sizeof (struct {...})]; - extern int dummy [sizeof (struct _gl_verify_type {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern void dummy (int [sizeof (struct _gl_verify_type {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})]; - - In the second and sixth case, the struct type is exported to the - outer scope; two such declarations therefore collide. GCC warns - about the first, third, and fourth cases. So the only remaining - possibility is the fifth case: - - extern int (*dummy (void)) [sizeof (struct {...})]; - - * GCC warns about duplicate declarations of the dummy function if - -Wredundant-decls is used. GCC 4.3 and later have a builtin - __COUNTER__ macro that can let us generate unique identifiers for - each dummy function, to suppress this warning. - - * This implementation exploits the fact that older versions of GCC, - which do not support _Static_assert, also do not warn about the - last declaration mentioned above. - - * GCC warns if -Wnested-externs is enabled and 'verify' is used - within a function body; but inside a function, you can always - arrange to use verify_expr instead. - - * In C++, any struct definition inside sizeof is invalid. - Use a template type to work around the problem. */ - -/* Concatenate two preprocessor tokens. */ -#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) -#define _GL_CONCAT0(x, y) x##y - -/* _GL_COUNTER is an integer, preferably one that changes each time we - use it. Use __COUNTER__ if it works, falling back on __LINE__ - otherwise. __LINE__ isn't perfect, but it's better than a - constant. */ -#if defined __COUNTER__ && __COUNTER__ != __COUNTER__ -# define _GL_COUNTER __COUNTER__ -#else -# define _GL_COUNTER __LINE__ -#endif - -/* Generate a symbol with the given prefix, making it unique if - possible. */ -#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) - -/* Verify requirement R at compile-time, as an integer constant expression - that returns 1. If R is false, fail at compile-time, preferably - with a diagnostic that includes the string-literal DIAGNOSTIC. */ - -#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \ - (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC))) - -#ifdef __cplusplus -# if !GNULIB_defined_struct__gl_verify_type -template - struct _gl_verify_type { - unsigned int _gl_verify_error_if_negative: w; - }; -# define GNULIB_defined_struct__gl_verify_type 1 -# endif -# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ - _gl_verify_type<(R) ? 1 : -1> -#elif defined _GL_HAVE__STATIC_ASSERT -# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ - struct { \ - _Static_assert (R, DIAGNOSTIC); \ - int _gl_dummy; \ - } -#else -# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \ - struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; } -#endif - -/* Verify requirement R at compile-time, as a declaration without a - trailing ';'. If R is false, fail at compile-time. - - This macro requires three or more arguments but uses at most the first - two, so that the _Static_assert macro optionally defined below supports - both the C11 two-argument syntax and the C23 one-argument syntax. - - Unfortunately, unlike C11, this implementation must appear as an - ordinary declaration, and cannot appear inside struct { ... }. */ - -#if 202311 <= __STDC_VERSION__ || 200410 <= __cpp_static_assert -# define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC) -#elif defined _GL_HAVE__STATIC_ASSERT -# define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC) -#else -# define _GL_VERIFY(R, DIAGNOSTIC, ...) \ - extern int (*_GL_GENSYM (_gl_verify_function) (void)) \ - [_GL_VERIFY_TRUE (R, DIAGNOSTIC)] -# if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) -# pragma GCC diagnostic ignored "-Wnested-externs" -# endif -#endif - -/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */ -#ifdef _GL_STATIC_ASSERT_H -# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert -# if !defined _MSC_VER || defined __clang__ -# define _Static_assert(...) \ - _GL_VERIFY (__VA_ARGS__, "static assertion failed", -) -# else - /* Work around MSVC preprocessor incompatibility with ISO C; see - . */ -# define _Static_assert(R, ...) \ - _GL_VERIFY ((R), "static assertion failed", -) -# endif -# endif -# if (!defined static_assert \ - && __STDC_VERSION__ < 202311 \ - && (!defined __cplusplus \ - || (__cpp_static_assert < 201411 \ - && __GNUG__ < 6 && __clang_major__ < 6))) -# if defined __cplusplus && _MSC_VER >= 1900 && !defined __clang__ -/* MSVC 14 in C++ mode supports the two-arguments static_assert but not - the one-argument static_assert, and it does not support _Static_assert. - We have to play preprocessor tricks to distinguish the two cases. - Since the MSVC preprocessor is not ISO C compliant (see above),. - the solution is specific to MSVC. */ -# define _GL_EXPAND(x) x -# define _GL_SA1(a1) static_assert ((a1), "static assertion failed") -# define _GL_SA2 static_assert -# define _GL_SA3 static_assert -# define _GL_SA_PICK(x1,x2,x3,x4,...) x4 -# define static_assert(...) _GL_EXPAND(_GL_SA_PICK(__VA_ARGS__,_GL_SA3,_GL_SA2,_GL_SA1)) (__VA_ARGS__) -# else -# define static_assert _Static_assert /* C11 requires this #define. */ -# endif -# endif -#endif - -/* @assert.h omit start@ */ - -#if defined __clang_major__ && __clang_major__ < 5 -# define _GL_HAS_BUILTIN_TRAP 0 -#elif 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__)) -# define _GL_HAS_BUILTIN_TRAP 1 -#elif defined __has_builtin -# define _GL_HAS_BUILTIN_TRAP __has_builtin (__builtin_trap) -#else -# define _GL_HAS_BUILTIN_TRAP 0 -#endif - -#if defined __clang_major__ && __clang_major__ < 5 -# define _GL_HAS_BUILTIN_UNREACHABLE 0 -#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) -# define _GL_HAS_BUILTIN_UNREACHABLE 1 -#elif defined __has_builtin -# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) -#else -# define _GL_HAS_BUILTIN_UNREACHABLE 0 -#endif - -/* Each of these macros verifies that its argument R is nonzero. To - be portable, R should be an integer constant expression. Unlike - assert (R), there is no run-time overhead. - - There are two macros, since no single macro can be used in all - contexts in C. verify_expr (R, E) is for scalar contexts, including - integer constant expression contexts. verify (R) is for declaration - contexts, e.g., the top level. */ - -/* Verify requirement R at compile-time. Return the value of the - expression E. */ - -#define verify_expr(R, E) \ - (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E)) - -/* Verify requirement R at compile-time, as a declaration without a - trailing ';'. verify (R) acts like static_assert (R) except that - it is portable to C11/C++14 and earlier, it can issue better - diagnostics, and its name is shorter and may be more convenient. */ - -#ifdef __PGI -/* PGI barfs if R is long. */ -# define verify(R) _GL_VERIFY (R, "verify (...)", -) -#else -# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -) -#endif - -/* Assume that R always holds. Behavior is undefined if R is false, - fails to evaluate, or has side effects. - - 'assume (R)' is a directive from the programmer telling the - compiler that R is true so the compiler needn't generate code to - test R. This is why 'assume' is in verify.h: it's related to - static checking (in this case, static checking done by the - programmer), not dynamic checking. - - 'assume (R)' can affect compilation of all the code, not just code - that happens to be executed after the assume (R) is "executed". - For example, if the code mistakenly does 'assert (R); assume (R);' - the compiler is entitled to optimize away the 'assert (R)'. - - Although assuming R can help a compiler generate better code or - diagnostics, performance can suffer if R uses hard-to-optimize - features such as function calls not inlined by the compiler. - - Avoid Clang's __builtin_assume, as it breaks GNU Emacs master - as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see - . It's not known whether this breakage - is a Clang bug or an Emacs bug; play it safe for now. */ - -#if _GL_HAS_BUILTIN_UNREACHABLE -# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) -#elif 1200 <= _MSC_VER -# define assume(R) __assume (R) -#elif 202311 <= __STDC_VERSION__ -# include -# define assume(R) ((R) ? (void) 0 : unreachable ()) -#elif (defined GCC_LINT || defined lint) && _GL_HAS_BUILTIN_TRAP - /* Doing it this way helps various packages when configured with - --enable-gcc-warnings, which compiles with -Dlint. It's nicer - if 'assume' silences warnings with GCC 3.4 through GCC 4.4.7 (2012). */ -# define assume(R) ((R) ? (void) 0 : __builtin_trap ()) -#else - /* Some older tools grok NOTREACHED, e.g., Oracle Studio 12.6 (2017). */ -# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0) -#endif - -/* @assert.h omit end@ */ - -#endif diff --git a/xcompile/lib/vla.h b/xcompile/lib/vla.h deleted file mode 100644 index 55f112a060a..00000000000 --- a/xcompile/lib/vla.h +++ /dev/null @@ -1,53 +0,0 @@ -/* vla.h - variable length arrays - - Copyright 2014-2023 Free Software Foundation, Inc. - - This program is free software: you can 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 . - - Written by Paul Eggert. */ - -/* The VLA_ELEMS macro does not allocate variable-length arrays (VLAs), - so it does not have the security or performance issues commonly - associated with VLAs. VLA_ELEMS is for exploiting a C11 feature - where a function can start like this: - - double scan_array (int n, double v[static n]) - - to require a caller to pass a vector V with at least N elements; - this allows better static checking and performance in some cases. - In C11 this feature means that V is a VLA, so the feature is - supported only if __STDC_NO_VLA__ is defined, and for compatibility - to platforms that do not support VLAs, VLA_ELEMS (n) expands to - nothing when __STDC_NO_VLA__ is not defined. */ - -/* A function's argument must point to an array with at least N elements. - Example: 'int main (int argc, char *argv[VLA_ELEMS (argc)]);'. */ - -#ifdef __STDC_NO_VLA__ -# define VLA_ELEMS(n) -#else -# define VLA_ELEMS(n) static n -#endif - -/* Although C99 requires support for variable-length arrays (VLAs), - some C compilers never supported VLAs and VLAs are optional in C11. - VLAs are controversial because their allocation may be unintended - or awkward to support, and large VLAs might cause security or - performance problems. GCC can diagnose the use of VLAs via the - -Wvla and -Wvla-larger-than warnings options, and defining the - macro GNULIB_NO_VLA disables the allocation of VLAs in Gnulib code. - - The VLA_ELEMS macro is unaffected by GNULIB_NO_VLA, since it does - not allocate VLAs. Programs that use VLA_ELEMS should be compiled - with 'gcc -Wvla-larger-than' instead of with 'gcc -Wvla'. */ diff --git a/xcompile/lib/warn-on-use.h b/xcompile/lib/warn-on-use.h deleted file mode 100644 index 30756034aff..00000000000 --- a/xcompile/lib/warn-on-use.h +++ /dev/null @@ -1,149 +0,0 @@ -/* A C macro for emitting warnings if a function is used. - Copyright (C) 2010-2023 Free Software Foundation, Inc. - - This program 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that 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 program. If not, see . */ - -/* _GL_WARN_ON_USE (function, "literal string") issues a declaration - for FUNCTION which will then trigger a compiler warning containing - the text of "literal string" anywhere that function is called, if - supported by the compiler. If the compiler does not support this - feature, the macro expands to an unused extern declaration. - - _GL_WARN_ON_USE_ATTRIBUTE ("literal string") expands to the - attribute used in _GL_WARN_ON_USE. If the compiler does not support - this feature, it expands to empty. - - These macros are useful for marking a function as a potential - portability trap, with the intent that "literal string" include - instructions on the replacement function that should be used - instead. - _GL_WARN_ON_USE is for functions with 'extern' linkage. - _GL_WARN_ON_USE_ATTRIBUTE is for functions with 'static' or 'inline' - linkage. - - However, one of the reasons that a function is a portability trap is - if it has the wrong signature. Declaring FUNCTION with a different - signature in C is a compilation error, so this macro must use the - same type as any existing declaration so that programs that avoid - the problematic FUNCTION do not fail to compile merely because they - included a header that poisoned the function. But this implies that - _GL_WARN_ON_USE is only safe to use if FUNCTION is known to already - have a declaration. Use of this macro implies that there must not - be any other macro hiding the declaration of FUNCTION; but - undefining FUNCTION first is part of the poisoning process anyway - (although for symbols that are provided only via a macro, the result - is a compilation error rather than a warning containing - "literal string"). Also note that in C++, it is only safe to use if - FUNCTION has no overloads. - - For an example, it is possible to poison 'getline' by: - - adding a call to gl_WARN_ON_USE_PREPARE([[#include ]], - [getline]) in configure.ac, which potentially defines - HAVE_RAW_DECL_GETLINE - - adding this code to a header that wraps the system : - #undef getline - #if HAVE_RAW_DECL_GETLINE - _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but" - "not universally present; use the gnulib module getline"); - #endif - - It is not possible to directly poison global variables. But it is - possible to write a wrapper accessor function, and poison that - (less common usage, like &environ, will cause a compilation error - rather than issue the nice warning, but the end result of informing - the developer about their portability problem is still achieved): - #if HAVE_RAW_DECL_ENVIRON - static char *** - rpl_environ (void) { return &environ; } - _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); - # undef environ - # define environ (*rpl_environ ()) - #endif - or better (avoiding contradictory use of 'static' and 'extern'): - #if HAVE_RAW_DECL_ENVIRON - static char *** - _GL_WARN_ON_USE_ATTRIBUTE ("environ is not always properly declared") - rpl_environ (void) { return &environ; } - # undef environ - # define environ (*rpl_environ ()) - #endif - */ -#ifndef _GL_WARN_ON_USE - -# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) -/* A compiler attribute is available in gcc versions 4.3.0 and later. */ -# define _GL_WARN_ON_USE(function, message) \ -_GL_WARN_EXTERN_C __typeof__ (function) function __attribute__ ((__warning__ (message))) -# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ - __attribute__ ((__warning__ (message))) -# elif __clang_major__ >= 4 -/* Another compiler attribute is available in clang. */ -# define _GL_WARN_ON_USE(function, message) \ -_GL_WARN_EXTERN_C __typeof__ (function) function \ - __attribute__ ((__diagnose_if__ (1, message, "warning"))) -# define _GL_WARN_ON_USE_ATTRIBUTE(message) \ - __attribute__ ((__diagnose_if__ (1, message, "warning"))) -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -/* Verify the existence of the function. */ -# define _GL_WARN_ON_USE(function, message) \ -_GL_WARN_EXTERN_C __typeof__ (function) function -# define _GL_WARN_ON_USE_ATTRIBUTE(message) -# else /* Unsupported. */ -# define _GL_WARN_ON_USE(function, message) \ -_GL_WARN_EXTERN_C int _gl_warn_on_use -# define _GL_WARN_ON_USE_ATTRIBUTE(message) -# endif -#endif - -/* _GL_WARN_ON_USE_CXX (function, rettype_gcc, rettype_clang, parameters_and_attributes, "message") - is like _GL_WARN_ON_USE (function, "message"), except that in C++ mode the - function is declared with the given prototype, consisting of return type, - parameters, and attributes. - This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does - not work in this case. */ -#ifndef _GL_WARN_ON_USE_CXX -# if !defined __cplusplus -# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ - _GL_WARN_ON_USE (function, msg) -# else -# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) -/* A compiler attribute is available in gcc versions 4.3.0 and later. */ -# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ -extern rettype_gcc function parameters_and_attributes \ - __attribute__ ((__warning__ (msg))) -# elif __clang_major__ >= 4 -/* Another compiler attribute is available in clang. */ -# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ -extern rettype_clang function parameters_and_attributes \ - __attribute__ ((__diagnose_if__ (1, msg, "warning"))) -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -/* Verify the existence of the function. */ -# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ -extern rettype_gcc function parameters_and_attributes -# else /* Unsupported. */ -# define _GL_WARN_ON_USE_CXX(function,rettype_gcc,rettype_clang,parameters_and_attributes,msg) \ -_GL_WARN_EXTERN_C int _gl_warn_on_use -# endif -# endif -#endif - -/* _GL_WARN_EXTERN_C declaration; - performs the declaration with C linkage. */ -#ifndef _GL_WARN_EXTERN_C -# if defined __cplusplus -# define _GL_WARN_EXTERN_C extern "C" -# else -# define _GL_WARN_EXTERN_C extern -# endif -#endif diff --git a/xcompile/lib/xalloc-oversized.h b/xcompile/lib/xalloc-oversized.h deleted file mode 100644 index 5dbdfb5506a..00000000000 --- a/xcompile/lib/xalloc-oversized.h +++ /dev/null @@ -1,65 +0,0 @@ -/* xalloc-oversized.h -- memory allocation size checking - - Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc. - - This file 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 file is distributed in the hope that 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 program. If not, see . */ - -#ifndef XALLOC_OVERSIZED_H_ -#define XALLOC_OVERSIZED_H_ - -#include -#include - -/* True if N * S does not fit into both ptrdiff_t and size_t. - N and S should be nonnegative and free of side effects. - This expands to a constant expression if N and S are both constants. - By gnulib convention, SIZE_MAX represents overflow in size_t - calculations, so the conservative size_t-based dividend to use here - is SIZE_MAX - 1. */ -#define __xalloc_oversized(n, s) \ - ((s) != 0 \ - && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \ - < (n))) - -/* Return 1 if and only if an array of N objects, each of size S, - cannot exist reliably because its total size in bytes would exceed - MIN (PTRDIFF_MAX, SIZE_MAX - 1). - - N and S should be nonnegative and free of side effects. - - Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can - misbehave if N and S are both narrower than ptrdiff_t and size_t, - and can be rewritten as (xalloc_oversized (N, S) ? NULL - : malloc (N * (size_t) S)). - - This is a macro, not a function, so that it works even if an - argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */ -#if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX -# define xalloc_oversized(n, s) \ - __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1) -#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \ - && PTRDIFF_MAX < SIZE_MAX) -# define xalloc_oversized(n, s) \ - (__builtin_constant_p (n) && __builtin_constant_p (s) \ - ? __xalloc_oversized (n, s) \ - : ({ ptrdiff_t __xalloc_count; \ - __builtin_mul_overflow (n, s, &__xalloc_count); })) - -/* Other compilers use integer division; this may be slower but is - more portable. */ -#else -# define xalloc_oversized(n, s) __xalloc_oversized (n, s) -#endif - -#endif /* !XALLOC_OVERSIZED_H_ */ diff --git a/xcompile/malloc/dynarray-skeleton.c b/xcompile/malloc/dynarray-skeleton.c deleted file mode 100644 index 580c278b7c5..00000000000 --- a/xcompile/malloc/dynarray-skeleton.c +++ /dev/null @@ -1,528 +0,0 @@ -/* Type-safe arrays which grow dynamically. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* Pre-processor macros which act as parameters: - - DYNARRAY_STRUCT - The struct tag of dynamic array to be defined. - DYNARRAY_ELEMENT - The type name of the element type. Elements are copied - as if by memcpy, and can change address as the dynamic - array grows. - DYNARRAY_PREFIX - The prefix of the functions which are defined. - - The following parameters are optional: - - DYNARRAY_ELEMENT_FREE - DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the - contents of elements. E is of type DYNARRAY_ELEMENT *. - DYNARRAY_ELEMENT_INIT - DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new - element. E is of type DYNARRAY_ELEMENT *. - If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is - defined, new elements are automatically zero-initialized. - Otherwise, new elements have undefined contents. - DYNARRAY_INITIAL_SIZE - The size of the statically allocated array (default: - at least 2, more elements if they fit into 128 bytes). - Must be a preprocessor constant. If DYNARRAY_INITIAL_SIZE is 0, - there is no statically allocated array at, and all non-empty - arrays are heap-allocated. - DYNARRAY_FINAL_TYPE - The name of the type which holds the final array. If not - defined, is PREFIX##finalize not provided. DYNARRAY_FINAL_TYPE - must be a struct type, with members of type DYNARRAY_ELEMENT and - size_t at the start (in this order). - - These macros are undefined after this header file has been - included. - - The following types are provided (their members are private to the - dynarray implementation): - - struct DYNARRAY_STRUCT - - The following functions are provided: - - void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *); - bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *); - size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t); - void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT); - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *); - bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t); - void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *); - void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *); - - The following functions are provided are provided if the - prerequisites are met: - - bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, - DYNARRAY_FINAL_TYPE *); - (if DYNARRAY_FINAL_TYPE is defined) - DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *, - size_t *); - (if DYNARRAY_FINAL_TYPE is not defined) -*/ - -#include - -#include -#include -#include - -#ifndef DYNARRAY_STRUCT -# error "DYNARRAY_STRUCT must be defined" -#endif - -#ifndef DYNARRAY_ELEMENT -# error "DYNARRAY_ELEMENT must be defined" -#endif - -#ifndef DYNARRAY_PREFIX -# error "DYNARRAY_PREFIX must be defined" -#endif - -#ifdef DYNARRAY_INITIAL_SIZE -# if DYNARRAY_INITIAL_SIZE < 0 -# error "DYNARRAY_INITIAL_SIZE must be non-negative" -# endif -# if DYNARRAY_INITIAL_SIZE > 0 -# define DYNARRAY_HAVE_SCRATCH 1 -# else -# define DYNARRAY_HAVE_SCRATCH 0 -# endif -#else -/* Provide a reasonable default which limits the size of - DYNARRAY_STRUCT. */ -# define DYNARRAY_INITIAL_SIZE \ - (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT)) -# define DYNARRAY_HAVE_SCRATCH 1 -#endif - -/* Public type definitions. */ - -/* All fields of this struct are private to the implementation. */ -struct DYNARRAY_STRUCT -{ - union - { - struct dynarray_header dynarray_abstract; - struct - { - /* These fields must match struct dynarray_header. */ - size_t used; - size_t allocated; - DYNARRAY_ELEMENT *array; - } dynarray_header; - } u; - -#if DYNARRAY_HAVE_SCRATCH - /* Initial inline allocation. */ - DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE]; -#endif -}; - -/* Internal use only: Helper macros. */ - -/* Ensure macro-expansion of DYNARRAY_PREFIX. */ -#define DYNARRAY_CONCAT0(prefix, name) prefix##name -#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name) -#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name) - -/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free), - so that Gnulib does not change 'free' to 'rpl_free'. */ -#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree) - -/* Address of the scratch buffer if any. */ -#if DYNARRAY_HAVE_SCRATCH -# define DYNARRAY_SCRATCH(list) (list)->scratch -#else -# define DYNARRAY_SCRATCH(list) NULL -#endif - -/* Internal use only: Helper functions. */ - -/* Internal function. Call DYNARRAY_ELEMENT_FREE with the array - elements. Name mangling needed due to the DYNARRAY_ELEMENT_FREE - macro expansion. */ -static inline void -DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array, - size_t __dynarray_used) -{ -#ifdef DYNARRAY_ELEMENT_FREE - for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i) - DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]); -#endif /* DYNARRAY_ELEMENT_FREE */ -} - -/* Internal function. Free the non-scratch array allocation. */ -static inline void -DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list) -{ -#if DYNARRAY_HAVE_SCRATCH - if (list->u.dynarray_header.array != list->scratch) - free (list->u.dynarray_header.array); -#else - free (list->u.dynarray_header.array); -#endif -} - -/* Public functions. */ - -/* Initialize a dynamic array object. This must be called before any - use of the object. */ -__attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list) -{ - list->u.dynarray_header.used = 0; - list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE; - list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); -} - -/* Deallocate the dynamic array and its elements. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_FREE (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - DYNARRAY_NAME (free__array__) (list); - DYNARRAY_NAME (init) (list); -} - -/* Return true if the dynamic array is in an error state. */ -__attribute_nonnull__ ((1)) -static inline bool -DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.allocated == __dynarray_error_marker (); -} - -/* Mark the dynamic array as failed. All elements are deallocated as - a side effect. */ -__attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - DYNARRAY_NAME (free__array__) (list); - list->u.dynarray_header.array = DYNARRAY_SCRATCH (list); - list->u.dynarray_header.used = 0; - list->u.dynarray_header.allocated = __dynarray_error_marker (); -} - -/* Return the number of elements which have been added to the dynamic - array. */ -__attribute_nonnull__ ((1)) -static inline size_t -DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.used; -} - -/* Return a pointer to the array element at INDEX. Terminate the - process if INDEX is out of bounds. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index) -{ - if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list))) - __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index); - return list->u.dynarray_header.array + index; -} - -/* Return a pointer to the first array element, if any. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.array; -} - -/* Return a pointer one element past the last array element. For a - zero-length array, the pointer can be NULL even though the dynamic - array has not entered the failure state. */ -__attribute_nonnull__ ((1)) -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list) -{ - return list->u.dynarray_header.array + list->u.dynarray_header.used; -} - -/* Internal function. Slow path for the add function below. */ -static void -DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) -{ - if (__glibc_unlikely - (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)))) - { - DYNARRAY_NAME (mark_failed) (list); - return; - } - - /* Copy the new element and increase the array length. */ - list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; -} - -/* Add ITEM at the end of the array, enlarging it by one element. - Mark *LIST as failed if the dynamic array allocation size cannot be - increased. */ -__attribute_nonnull__ ((1)) -static inline void -DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item) -{ - /* Do nothing in case of previous error. */ - if (DYNARRAY_NAME (has_failed) (list)) - return; - - /* Enlarge the array if necessary. */ - if (__glibc_unlikely (list->u.dynarray_header.used - == list->u.dynarray_header.allocated)) - { - DYNARRAY_NAME (add__) (list, item); - return; - } - - /* Copy the new element and increase the array length. */ - list->u.dynarray_header.array[list->u.dynarray_header.used++] = item; -} - -/* Internal function. Building block for the emplace functions below. - Assumes space for one more element in *LIST. */ -static inline DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list) -{ - DYNARRAY_ELEMENT *result - = &list->u.dynarray_header.array[list->u.dynarray_header.used]; - ++list->u.dynarray_header.used; -#if defined (DYNARRAY_ELEMENT_INIT) - DYNARRAY_ELEMENT_INIT (result); -#elif defined (DYNARRAY_ELEMENT_FREE) - memset (result, 0, sizeof (*result)); -#endif - return result; -} - -/* Internal function. Slow path for the emplace function below. */ -static DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list) -{ - if (__glibc_unlikely - (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)))) - { - DYNARRAY_NAME (mark_failed) (list); - return NULL; - } - return DYNARRAY_NAME (emplace__tail__) (list); -} - -/* Allocate a place for a new element in *LIST and return a pointer to - it. The pointer can be NULL if the dynamic array cannot be - enlarged due to a memory allocation failure. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1)) -static -/* Avoid inlining with the larger initialization code. */ -#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE)) -inline -#endif -DYNARRAY_ELEMENT * -DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list) -{ - /* Do nothing in case of previous error. */ - if (DYNARRAY_NAME (has_failed) (list)) - return NULL; - - /* Enlarge the array if necessary. */ - if (__glibc_unlikely (list->u.dynarray_header.used - == list->u.dynarray_header.allocated)) - return (DYNARRAY_NAME (emplace__) (list)); - return DYNARRAY_NAME (emplace__tail__) (list); -} - -/* Change the size of *LIST to SIZE. If SIZE is larger than the - existing size, new elements are added (which can be initialized). - Otherwise, the list is truncated, and elements are freed. Return - false on memory allocation failure (and mark *LIST as failed). */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static bool -DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size) -{ - if (size > list->u.dynarray_header.used) - { - bool ok; -#if defined (DYNARRAY_ELEMENT_INIT) - /* The new elements have to be initialized. */ - size_t old_size = list->u.dynarray_header.used; - ok = __libc_dynarray_resize (&list->u.dynarray_abstract, - size, DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)); - if (ok) - for (size_t i = old_size; i < size; ++i) - { - DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]); - } -#elif defined (DYNARRAY_ELEMENT_FREE) - /* Zero initialization is needed so that the elements can be - safely freed. */ - ok = __libc_dynarray_resize_clear - (&list->u.dynarray_abstract, size, - DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT)); -#else - ok = __libc_dynarray_resize (&list->u.dynarray_abstract, - size, DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT)); -#endif - if (__glibc_unlikely (!ok)) - DYNARRAY_NAME (mark_failed) (list); - return ok; - } - else - { - /* The list has shrunk in size. Free the removed elements. */ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array + size, - list->u.dynarray_header.used - size); - list->u.dynarray_header.used = size; - return true; - } -} - -/* Remove the last element of LIST if it is present. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list) -{ - /* used > 0 implies that the array is the non-failed state. */ - if (list->u.dynarray_header.used > 0) - { - size_t new_length = list->u.dynarray_header.used - 1; -#ifdef DYNARRAY_ELEMENT_FREE - DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]); -#endif - list->u.dynarray_header.used = new_length; - } -} - -/* Remove all elements from the list. The elements are freed, but the - list itself is not. */ -__attribute_maybe_unused__ __attribute_nonnull__ ((1)) -static void -DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list) -{ - /* free__elements__ does nothing if the list is in the failed - state. */ - DYNARRAY_NAME (free__elements__) - (list->u.dynarray_header.array, list->u.dynarray_header.used); - list->u.dynarray_header.used = 0; -} - -#ifdef DYNARRAY_FINAL_TYPE -/* Transfer the dynamic array to a permanent location at *RESULT. - Returns true on success on false on allocation failure. In either - case, *LIST is re-initialized and can be reused. A NULL pointer is - stored in *RESULT if LIST refers to an empty list. On success, the - pointer in *RESULT is heap-allocated and must be deallocated using - free. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1, 2)) -static bool -DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, - DYNARRAY_FINAL_TYPE *result) -{ - struct dynarray_finalize_result res; - if (__libc_dynarray_finalize (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT), &res)) - { - /* On success, the result owns all the data. */ - DYNARRAY_NAME (init) (list); - *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length }; - return true; - } - else - { - /* On error, we need to free all data. */ - DYNARRAY_FREE (list); - errno = ENOMEM; - return false; - } -} -#else /* !DYNARRAY_FINAL_TYPE */ -/* Transfer the dynamic array to a heap-allocated array and return a - pointer to it. The pointer is NULL if memory allocation fails, or - if the array is empty, so this function should be used only for - arrays which are known not be empty (usually because they always - have a sentinel at the end). If LENGTHP is not NULL, the array - length is written to *LENGTHP. *LIST is re-initialized and can be - reused. */ -__attribute_maybe_unused__ __attribute_warn_unused_result__ -__attribute_nonnull__ ((1)) -static DYNARRAY_ELEMENT * -DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp) -{ - struct dynarray_finalize_result res; - if (__libc_dynarray_finalize (&list->u.dynarray_abstract, - DYNARRAY_SCRATCH (list), - sizeof (DYNARRAY_ELEMENT), &res)) - { - /* On success, the result owns all the data. */ - DYNARRAY_NAME (init) (list); - if (lengthp != NULL) - *lengthp = res.length; - return res.array; - } - else - { - /* On error, we need to free all data. */ - DYNARRAY_FREE (list); - errno = ENOMEM; - return NULL; - } -} -#endif /* !DYNARRAY_FINAL_TYPE */ - -/* Undo macro definitions. */ - -#undef DYNARRAY_CONCAT0 -#undef DYNARRAY_CONCAT1 -#undef DYNARRAY_NAME -#undef DYNARRAY_SCRATCH -#undef DYNARRAY_HAVE_SCRATCH - -#undef DYNARRAY_STRUCT -#undef DYNARRAY_ELEMENT -#undef DYNARRAY_PREFIX -#undef DYNARRAY_ELEMENT_FREE -#undef DYNARRAY_ELEMENT_INIT -#undef DYNARRAY_INITIAL_SIZE -#undef DYNARRAY_FINAL_TYPE diff --git a/xcompile/malloc/dynarray.h b/xcompile/malloc/dynarray.h deleted file mode 100644 index a9a3b0859c1..00000000000 --- a/xcompile/malloc/dynarray.h +++ /dev/null @@ -1,177 +0,0 @@ -/* Type-safe arrays which grow dynamically. Shared definitions. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -/* To use the dynarray facility, you need to include - and define the parameter macros - documented in that file. - - A minimal example which provides a growing list of integers can be - defined like this: - - struct int_array - { - // Pointer to result array followed by its length, - // as required by DYNARRAY_FINAL_TYPE. - int *array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_int - #define DYNARRAY_ELEMENT int - #define DYNARRAY_PREFIX dynarray_int_ - #define DYNARRAY_FINAL_TYPE struct int_array - #include - - To create a three-element array with elements 1, 2, 3, use this - code: - - struct dynarray_int dyn; - dynarray_int_init (&dyn); - for (int i = 1; i <= 3; ++i) - { - int *place = dynarray_int_emplace (&dyn); - assert (place != NULL); - *place = i; - } - struct int_array result; - bool ok = dynarray_int_finalize (&dyn, &result); - assert (ok); - assert (result.length == 3); - assert (result.array[0] == 1); - assert (result.array[1] == 2); - assert (result.array[2] == 3); - free (result.array); - - If the elements contain resources which must be freed, define - DYNARRAY_ELEMENT_FREE appropriately, like this: - - struct str_array - { - char **array; - size_t length; - }; - - #define DYNARRAY_STRUCT dynarray_str - #define DYNARRAY_ELEMENT char * - #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr) - #define DYNARRAY_PREFIX dynarray_str_ - #define DYNARRAY_FINAL_TYPE struct str_array - #include - - Compared to scratch buffers, dynamic arrays have the following - features: - - - They have an element type, and are not just an untyped buffer of - bytes. - - - When growing, previously stored elements are preserved. (It is - expected that scratch_buffer_grow_preserve and - scratch_buffer_set_array_size eventually go away because all - current users are moved to dynamic arrays.) - - - Scratch buffers have a more aggressive growth policy because - growing them typically means a retry of an operation (across an - NSS service module boundary), which is expensive. - - - For the same reason, scratch buffers have a much larger initial - stack allocation. */ - -#ifndef _DYNARRAY_H -#define _DYNARRAY_H - -#include -#include - -struct dynarray_header -{ - size_t used; - size_t allocated; - void *array; -}; - -/* Marker used in the allocated member to indicate that an error was - encountered. */ -static inline size_t -__dynarray_error_marker (void) -{ - return -1; -} - -/* Internal function. See the has_failed function in - dynarray-skeleton.c. */ -static inline bool -__dynarray_error (struct dynarray_header *list) -{ - return list->allocated == __dynarray_error_marker (); -} - -/* Internal function. Enlarge the dynamically allocated area of the - array to make room for one more element. SCRATCH is a pointer to - the scratch area (which is not heap-allocated and must not be - freed). ELEMENT_SIZE is the size, in bytes, of one element. - Return false on failure, true on success. */ -bool __libc_dynarray_emplace_enlarge (struct dynarray_header *, - void *scratch, size_t element_size); - -/* Internal function. Enlarge the dynamically allocated area of the - array to make room for at least SIZE elements (which must be larger - than the existing used part of the dynamic array). SCRATCH is a - pointer to the scratch area (which is not heap-allocated and must - not be freed). ELEMENT_SIZE is the size, in bytes, of one element. - Return false on failure, true on success. */ -bool __libc_dynarray_resize (struct dynarray_header *, size_t size, - void *scratch, size_t element_size); - -/* Internal function. Like __libc_dynarray_resize, but clear the new - part of the dynamic array. */ -bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size, - void *scratch, size_t element_size); - -/* Internal type. */ -struct dynarray_finalize_result -{ - void *array; - size_t length; -}; - -/* Internal function. Copy the dynamically-allocated area to an - explicitly-sized heap allocation. SCRATCH is a pointer to the - embedded scratch space. ELEMENT_SIZE is the size, in bytes, of the - element type. On success, true is returned, and pointer and length - are written to *RESULT. On failure, false is returned. The caller - has to take care of some of the memory management; this function is - expected to be called from dynarray-skeleton.c. */ -bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch, - size_t element_size, - struct dynarray_finalize_result *result); - - -/* Internal function. Terminate the process after an index error. - SIZE is the number of elements of the dynamic array. INDEX is the - lookup index which triggered the failure. */ -_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index); - -#ifndef _ISOMAC -libc_hidden_proto (__libc_dynarray_emplace_enlarge) -libc_hidden_proto (__libc_dynarray_resize) -libc_hidden_proto (__libc_dynarray_resize_clear) -libc_hidden_proto (__libc_dynarray_finalize) -libc_hidden_proto (__libc_dynarray_at_failure) -#endif - -#endif /* _DYNARRAY_H */ diff --git a/xcompile/malloc/dynarray_at_failure.c b/xcompile/malloc/dynarray_at_failure.c deleted file mode 100644 index ebc9310982c..00000000000 --- a/xcompile/malloc/dynarray_at_failure.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Report an dynamic array index out of bounds condition. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -# include -#endif - -#include -#include - -void -__libc_dynarray_at_failure (size_t size, size_t index) -{ -#ifdef _LIBC - char buf[200]; - __snprintf (buf, sizeof (buf), "Fatal glibc error: " - "array index %zu not less than array length %zu\n", - index, size); - __libc_fatal (buf); -#else - abort (); -#endif -} -libc_hidden_def (__libc_dynarray_at_failure) diff --git a/xcompile/malloc/dynarray_emplace_enlarge.c b/xcompile/malloc/dynarray_emplace_enlarge.c deleted file mode 100644 index 7da539316c1..00000000000 --- a/xcompile/malloc/dynarray_emplace_enlarge.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Increase the size of a dynamic array in preparation of an emplace operation. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include -#include -#include - -bool -__libc_dynarray_emplace_enlarge (struct dynarray_header *list, - void *scratch, size_t element_size) -{ - size_t new_allocated; - if (list->allocated == 0) - { - /* No scratch buffer provided. Choose a reasonable default - size. */ - if (element_size < 4) - new_allocated = 16; - else if (element_size < 8) - new_allocated = 8; - else - new_allocated = 4; - } - else - /* Increase the allocated size, using an exponential growth - policy. */ - { - new_allocated = list->allocated + list->allocated / 2 + 1; - if (new_allocated <= list->allocated) - { - /* Overflow. */ - __set_errno (ENOMEM); - return false; - } - } - - size_t new_size; - if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size)) - return false; - void *new_array; - if (list->array == scratch) - { - /* The previous array was not heap-allocated. */ - new_array = malloc (new_size); - if (new_array != NULL && list->array != NULL) - memcpy (new_array, list->array, list->used * element_size); - } - else - new_array = realloc (list->array, new_size); - if (new_array == NULL) - return false; - list->array = new_array; - list->allocated = new_allocated; - return true; -} -libc_hidden_def (__libc_dynarray_emplace_enlarge) diff --git a/xcompile/malloc/dynarray_finalize.c b/xcompile/malloc/dynarray_finalize.c deleted file mode 100644 index 673595a5fad..00000000000 --- a/xcompile/malloc/dynarray_finalize.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copy the dynamically-allocated area to an explicitly-sized heap allocation. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_dynarray_finalize (struct dynarray_header *list, - void *scratch, size_t element_size, - struct dynarray_finalize_result *result) -{ - if (__dynarray_error (list)) - /* The caller will reported the deferred error. */ - return false; - - size_t used = list->used; - - /* Empty list. */ - if (used == 0) - { - /* An empty list could still be backed by a heap-allocated - array. Free it if necessary. */ - if (list->array != scratch) - free (list->array); - *result = (struct dynarray_finalize_result) { NULL, 0 }; - return true; - } - - size_t allocation_size = used * element_size; - void *heap_array = malloc (allocation_size); - if (heap_array != NULL) - { - /* The new array takes ownership of the strings. */ - if (list->array != NULL) - memcpy (heap_array, list->array, allocation_size); - if (list->array != scratch) - free (list->array); - *result = (struct dynarray_finalize_result) - { .array = heap_array, .length = used }; - return true; - } - else - /* The caller will perform the freeing operation. */ - return false; -} -libc_hidden_def (__libc_dynarray_finalize) diff --git a/xcompile/malloc/dynarray_resize.c b/xcompile/malloc/dynarray_resize.c deleted file mode 100644 index 7ecd4de63b9..00000000000 --- a/xcompile/malloc/dynarray_resize.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Increase the size of a dynamic array. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include -#include -#include - -bool -__libc_dynarray_resize (struct dynarray_header *list, size_t size, - void *scratch, size_t element_size) -{ - /* The existing allocation provides sufficient room. */ - if (size <= list->allocated) - { - list->used = size; - return true; - } - - /* Otherwise, use size as the new allocation size. The caller is - expected to provide the final size of the array, so there is no - over-allocation here. */ - - size_t new_size_bytes; - if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes)) - { - /* Overflow. */ - __set_errno (ENOMEM); - return false; - } - void *new_array; - if (list->array == scratch) - { - /* The previous array was not heap-allocated. */ - new_array = malloc (new_size_bytes); - if (new_array != NULL && list->array != NULL) - memcpy (new_array, list->array, list->used * element_size); - } - else - new_array = realloc (list->array, new_size_bytes); - if (new_array == NULL) - return false; - list->array = new_array; - list->allocated = size; - list->used = size; - return true; -} -libc_hidden_def (__libc_dynarray_resize) diff --git a/xcompile/malloc/dynarray_resize_clear.c b/xcompile/malloc/dynarray_resize_clear.c deleted file mode 100644 index bb23c522a14..00000000000 --- a/xcompile/malloc/dynarray_resize_clear.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Increase the size of a dynamic array and clear the new part. - Copyright (C) 2017-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -bool -__libc_dynarray_resize_clear (struct dynarray_header *list, size_t size, - void *scratch, size_t element_size) -{ - size_t old_size = list->used; - if (!__libc_dynarray_resize (list, size, scratch, element_size)) - return false; - /* __libc_dynarray_resize already checked for overflow. */ - char *array = list->array; - memset (array + (old_size * element_size), 0, - (size - old_size) * element_size); - return true; -} -libc_hidden_def (__libc_dynarray_resize_clear) diff --git a/xcompile/malloc/scratch_buffer.h b/xcompile/malloc/scratch_buffer.h deleted file mode 100644 index 33fd2b29cd5..00000000000 --- a/xcompile/malloc/scratch_buffer.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _SCRATCH_BUFFER_H -#define _SCRATCH_BUFFER_H - -/* Scratch buffers with a default stack allocation and fallback to - heap allocation. It is expected that this function is used in this - way: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - return -1; - - scratch_buffer_free (&tmpbuf); - return 0; - - The allocation functions (scratch_buffer_grow, - scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make - sure that the heap allocation, if any, is freed, so that the code - above does not have a memory leak. The buffer still remains in a - state that can be deallocated using scratch_buffer_free, so a loop - like this is valid as well: - - struct scratch_buffer tmpbuf; - scratch_buffer_init (&tmpbuf); - - while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length)) - if (!scratch_buffer_grow (&tmpbuf)) - break; - - scratch_buffer_free (&tmpbuf); - - scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed - to grow the buffer by at least 512 bytes. This means that when - using the scratch buffer as a backing store for a non-character - array whose element size, in bytes, is 512 or smaller, the scratch - buffer only has to grow once to make room for at least one more - element. -*/ - -#include -#include -#include - -/* Scratch buffer. Must be initialized with scratch_buffer_init - before its use. */ -struct scratch_buffer { - void *data; /* Pointer to the beginning of the scratch area. */ - size_t length; /* Allocated space at the data pointer, in bytes. */ - union { max_align_t __align; char __c[1024]; } __space; -}; - -/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space - and BUFFER->length reflects the available space. */ -static inline void -scratch_buffer_init (struct scratch_buffer *buffer) -{ - buffer->data = buffer->__space.__c; - buffer->length = sizeof (buffer->__space); -} - -/* Deallocates *BUFFER (if it was heap-allocated). */ -static inline void -scratch_buffer_free (struct scratch_buffer *buffer) -{ - if (buffer->data != buffer->__space.__c) - free (buffer->data); -} - -/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT - preserved. Return true on success, false on allocation failure (in - which case the old buffer is freed). On success, the new buffer is - larger than the previous size. On failure, *BUFFER is deallocated, - but remains in a free-able state, and errno is set. */ -bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer); -libc_hidden_proto (__libc_scratch_buffer_grow) - -/* Alias for __libc_scratch_buffer_grow. */ -static __always_inline bool -scratch_buffer_grow (struct scratch_buffer *buffer) -{ - return __glibc_likely (__libc_scratch_buffer_grow (buffer)); -} - -/* Like __libc_scratch_buffer_grow, but preserve the old buffer - contents on success, as a prefix of the new buffer. */ -bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer); -libc_hidden_proto (__libc_scratch_buffer_grow_preserve) - -/* Alias for __libc_scratch_buffer_grow_preserve. */ -static __always_inline bool -scratch_buffer_grow_preserve (struct scratch_buffer *buffer) -{ - return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer)); -} - -/* Grow *BUFFER so that it can store at least NELEM elements of SIZE - bytes. The buffer contents are NOT preserved. Both NELEM and SIZE - can be zero. Return true on success, false on allocation failure - (in which case the old buffer is freed, but *BUFFER remains in a - free-able state, and errno is set). It is unspecified whether this - function can reduce the array size. */ -bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size); -libc_hidden_proto (__libc_scratch_buffer_set_array_size) - -/* Alias for __libc_scratch_set_array_size. */ -static __always_inline bool -scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size) -{ - return __glibc_likely (__libc_scratch_buffer_set_array_size - (buffer, nelem, size)); -} - -#endif /* _SCRATCH_BUFFER_H */ diff --git a/xcompile/malloc/scratch_buffer_dupfree.c b/xcompile/malloc/scratch_buffer_dupfree.c deleted file mode 100644 index 2f60fbb54e8..00000000000 --- a/xcompile/malloc/scratch_buffer_dupfree.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2020-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -void * -__libc_scratch_buffer_dupfree (struct scratch_buffer *buffer, size_t size) -{ - void *data = buffer->data; - if (data == buffer->__space.__c) - { - void *copy = malloc (size); - return copy != NULL ? memcpy (copy, data, size) : NULL; - } - else - { - void *copy = realloc (data, size); - return copy != NULL ? copy : data; - } -} -libc_hidden_def (__libc_scratch_buffer_dupfree) diff --git a/xcompile/malloc/scratch_buffer_grow.c b/xcompile/malloc/scratch_buffer_grow.c deleted file mode 100644 index a5e8f2f7230..00000000000 --- a/xcompile/malloc/scratch_buffer_grow.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include - -bool -__libc_scratch_buffer_grow (struct scratch_buffer *buffer) -{ - void *new_ptr; - size_t new_length = buffer->length * 2; - - /* Discard old buffer. */ - scratch_buffer_free (buffer); - - /* Check for overflow. */ - if (__glibc_likely (new_length >= buffer->length)) - new_ptr = malloc (new_length); - else - { - __set_errno (ENOMEM); - new_ptr = NULL; - } - - if (__glibc_unlikely (new_ptr == NULL)) - { - /* Buffer must remain valid to free. */ - scratch_buffer_init (buffer); - return false; - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_grow) diff --git a/xcompile/malloc/scratch_buffer_grow_preserve.c b/xcompile/malloc/scratch_buffer_grow_preserve.c deleted file mode 100644 index c0b5d87b7e4..00000000000 --- a/xcompile/malloc/scratch_buffer_grow_preserve.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer) -{ - size_t new_length = 2 * buffer->length; - void *new_ptr; - - if (buffer->data == buffer->__space.__c) - { - /* Move buffer to the heap. No overflow is possible because - buffer->length describes a small buffer on the stack. */ - new_ptr = malloc (new_length); - if (new_ptr == NULL) - return false; - memcpy (new_ptr, buffer->__space.__c, buffer->length); - } - else - { - /* Buffer was already on the heap. Check for overflow. */ - if (__glibc_likely (new_length >= buffer->length)) - new_ptr = realloc (buffer->data, new_length); - else - { - __set_errno (ENOMEM); - new_ptr = NULL; - } - - if (__glibc_unlikely (new_ptr == NULL)) - { - /* Deallocate, but buffer must remain valid to free. */ - free (buffer->data); - scratch_buffer_init (buffer); - return false; - } - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_grow_preserve) diff --git a/xcompile/malloc/scratch_buffer_set_array_size.c b/xcompile/malloc/scratch_buffer_set_array_size.c deleted file mode 100644 index 24c39350ade..00000000000 --- a/xcompile/malloc/scratch_buffer_set_array_size.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Variable-sized buffer with on-stack default allocation. - Copyright (C) 2015-2023 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C 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. - - The GNU C 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 the GNU C Library; if not, see - . */ - -#ifndef _LIBC -# include -#endif - -#include -#include -#include - -bool -__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer, - size_t nelem, size_t size) -{ - size_t new_length = nelem * size; - - /* Avoid overflow check if both values are small. */ - if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0 - && nelem != 0 && size != new_length / nelem) - { - /* Overflow. Discard the old buffer, but it must remain valid - to free. */ - scratch_buffer_free (buffer); - scratch_buffer_init (buffer); - __set_errno (ENOMEM); - return false; - } - - if (new_length <= buffer->length) - return true; - - /* Discard old buffer. */ - scratch_buffer_free (buffer); - - char *new_ptr = malloc (new_length); - if (new_ptr == NULL) - { - /* Buffer must remain valid to free. */ - scratch_buffer_init (buffer); - return false; - } - - /* Install new heap-based buffer. */ - buffer->data = new_ptr; - buffer->length = new_length; - return true; -} -libc_hidden_def (__libc_scratch_buffer_set_array_size) diff --git a/xcompile/verbose.mk.android b/xcompile/verbose.mk.android deleted file mode 100644 index 7d07b978de2..00000000000 --- a/xcompile/verbose.mk.android +++ /dev/null @@ -1,65 +0,0 @@ -### verbose.mk --- Makefile fragment for GNU Emacs during -### cross-compilation. - -## Copyright (C) 2023 Free Software Foundation, Inc. - -## This file is part of GNU Emacs. - -## GNU Emacs is free software: you can 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. -## -## GNU Emacs is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with GNU Emacs. If not, see . - -# 'make' verbosity. -V = 0 -ifeq (${V},1) -AM_V_AR = -AM_V_at = -AM_V_CC = -AM_V_CXX = -AM_V_CCLD = -AM_V_CXXLD = -AM_V_ELC = -AM_V_ELN = -AM_V_GEN = -AM_V_GLOBALS = -AM_V_NO_PD = -AM_V_RC = -AM_V_JAVAC = -AM_V_DX = -AM_V_AAPT = -AM_V_ZIPALIGN = -else - -# Whether $(info ...) works. This is to work around a bug in GNU Make -# 4.3 and earlier, which implements $(info MSG) via two system calls -# { write (..., "MSG", 3); write (..., "\n", 1); } -# which looks bad when make -j interleaves two of these at about the same time. -# -# Later versions of GNU Make have the 'notintermediate' feature, -# so assume that $(info ...) works if this feature is present. -# -have_working_info = $(filter notintermediate,$(value .FEATURES)) -# -# The workaround is to use the shell and 'echo' rather than $(info ...). -# The workaround is done only for AM_V_ELC and AM_V_ELN, -# since the bug is not annoying elsewhere. - -AM_V_AR = @$(info $ AR $@) -AM_V_at = @ -AM_V_CC = @$(info $ ANDROID_CC $@) -AM_V_CXX = @$(info $ ANDROID_CXX $@) -AM_V_CCLD = @$(info $ CCLD $@) -AM_V_CXXLD = @$(info $ CXXLD $@) - -AM_V_GEN = @$(info $ GEN $@) -AM_V_NO_PD = --no-print-directory -endif