pax_global_header00006660000000000000000000000064131707230500014510gustar00rootroot0000000000000052 comment=25dadace9878eda8778ffd549ad0b6fc4ca89c11 remake-4.1+dbg1.3~dfsg.1/000077500000000000000000000000001317072305000147735ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/.cvsignore000066400000000000000000000012461317072305000167760ustar00rootroot00000000000000*.gz *.Z *.tar *.tgz =* TODO COPYING* ABOUT-NLS make-3* make-test* *.info *.info-* stamp-* makebook* .*gdbinit .gdb_history *.dep *.dvi *.toc *.aux *.log *.cp *.cps *.fn *.fns *.vr *.vrs *.tp *.tps *.ky *.kys *.pg *.pgs README README.DOS README.W32 README.OS2 aclocal.m4 autom4te.cache config.h.in config.h config.status config.cache configure Makefile.in Makefile build.sh.in build.sh SMakefile NMakefile Makefile.DOS config.ami configh.dos config.h.W32 config.h-vms loadavg loadavg.c make .deps .dep_segment ID TAGS _* sun4 i386 i386-netbsd hp300-netbsd hp300 rs6000 sun3 news800 amiga hp700 hp834 mips sol2 i486-linux customs install-sh mkinstalldirs .directive.asc remake-4.1+dbg1.3~dfsg.1/.gitignore000066400000000000000000000007461317072305000167720ustar00rootroot00000000000000*.a *.o *~ .deps /*.log /.Tpo /.dep_segment /ABOUT-NLS /ChangeLog /Makefile /Makefile.DOS /Makefile.in /NMakefile /README /README.DOS /README.OS2 /README.W32 /SMakefile /aclocal.m4 /autom4te.cache /build.sh /build.sh.in /config /config.ami /config.h /config.h-vms /config.h.W32 /config.h.in /config.log /config.status /configh.dos /configure /debian/remake.debhelper.log /loadavg /make /po-check-* /remake /remake-*.tar.bz2 /remake-*.tar.gz /stamp-h1 /test-profile /tmp callgrind.out.* remake-4.1+dbg1.3~dfsg.1/.purify000066400000000000000000000011241317072305000163100ustar00rootroot00000000000000# Solaris (2.5.1) has a couple if issues. # suppress plk malloc; setvbuf "libc*"; main "main.c" suppress umr kstat_read; kstat_chain_update; kstat_open; getloadavg suppress umr kstat_chain_update; kstat_open; getloadavg # The command line options stuff leaks a little bit. No big deal. # suppress mlk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress plk malloc; xmalloc "misc.c"; decode_env_switches "main.c" suppress mlk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c" suppress plk malloc; xmalloc "misc.c"; concat "misc.c"; decode_env_switches "main.c" remake-4.1+dbg1.3~dfsg.1/.travis.yml000066400000000000000000000005551317072305000171110ustar00rootroot00000000000000language: C sudo: false addons: apt: packages: - autopoint - libreadline-dev - wget - texinfo # run the tests #script: autoreconf -i && ./configure --enable-maintainer-mode && make update && (cd doc && make stamp-vti) && make && TRAVIS=1 make check script: autoreconf -i && ./configure && make update && make && TRAVIS=1 make check remake-4.1+dbg1.3~dfsg.1/AUTHORS000066400000000000000000000056371317072305000160560ustar00rootroot00000000000000----------------------------------- GNU make development up to version 3.75 by: Roland McGrath Development starting with GNU make 3.76 by: Paul D. Smith Additional development starting with GNU make 3.81 by: Boris Kolpackov GNU Make User's Manual Written by: Richard M. Stallman Edited by: Roland McGrath Bob Chassell Melissa Weisshaus Paul D. Smith ----------------------------------- GNU make porting efforts: Port to VMS by: Klaus Kaempf Hartmut Becker Archive support/Bug fixes by: John W. Eaton Martin Zinser Port to Amiga by: Aaron Digulla Port to MS-DOS (DJGPP), OS/2, and MS-Windows (native/MinGW) by: DJ Delorie Rob Tulloh Eli Zaretskii Jonathan Grant Andreas Beuning Earnie Boyd Troy Runkel ----------------------------------- Other contributors: Janet Carson Howard Chu Ludovic Courtès Paul Eggert Ramon Garcia Fernandez Klaus Heinz Michael Joosten Jim Kelton David Lubbren Tim Magill Markus Mauhart Greg McGary Thien-Thi Nguyen Thomas Riedl Han-Wen Nienhuys Andreas Schwab Carl Staelin (Princeton University) Ian Stewartson (Data Logic Limited) David A. Wheeler David Boyce Frank Heckenbach With suggestions/comments/bug reports from a cast of ... well ... hundreds, anyway :) ------------------------------------------------------------------------------- Copyright (C) 1997-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/COPYING000066400000000000000000001045131317072305000160320ustar00rootroot00000000000000 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 . remake-4.1+dbg1.3~dfsg.1/ChangeLog.1000066400000000000000000005554041317072305000167210ustar00rootroot00000000000000Tue Oct 29 20:57:36 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62. * remake.c (update_file_1): Check for deps still running before giving up if any dep has failed. Sat Oct 26 16:20:00 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h [uts]: #undef S_ISREG and S_ISDIR if defined. Fri Oct 25 19:50:39 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.17. Thu Oct 24 16:58:36 1991 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * job.c (start_job): Don't check for empty cmds before tweaking the command_ptr. Just let construct_command_argv do it. Tue Oct 22 20:21:03 1991 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * remake.c, arscan.c [POSIX]: instead of . * make.h [POSIX]: Declare vfork as pid_t. Mon Oct 21 15:37:30 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.16. * job.c (construct_command_argv, construct_command_argv_internal): Take new 2nd arg RESTP. If non-NULL, stop parsing at newline, and store addr of the NL in *RESTP. (start_job): Don't chop expanded cmd lines up; use above code to do it. * function.c (expand_function: `shell'): Pass RESTP==NULL. Sat Oct 19 15:36:34 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.15. Fri Oct 18 15:26:55 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (start_job): If on the same cmds->command_lines elt, look at cmds->lines_recurse[CHILD->command_line - 1] instead of [CHILD->command_line]. * dir.c [sgi]: , not ndir or anything else. Thu Oct 17 16:28:55 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * file.c (print_file_data_base): Remove unused var. * make.h [NeXT]: No #define ANSI_STRING. Tue Oct 15 20:08:41 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.60.14. Fri Oct 11 16:23:52 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * make.h: Use PATH_MAX for getwd defn. * make.h: Move getcwd/getwd outside of #ifndef POSIX, and make it #if USG||POSIX. Thu Oct 10 11:53:31 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.60.13. * read.c (read_all_makefiles): When processing MAKEFILES, save the malloc'd ptr to be freed, instead of freeing part-way thru it. * remake.c (update_file_1): Don't tweak FILE->also_make. (update_file): Do it here. After calling update_file_1, set the command_state, update_status, and updated members of each also_make elt to FILE's values. Tue Oct 8 14:56:04 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.60.12. * remake.c (notice_finished_file): Set command_state of FILE and its also_make chain to cs_finished here. * commands.c (execute_file_commands), job.c (child_handler), remake.c (remake_file): Don't set it before calling notice_finished_file. * file.h (struct file): Changed `also_make' to struct dep *. * job.c (delete_child_targets), file.c (print_file_data_base), remake.c (notice_finished_file), implicit.c (pattern_search): Use dep chain instead of array of file names. Mon Oct 7 17:04:33 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.60.11. * arscan.c: Declare open. * misc.c: Declare {get,set}{re,}[ug]id. * variable.c (target_environment): Declare getenv. Sat Oct 5 15:13:03 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * make.h [NeXT]: instead of . Fri Oct 4 16:05:41 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * default.c (default_suffixes, defualt_suffix_rules): Add .texi just like .texinfo. * Version 3.60.10. * job.c: Move vfork decl into make.h. Fri Sep 27 18:45:30 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * compatMakefile (glob/libglob.a): Pass CC value to submake. Thu Sep 26 00:08:15 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * load.c (load_average): Made not static. * load.c [ultrix && vax]: Define LDAV_TYPE and LDAV_CVT for Ultrix 4.2. Tue Sep 24 00:17:20 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.9. * read.c (record_files): Warn about extra cmds even if the target's name begins with a dot. I think the lusers can handle this. Mon Sep 23 22:33:26 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h, arscan.c: Don't declare bcmp, bzero, or bcopy if they're #define'd. * make.h: Declare write and open. * default.c (default_suffixes, default_suffix_rules, default_variables): Add .C just like .cc. * make.texinfo (Catalogue of Rules): Document .C. * make.man (-w): Fix gramo. Fri Sep 20 17:18:16 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h: No text after #endif. Sun Sep 15 16:20:46 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.60.8. * implicit.c (pattern_search): In the second pass, recurse on rule deps that don't have a %. Why did I make it not do this? Fri Sep 14 18:29:39 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * read.c (record_files): For extra cmds, use the last ones given. If the target's name doesn't begin with a dot (bletch!!), emit a two-line warning, one line giving the old cmds' location and the other the new cmds' location. * misc.c (makefile_error, makefile_fatal): New fns. * make.h: Declare them. * Use them instead of error/fatal for all msgs including a file name and line number. Thu Sep 13 16:35:54 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * make.h: Declare define_default_variables. Declare ar_parse_name, instead of ar_name_parse (M-t). Mon Sep 10 18:35:40 1991 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * Version 3.60.7. * make.texinfo (Variables: Setting): Say whitespace is removed if "immediately after =", rather than simply "after =". * job.c: Don't declare wait #ifdef POSIX. * make.h [__GNUC__]: #undef alloca and then #define it. * main.c (main): When pruning makefiles which might loop from the read_makefiles chain, look at all `prev' entries of double-colon rules. Fri Sep 7 00:41:53 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * main.c (main): Only remove makefiles with cmds but no deps from the list of makefiles to be rebuilt if they are :: targets. : targets with cmds and no deps are not dangerous. Wed Sep 5 17:35:51 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (defines): Add comment that some compilers take ENUM_BITFIELDS but produce bogus code. (LOAD_AVG): Fix examples to \ "s. (LOADLIBES): Add comment that SGI Irix needs -lmld for nlist. Tue Sep 4 20:26:26 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.6. Fri Aug 30 19:34:04 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (update_file_1): When checking the command_state of deps, check through the prev chain. (update_goal_chain): When a target is finished, start checking its prev (if it has one) instead. Wed Aug 7 17:32:03 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * rule.c (convert_to_pattern): Allow files with deps to define suffix rules (really this time). Mon Aug 5 17:09:21 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * misc.c (user_access, make_access): Do saved-IDs (USG) flavor #ifdef POSIX. * file.c (enter_file): Strip ./s here. * read.c (parse_file_seq): Not here. Tue Jul 23 23:34:30 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile: Added comment that -lPW alloca is broken on HPUX. Thu Jul 18 03:10:41 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.5. * read.c (read_makefile): Ignore lines containing chars that are all isspace, not just all isblank. * make.texinfo (Copying): @include gpl.texinfo, rather than copying the text. * gpl.texinfo: New file (symlink to /gd/gnu/doc/gpl.texinfo). * GNUmakefile: Put gpl.texinfo in distribution. Tue Jul 16 12:50:35 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * make.h: #define _GNU_SOURCE before including headers. Include and define isblank if doesn't. * commands.c: Don't include here. * *.c: Use isblank instead of explicit ' ' || '\t'. Mon Jul 15 17:43:38 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * function.c (expand_function: `filter'/`filter-out'): Fixed to not loop infinitely. Fri Jul 12 12:18:12 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * function.c (expand_function: `filter'/`filter-out'): Rewritten to handle filter-out of multiple patterns properly. Also no longer mallocs and reallocs for temp array; uses alloca and a linked-list instead. Wed Jul 10 22:34:54 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.4. * make.texinfo: Moved some @groups that were outside @examples to be inside them. * load.c [apollo] (load_average): Define using special syscall for Apollo DOMAIN/OS SR10.n. Thu Jul 4 12:32:53 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * make.texinfo (Missing): Added Unix excessive implicit rule search; mention that POSIX.2 doesn't require any of the missing features. (Top): Updated printed manual price to $15. Wed Jul 3 18:17:50 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * file.c (rename_file): Carry over last_mtime when merging files. * remake.c (f_mtime): Tail-recurse after renaming VPATH file, to check for saved date in existing renamed-to file. * remote-cstms.c (start_remote_job): Use PATH_VAR. * commands.c [POSIX || __GNU_LIBRARY__]: Don't declare getpid. * compatMakefile (glob-{clean,realclean}): Run clean/realclean in glob. (clean, realclean): Require those. * make.h: Always declare environ. Don't declare old glob functions. * GNUmakefile: Make no-lib deps for load.c and remote.c. Tue Jul 2 18:35:20 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.60.3. Mon Jul 1 16:58:30 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (multi_glob): Don't pass GLOB_QUOTE flag to glob. * make.h [POSIX]: Include , and don't declare things that should be there. * main.c (main) [USG && sgi]: malloc a buffer for broken sgi stdio. Sat Jun 29 11:22:21 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * function.c (expand_function: `shell'): Use alloca for the error msg buffer, instead of assuming an arbitrary max size. Fri Jun 28 18:15:08 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c [POSIX] (search_path): Do real 1003.1 goop to get NGROUPS_MAX. Wed Jun 26 11:04:44 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * default.c (define_default_variables): New fn. (install_default_implicit_rules): Code for above fn moved there. * main.c (main): Do define_default_variables before reading the makefile. Tue Jun 25 17:30:46 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * main.c (main): Quote ; in MAKEOVERRIDES. Tue Jun 18 13:56:30 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * compatMakefile: Fixed typo in comment. Tue Jun 11 00:14:59 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.60.2. Mon Jun 10 14:46:37 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h: Always include . [POSIX]: Include and #define MAXPATHLEN to be PATH_MAX. * default.c (default_suffix_rules: .texinfo.dvi): Use $(TEXI2DVI). (default_variables): Define TEXI2DVI. Thu Jun 6 16:49:19 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.60.1. * make.h (SIGNAL): Cast handler arg to SIGHANDLER type. Wed Jun 5 06:00:43 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * read.c (multi_glob): Use POSIX.2 `glob' function. If a glob pattern matches nothing, leave it as is (a la sh, bash). Also, if can't find USER for ~USER, leave it as is (a la bash). Mon Jun 3 16:36:00 1991 Roland McGrath (roland@albert.gnu.ai.mit.edu) * compatMakefile: Rewrote comments about -Ds to be easier to use. * make.h, arscan.c, remake.c, main.c, dir.c, job.c: Changed tests of _POSIX_SOURCE to POSIX. * job.c: Take getdtablesize out of #ifdef __GNU_LIBRARY__. Put separately #ifdef USG. * COPYING: Replaced with version 2. * Changed copyright notices to refer to GPL v2. Thu May 30 00:31:11 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h: Don't declare sigblock for POSIX. * main.c (main, log_working_directory) [USG]: Get getcwd failure mode from errno, not passed buffer like BSD getwd. * misc.c (child_access): New fn to set access for a child process; like user_access, but you can't change back. * make.h: Declare it. * job.c (exec_command): Use it in place of user_access. Wed May 29 23:28:48 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (default_variables) [pyr]: PC = pascal. Tue May 28 20:24:56 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (print_variable): Put a newline before `endef'. Sat May 25 02:39:52 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.60. Wed May 22 19:41:37 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.59.5. Thu May 16 13:59:24 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (main): Do USGr3 setvbuf behavior #ifdef APOLLO. Don't handle SIGCHLD #ifdef USG (Apollo is USG but defines SIGCHLD). Fri May 10 14:59:33 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * remake.c [sgi]: Don't include . Wed May 8 01:54:08 1991 Roland McGrath (roland@geech.gnu.ai.mit.edu) * make.h (SIGHANDLER): #define as (void *) #if __STDC__, else (int (*)()). (SIGNAL): Use it to cast return value. * main.c (main): Cast SIG_IGN to SIGHANDLER when comparing. * job.c (block_signals, unblock_signals): Use SIGNAL instead of signal. * main.c: Declare mktemp to return char*, not int. * job.c (new_job): Don't increment files_remade. * remake.c (notice_finished_file): Do it here. * read.c (do_define): Don't clobber DEFINITION[-1] on empty defns. Free storage that is no longer needed. Wed Apr 24 20:49:48 1991 Roland McGrath (roland at churchy.gnu.ai.mit.edu) * misc.c (message): New fn to print informational msgs with leading "make: " or "make[N]: ". * make.h: Declare it. * remake.c (update_file): Use it instead of printf. Fri Apr 19 05:52:45 1991 Roland McGrath (roland at churchy.gnu.ai.mit.edu) * main.c (main): When there are no targets, if there were no makefiles, print a different error message, which mentions makefiles. Tue Apr 16 03:22:45 1991 Roland McGrath (roland at geech.gnu.ai.mit.edu) * remake.c (update_file): Print "nothing to be done" instead of "is up to date" if FILE->cmds == 0. * job.c [!WIFEXITED]: Define if not already defined. Thu Apr 11 18:00:50 1991 Roland McGrath (roland at wookumz.gnu.ai.mit.edu) * arscan.c (ar_name_equal): Fixed truncation comparison. Tue Apr 2 16:17:35 1991 Roland McGrath (roland at churchy.gnu.ai.mit.edu) * glob.c: Use common version from djm. * dir.c: Snarfed #ifdef mess for or whatever from glob.c. (dir_file_exists_p): Ignore directory entries with d_ino==0. Mon Apr 1 20:49:45 1991 Roland McGrath (roland at albert.gnu.ai.mit.edu) * Version 3.59.4. Fri Mar 29 19:16:18 1991 Roland McGrath (roland at albert.gnu.ai.mit.edu) * job.c (free_child): Free CHILD->environment and its elts. Sat Mar 23 14:08:09 1991 Roland McGrath (roland at albert.gnu.ai.mit.edu) * read.c (read_makefile): Don't ignore lines containing only comments if they start with a tab. Such lines should be passed to the shell for it to decide about the comments. * job.c (free_child): Free CHILD->command_lines and its elts, not CHILD->commands (which is obsolete). * job.h, job.c: Remove obsolete `commands' member of `struct child'. Sun Mar 17 18:40:53 1991 Roland McGrath (roland at albert.ai.mit.edu) * remake.c (update_file): Print a msg for a top-level up-to-date phony target (a different one than for a real file). * read.c (conditional_line): Boundary check so we don't check the value of the -1th elt of the stack (which is bogus). Sat Mar 16 16:58:47 1991 Roland McGrath (roland at albert.ai.mit.edu) * read.c (conditional_line): Don't evaluate an if* when we're already ignoring. Instead, just push a new level, with a value of 1, to keep ignoring. Tue Mar 12 00:16:52 1991 Roland McGrath (roland at geech.ai.mit.edu) * Version 3.59.3. Mon Mar 11 23:56:57 1991 Roland McGrath (roland at geech.ai.mit.edu) * job.c (construct_command_argv_internal): Quote backslashes when building the shell -c line. Fri Mar 8 01:40:18 1991 Roland McGrath (roland at geech.ai.mit.edu) * job.c (exec_command): Call user_access rather than setgid(getgid()). * misc.c (remove_comments): Renamed from collapse_line; took out collapse_continuations call. * make.h: Change decl. * read.c (read_makefile): Collapse continuations on the line buffer immediately after reading it. Call remove_comments rather than collapse_line (which is now defunct). Thu Feb 21 18:06:51 1991 Roland McGrath (mcgrath at cygint.cygnus.com) * misc.c (user_access, make_access): New fns to toggle btwn permissions for user data (files and spawning children), and permissions for make (for taking the load average, mostly). * make.h: Declare them. * job.c (start_job): Call make_access before wait_to_start_job, and user_access after. * main.c (main): Call user_access before doing much. Mon Feb 3 15:02:03 1991 Roland McGrath (roland at albert.ai.mit.edu) * Version 3.59.2. Tue Jan 29 20:30:50 1991 Roland McGrath (roland at cygint.cygnus.com) * read.c (read_all_makefiles): Use allocated_variable_expand to expand `$(MAKEFILES)', since the results are used across calls to read_makefile, which could clobber them. Wed Jan 23 00:24:10 1991 Roland McGrath (roland at cygint.cygnus.com) * main.c (main): Call install_default_implicit_rules after reading makefiles, not before. * default.c (install_default_implicit_rules): If a suffix-rule file entry has cmds, don't give it any from default_suffix_rules. Fri Jan 17 17:39:49 1991 Roland McGrath (roland at albert.ai.mit.edu) * arscan.c: Added support for AIX archives. * remake.c: Don't include ar.h. * main.c: Removed unused atol decl. * arscan.c (ar_scan): Declare arg FUNCTION to return long int. * ar.c (ar_touch): Don't perror for an invalid archive. * make.h: Declare lseek as long int. * job.c [hpux]: Define getdtablesize a la USG. Sun Jan 12 21:08:34 1991 Roland McGrath (roland at albert.ai.mit.edu) * Version 3.59.1. Fri Jan 10 03:48:08 1991 Roland McGrath (roland at albert.ai.mit.edu) * job.c (search_path): Take new arg, place to put full pathname (rather than mallocing it). (exec_command): Pass it, using auto storage. * main.c (print_version): Updated copyright years. Wed Jan 8 19:46:19 1991 Roland McGrath (roland at albert.ai.mit.edu) * job.c [_POSIX_SOURCE]: Just #include , and define macro WAIT_NOHANG in terms of waitpid. [!_POSIX_SOURCE && (HAVE_SYS_WAIT || !USG)]: Don't #include (make.h does). Define macro WAIT_NOHANG in terms of wait3. (child_handler): #ifdef on WAIT_NOHANG, not HAVE_SYS_WAIT || !USG. Use WAIT_NOHANG macro instead of wait3. * file.h (struct file.command_state): Remove unused elt. Wed Dec 26 18:10:26 1990 Roland McGrath (roland at albert.ai.mit.edu) * commands.c (set_file_variables): If FILE got its commands from .DEFAULT, make $< == $@ (4.3 BSD/POSIX.2d11 compat). Mon Dec 24 17:36:27 1990 Roland McGrath (roland at albert.ai.mit.edu) * default.c (default_variables): Rename 2nd LINK.s defn to LINK.S. Fri Dec 14 15:05:25 1990 Roland McGrath (roland at albert.ai.mit.edu) * vpath.c (selective_vpath_search): Check for makefile-mentioned before checking for actual existence. The old order loses if the containing directory doesn't exist (but a rule might make it). * make.h [__GNUC__]: Don't #define alloca if already #define'd. * rule.c (convert_to_pattern): Don't look at the target constructed for the empty rule when making the null-suffix rule. Construct it over again, since the former may have been freed already. Thu Dec 13 17:21:03 1990 Roland McGrath (roland at churchy.ai.mit.edu) * make.h [__GNU_LIBRARY__]: Include to get random fn decls. Wed Dec 12 17:12:59 1990 Roland McGrath (roland at churchy.ai.mit.edu) * make.h, arscan.c, glob.c: Only include #ifdef USG. * variable.c (define_variable_in_set): Replace env_overrides check that wasn't really redundant (undoing Sep 28 change). Add comment saying why this check is necessary. * job.c, main.c [DGUX]: Needs siglist like USG. Mon Dec 11 01:19:29 1990 Roland McGrath (roland at albert.ai.mit.edu) * default.c [M_XENIX]: For rules that are different for Xenix, use the generic Unix version #ifdef __GNUC__. * main.c [M_XENIX]: Use USGr3-style setvbuf call. * read.c (find_percent): Do backslash folding correctly, not leaving extra crud on the end of the string. Sun Dec 10 21:48:36 1990 Roland McGrath (roland at albert.ai.mit.edu) * job.c: Don't declare wait3 if it's #defined. * GNUmakefile, compatMakefile, make.texinfo: Change make-info to make.info. Thu Dec 7 21:20:01 1990 Roland McGrath (roland at churchy.ai.mit.edu) * make.h [STDC_HEADERS || __GNU_LIBRARY__ || _POSIX_SOURCE]: Use ANSI and names for str/mem functions. Use to declare misc fns rather than explicit decls. [_POSIX_SOURCE]: Don't declare kill ( will). Include before because some braindead nonconformant 1003.1 implementation needs it. * misc.c: Don't declare malloc, realloc. Do it in make.h. * arscan.c, glob.c: Use sequence for string fns from make.h verbatim. * make.h (S_ISDIR, S_ISREG): Declare if necessary. * commands.c (delete_child_targets), job.c (search_path), read.c (construct_include_path): Use S_ISfoo(m) instead of (m & S_IFMT) == S_IFfoo. * dir.c, glob.c [_POSIX_SOURCE]: Use dirent. Wed Nov 29 22:53:32 1990 Roland McGrath (roland at geech.ai.mit.edu) * Version 3.59. Tue Nov 28 16:00:04 1990 Roland McGrath (roland at churchy.ai.mit.edu) * arscan.c (ar_name_equal) [APOLLO]: Don't do `.o' hacking. On Apollos the full file name is elsewhere, and there is no length restriction (or so I'm told). Thu Nov 23 17:33:11 1990 Roland McGrath (roland at albert.ai.mit.edu) * load.c [hp300 && BSD] (LDAV_CVT): Define for this system. Tue Nov 21 07:58:40 1990 Roland McGrath (roland at albert.ai.mit.edu) * read.c (record_files): Fix trivial bug with deciding to free storage for a file name. Thu Nov 16 06:21:38 1990 Roland McGrath (roland at geech.ai.mit.edu) * compatMakefile ($(bindir)/make): Install it setgid kmem. Thu Nov 1 16:12:55 1990 Roland McGrath (roland at churchy.ai.mit.edu) * GNUmakefile (make-*.tar.Z): Use `h' option to tar (dereference symlinks), to grab texinfo.tex from wherever it lives. Tue Oct 30 16:15:20 1990 Roland McGrath (roland at churchy.ai.mit.edu) * Version 3.58.13. Fri Oct 26 14:33:34 1990 Roland McGrath (roland at churchy.ai.mit.edu) * GNUmakefile: make-*.tar.Z: Include texinfo.tex. Tue Oct 23 19:34:33 1990 Roland McGrath (roland at churchy.ai.mit.edu) * main.c (define_makeflags): When there are no flags to write, make sure the array has two leading nulls, since `MAKEFLAGS' is defined from &flags[1]. * main.c (default_keep_going_flag): New variable (constant one). (command_switches: -k, -S): Use above for default value. (define_makeflags): Only write flag/flag_off switches if they are on, and either there is no default value, or they are not the default. Mon Oct 22 16:14:44 1990 Roland McGrath (roland at churchy.ai.mit.edu) * main.c (struct command_switch): New member `no_makefile'. (command_switches: -n, -q, -t): Set no_makefile == 1. (define_makeflags): Take new arg MAKEFILE: if nonzero, don't use options whose `no_makefile' flags are set. (main): Call define_makeflags with MAKEFILE==1 before remaking makefiles, and again with MAKEFILE==0 before remaking goals. Tue Oct 2 17:16:45 1990 Roland McGrath (roland at geech.ai.mit.edu) * Version 3.58.12. Mon Oct 1 15:43:23 1990 Roland McGrath (roland at churchy.ai.mit.edu) * arscan.c [HPUX]: Use PORTAR==1 format. Sat Sep 29 16:38:05 1990 Roland McGrath (roland at churchy.ai.mit.edu) * make.h, remake.c, arscan.c: Don't declare `open'. Fri Sep 28 04:46:23 1990 Roland McGrath (roland at churchy.ai.mit.edu) * variable.c (define_variable_in_set): Remove redundant -e check. Wed Sep 26 00:28:59 1990 Roland McGrath (roland at geech.ai.mit.edu) * job.c (start_job): Set RECURSIVE from the right elt of CHILD->file->cmds->lines_recurse. * commands.c (chop_commands): Don't botch the line count for allocating CMDS->lines_recurse. * Version 3.58.11. * job.c (start_job): Don't always increment CHILD->command_line! Only do it when CHILD->command_ptr has run out! (Dumb bug. Sigh.) Thu Sep 20 02:18:51 1990 Roland McGrath (roland at geech.ai.mit.edu) * GNUmakefile [ARCH]: Give explicit rule for remote.{c,dep} to use variable `REMOTE' for more flags. ($(prog)): Link in $(LOADLIBES). Wed Sep 19 02:30:36 1990 Roland McGrath (roland at churchy.ai.mit.edu) * commands.h (struct commands): New member `ncommand_lines', the number of elts in `command_lines' et al. * commands.c (chop_commands): Set `ncommand_lines' elt of CMDS, and don't put a nil pointer at the end of `command_lines'. * job.h (struct child): New member `command_lines' to hold variable-expanded command lines. * job.c (new_job): Store expanded command lines in `command_lines' member of new child. Don't clobber FILE->cmds. (start_job): Use CHILD->command_lines in place of CHILD->file->cmds->command_lines. * variable.h, variable.c, job.c, expand.c: Undo yesterday's change, which is no longer necessary since we have cleverly avoided the issue. * job.c (start_job): Don't variable-expand each command line. (new_job): Do them all here, storing the expansions in the array. Tue Sep 18 01:23:13 1990 Roland McGrath (roland at churchy.ai.mit.edu) * variable.h (struct variable): Remove `expanding' member. * variable.c (define_variable_in_set): Don't initialize it. * expand.c (struct variable_expanding): New type, a linked list containing `struct variable' pointers. (variables_expanding): New variable, the chain of variables currently being expanded. (recursively_expand): Don't test and set `expanding' member. Instead, run through the `variables_expanding' chain looking for a link referring to V to find self-reference. Add a new link to the chain, describing V, before recursive expansion, and pop it off afterward. * job.c (child_handler): Save `variables_expanding' and clear it before calling start_job, and restore it afterward. This avoids major lossage when the SIGCHLD comes in the middle of variable expansion. Mon Sep 17 14:46:26 1990 Roland McGrath (roland at geech.ai.mit.edu) * job.c, commands.c: Don't define sigmask. * make.h: Put it here instead. * variable.c (target_environment): If `.NOEXPORT' was specified as a target, only export command-line and environment variables, and file-origin variables that were in the original environment. * make.man: Add missing ?roff control for `-I' option description. Thu Sep 13 14:10:02 1990 Roland McGrath (roland at churchy.ai.mit.edu) * load.c [UMAX]: Move #include to [not UMAX_43]. Wed Sep 12 15:10:15 1990 Roland McGrath (roland at churchy.ai.mit.edu) * expand.c (recursively_expand): Don't use `reading_filename' and `reading_lineno_ptr' if they're nil. Thu Aug 30 17:32:50 1990 Roland McGrath (roland at geech) * Version 3.58.10. Tue Aug 28 04:06:29 1990 Roland McGrath (roland at churchy.ai.mit.edu) * job.c [USG] (unknown_children_possible): New variable, set nonzero when it's possible for children not in the `children' chain to die. (block_signals) [USG]: Set it. (unblock_signals) [USG]: Clear it. (child_handler) [USG]: Don't complain about unknown children if `unknown_children_possible' is set. * read.c (do_define): Make sure there's enough space for the newline, so we don't write off the end of allocated space. * arscan.c (ar_name_equal): Fixed to work when MEM is AR_NAMELEN-1 but NAME is not the same length. Sat Aug 25 16:17:14 1990 Roland McGrath (roland at geech) * job.c (construct_command_argv_internal): Use a static char array for a constant, since old C has no auto aggregate initializers. Thu Aug 23 16:11:03 1990 Roland McGrath (roland at churchy.ai.mit.edu) * job.c (search_path): If PATH is nil or "" use a default path. Wed Aug 22 01:05:32 1990 Roland McGrath (roland at churchy.ai.mit.edu) * Version 3.58.9. * job.c (exec_command): Don't take PATH and SHELL args. Get them from ENVP. (child_execute_job): Don't take FILE arg, and don't pass path and shell to exec_command. (start_job): Don't pass FILE arg to child_execute_job. * function.c (expand_function: `shell'): Ditto. * main.c (main): Don't pass path and shell to exec_command. Fri Aug 17 23:17:27 1990 Roland McGrath (roland at geech) * job.c (construct_command_argv_internal): New fn broken out of construct_command_argv. Takes strings SHELL and IFS instead of doing variable expansion for them. Recurse to make an argv for SHELL, passing SHELL==0. When SHELL==0, don't recurse for shell argv; make a simple one using /bin/sh. (construct_command_argv): Do the variable expansions and call above. Thu Aug 16 19:03:14 1990 Roland McGrath (roland at geech) * read.c (multi_glob): For ~USER/FILE, if USER isn't found, don't change the file name at all. Tue Aug 7 18:33:28 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * function.c (expand_function: `suffix'/`notdir'): Don't kill the last space if we never wrote one. * function.c (expand_function: `suffix'): Retain the dot, like the documentation says. Mon Aug 6 14:35:06 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.58.8. * main.c (decode_switches): For positive_int and floating cases, move SW past the arg (and don't set it to ""), so another switch can follow. Fri Aug 3 00:43:15 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * job.c (child_execute_job): Use unblock_signals instead of push_signals_blocked_p (0). * main.c (fatal_signal_mask): New variable, mask of signals caught with fatal_error_signal. (main): Set it. * job.c ({block,unblock}_children): Renamed to {block,unblock}_signals. Block/unblock both child signal and signals in fatal_signal_mask. (children_blocked_p_{stack,max,depth}, {push,pop}_children_blocked_p): Renamed from children to signals. Use {block,unblock}_signals instead of {block,unblock}_children. * commands.c (fatal_error_signal), job.c (wait_for_children, new_job, child_execute_job, main, log_working_directory), function.c (expand_function: `shell'), job.h: Rename {push,pop}_children_blocked_p to {push,pop}_signals_blocked_p. * job.c (child_handler): Call {block,unblock}_signals instead of just {block,unblock}_remote_children. We need to block the fatal signals. Thu Aug 2 22:41:06 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * main.c, function.c: Fixed typos in comments. * file.c (print_file_data_base): Fix computation of avg files/bucket. Tue Jul 31 22:11:14 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.58.7. Wed Jul 25 16:32:38 1990 Roland McGrath (mcgrath at tully.Berkeley.EDU) * arscan.c (ar_name_equal): Fixed to really do it right. (ar_member_pos): Fixed order of args. * ar.c (ar_member_date_1): Ditto. Fri Jul 20 15:30:26 1990 Roland McGrath (mcgrath at tully.Berkeley.EDU) * arscan.c (ar_name_equal): Rewritten. Accounts for a possible trailing slash in MEM. * remake.c (f_mtime): Keep track of whether ARNAME is used and free it if not. Also free MEMNAME. * ar.c (ar_member_date, ar_touch): Ditto. * arscan.c (arscan) [HPUX or hpux]: Treat same as USGr3 PORTAR==1. * make.h: If NSIG is not defined, but _NSIG is, #define NSIG _NSIG. * compatMakefile: Don't use $* in explicit rules. * default.c (default_variables: "PREPROCESS.S"): Include $(CPPFLAGS). * remake.c (f_mtime): If FILE is an ar ref, get the member modtime. * function.c (string_glob): Terminate the string properly when it's empty. Wed Jul 18 11:26:56 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.58.6. * commands.c (set_file_variables): Fixed computation for ^F/?F elt len. Sat Jul 14 13:41:24 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * job.c (construct_command_argv): Always use allocated_variable_expand_for_file instead of variable_expand_for_file because we might be called from inside a variable expansion (for the `shell' function). * function.c (expand_function: `shell'): Free the arglist's storage correctly. construct_command_argv only allocates ARGV and ARGV[0]. * job.c (children_blocked_p_idx): Renamed to children_blocked_p_depth. (push_children_blocked_p, pop_children_blocked_p): Use ..._depth instead of ..._idx, and do it right! Wed Jul 11 15:35:43 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.h (SIGNAL): New macro to replace `signal' calls. Does arg and ret value casts to (void *) #ifdef __STDC__ to avoid conflicts btwn ANSI and BSD `signal' and handler types. * main.c (main), job.c (child_handler): Use it. Fri Jul 6 00:00:38 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * ar.c (ar_member_date, ar_touch): Pass 2nd arg to f_mtime. * read.c (read_makefile): Search the include path for MAKEFILES variable makefiles (TYPE == 1), like it says in the manual. * file.h (struct file), main.c (struct command_switch): Remove trailing commas from enums. * commands.c (execute_file_commands): Remove unused variables. * commands.h: Declare chop_commands. * make.h: Declare uniquize_deps. * main.c (main): Remove unused variable. (decode_switches): Remove unused label. * remake.c: Include "ar.h" for ar_parse_name decl. * implicit.c (try_implicit_rule): Remove unused variable. * function.c (expand_function: `shell'): Declare fork, pipe. * ar.c: Declare ar_name_equal. * GNUmakefile: If using gcc, add warning flags to CFLAGS. * remake.c: Remove decl of ar_member_date, since it's done in make.h. * remake.c (f_mtime): For ar refs, allow the archive to be found via VPATH search if we're searching, and change the ar ref accordingly. * ar.c (ar_parse_name): New global fn to parse archive-member references into the archive and member names. (ar_member_date, ar_touch): Use it. * make.h: Declare it. * remake.c (f_mtime): After doing rename_file, do check_renamed instead of assuming rename_file will always set FILE->renamed (which it won't). * vpath.c (selective_vpath_search): Only accept prospective files that don't actually exist yet are mentioned in a makefile if the file we are searching for isn't a target. Wed Jul 4 04:11:55 1990 Roland McGrath (mcgrath at helen.Berkeley.EDU) * remake.c (update_goal_chain): Do check_renamed after calling file_mtime. (check_dep): Ditto after update_file. * file.c (rename_file): Prettied up long message for merging cmds. * remake.c (update_file_1): Get each dep file's modtime, and allow for it being renamed, before checking for a circular dep, since a renaming may have introduced one. Tue Jul 3 18:15:01 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * ar.c (ar_touch): Don't free ARNAME since enter_file holds onto the storage. * function.c (string_glob): Don't leave a trailing space. * read.c (do_define): Allow leading whitespace before `endef'. Mon Jul 2 14:10:16 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * implicit.c (pattern_search): No longer take NAME arg. Instead take ARCHIVE flag. If ARCHIVE is nonzero, FILE->name is of the form "LIB(MEMBER)"; rule for "(MEMBER)" is searched for, and LASTSLASH is set to nil. Since NAME was only non-nil when it was the archive member name passed by try_implicit_rule, this change easily allows turning off LASTSLASH checking for archive members without excessive kludgery. (try_implicit_rule): Pass ARCHIVE flag instead of file name. * Version 3.58.5. * commands./c (set_file_variables): Don't kill last char of $(^D) elts. Sat Jun 30 00:53:38 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * ar.c (ar_member_date): Don't free ARNAME since enter_file holds onto the storage. * arscan.c (ar_scan) [sun386 && PORTAR == 1]: Treat like USGr3. Wed Jun 27 14:38:49 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * main.c (main): Put a newline on the debugging message when deciding not to remake a makefile to avoid a possible loop. Only decide not to remake makefiles that have commands (as well as being targets and having no deps). Fri Jun 22 12:35:37 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * default.c (default_variables): Define `LINK.s' and `LINK.S'. (default_suffix_rules): Define .S.o rule. * job.c (construct_command_argv): If we decide to go the slow route, free all storage for the chopped args. (start_job): Free the argument list's storage correctly. construct_command_argv only allocates ARGV and ARGV[0]. Tue Jun 19 18:27:43 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.58.4. Fri Jun 15 21:12:10 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * glob.c: New version from ai-lab which doesn't do [^abc]. Thu Jun 7 00:30:46 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * dir.c: Copied dirent vs direct et al mess from glob.c. * glob.c: Replaced with updated version from djm. * glob.c: Check macro DIRENT instead of _POSIX_SOURCE for . __GNU_LIBRARY__ implies DIRENT and STDC_HEADERS. Thu May 31 22:19:49 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * vpath.c (vpath_search): Don't stop the loop if a pattern matches but the search fails. All matching patterns have their paths searched (like it says in the manual). * make.texinfo (Rules: Directory Search: Selective Search): Say that multiple `vpath' directives with the same pattern DO accumulate, not supersede earlier ones. * vpath.c (print_vpath_data_base): Increment the count of vpaths on each loop iteration, rather than letting it stay zero. * Version 3.58.3. * job.c (block_children, unblock_children): Made static. (push_children_blocked_p, pop_children_blocked_p): New functions to push and pop whether children are blocked or not. * job.h: Declare push_children_blocked_p, pop_children_blocked_p and not block_children, unblock_children. * commands.c (fatal_error_signal), job.c (wait_for_children, new_job, child_execute_job), main.c (main, log_working_directory): Use sequences of push_children_blocked_p (1) and pop_children_blocked_p () instead of explicitly blocking and unblocking children. * function.c (expand_function: `shell'): Don't unblock children. The push-pop sequence in wait_for_children makes it unnecessary. Tue May 29 21:30:00 1990 Roland McGrath (mcgrath at helen.Berkeley.EDU) * read.c (do_define): Don't include the last newline in the definition. * function.c (expand_function: `shell'): Call construct_command_argv before forking and don't fork if it returns nil. Free the argument list's storage before finishing. * job.c (start_job): Free the storage for the child's argument list in the parent side of the fork after the child has been spawned. * job.c (start_job): If construct_command_argv returns nil, go to the next command line. * job.c (construct_command_argv): Use the shell if the command contains an unterminated quote. Wed May 23 19:54:10 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.58.2. * read.c (read_makefile): Parse "override define" correctly. Thu May 17 15:25:58 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * arscan.c [USG]: Don't declare memcpy and memcmp. should do this anyway (and lack of declarations is harmless). * remote-customs.c: Renamed to remote-cstms.c for System V. * remote.c [CUSTOMS]: Changed accordingly. Sun May 13 14:38:39 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * GNUmakefile: Use same cmds for doc tar.Z as for dist tar.Z (so the contents go in make-N.NN). Thu Apr 26 19:33:25 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.58.1. Wed Apr 25 20:27:52 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * job.c (init_siglist): Don't do SIGUSR1 and SIGUSR2 if they are the same as SIGIO and SIGURG (true on Cray). Tue Apr 24 20:26:41 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * arscan.c (ar_scan): Do behavior for PORTAR == 1 and USGr3 also #ifdef APOLLO. Wed Apr 11 10:00:39 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * job.c (exec_command): Set the effective GID to the real GID. Somehow this code got lost. * implicit.c (pattern_search): Use the right index variable when seeing if we need to expand FILE->also_make. Sun Mar 4 09:18:58 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.58.0. * remake.c (remake_file): Treat non-targets without commands under -t the same as anything else without commands. Sat Feb 24 17:46:04 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * default.c (default_variables: PREPROCESS.S): Removed $< from defn. * main.c (main): Ignore arguments that are the empty string, rather than feeding them to enter_file and barfing therein. Wed Feb 14 16:28:37 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * main.c (main): Call construct_include_path after doing chdirs. Thu Feb 8 13:43:44 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.58. Sat Feb 3 22:06:55 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.57.7. * make.texinfo (Implicit: Catalogue of Rules): For RCS, noted that working files are never overwritten by the default rule. Thu Feb 1 17:27:54 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * rule.c (count_implicit_rule_limits): Redid loop control to not run twice on freed rules. * GNUmakefile: Made `.dep' files be architecture-specific too. * main.c (main, log_working_directory) [USG]: Block children around calls to `getwd' (actually `getcwd' on USG), because that function sometimes spawns a child running /bin/pwd on USG. Tue Jan 30 14:02:50 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * function.c (subst_expand): Pay attention to SUFFIX_ONLY, putz. Wed Jan 24 21:03:29 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * make.man: Fixed repeated word. * make.texinfo (Missing): Reworded a buggy sentence. Mon Jan 22 12:39:22 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * main.c (print_version): Added 1990 to copyright notice. * Version 3.57.6. Sat Jan 20 11:52:01 1990 Roland McGrath (mcgrath at homer.Berkeley.EDU) * file.c (rename_file): Don't free the storage for the old name, since it might not have been malloc'd. * job.c (construct_command_argv): Call allocated_variable_expand_for_file instead of variable_expand_for_file to expand `$(SHELL)'. * make.texinfo (Bugs): Change address from roland@wheaties.ai.mit.edu to roland@prep.ai.mit.edu. Tue Jan 16 19:22:33 1990 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.57.5. Sun Jan 14 16:48:01 1990 Roland McGrath (mcgrath at helen.Berkeley.EDU) * job.c (start_job): Only call wait_to_start_job for the first command line in each sequence. Thu Jan 4 14:27:20 1990 Roland McGrath (mcgrath at helen.Berkeley.EDU) * load.c [LDAV_BASED] (wait_to_start_job): Loop while job_slots_used > 0, not > 1. * job.c (search_path): Don't return a pointer to local storage. Allocate data space for the pathname instead. * function.c (expand_function: `shell'): Don't write garbage if the child wrote no output. Wed Jan 3 15:28:30 1990 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.57.4. * file.h (struct file): New member `renamed', a `struct file *' that is the place this file has been renamed to (or nil). (check_renamed): Macro to check for a file having been renamed. Dereferences the renaming and sets the given variable. * file.c (rename_file): Completely rewritten. Renames in place if possible, or moves FILE to a different hash bucket if there is no existing file with the new name. If there is an existing file with the new name, FILE is merged into it and FILE->renamed is set to point to it. * variable.c (merge_variable_sets): New fn to merge two variable sets. (merge_variable_set_lists): New fn to merge two variable set lists. * variable.h: Declare merge_variable_set_lists. * remake.c (update_file_1, check_dep): Run `check_renamed' after calling file_mtime, check_dep. (update_file): Same after update_file_1. (update_goal_chain, update_file_1, check_dep): Same after update_file. * read.c (uniquize_deps): New fn, broken out of record_files, to remove duplicate deps from a chain. (record_files): Use it. * implicit.c (pattern_search): Use uniquize_deps. * file.h (file_mtime_1): New macro, like file_mtime, but take second arg, passed to f_mtime. (file_mtime): Implement as file_mtime_1 (file, 1). (file_mtime_no_search): New macro: file_mtime (file, 0). * remake.c (f_mtime): Take new arg SEARCH. Only do VPATH and `-lNAME' searching if it is nonzero. * main.c (main): Use file_mtime_no_search for makefiles. * remake.c (update_goal_chain): Use file_mtime_no_search if MAKEFILES. * main.c (printed_version): New variable, init'd to zero. (print_version): Set it to nonzero before returning. (die): If -v and !printed_version, call print_version before clean up and death. * main.c (log_working_directory): Keep track of whether or not the "Entering" message has been printed, and return without printing the "Leaving" message if not. * main.c (decode_switches): Don't complain about missing args before checking for a noarg_value elt in the command_switch structure. Tue Jan 2 15:41:08 1990 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.texinfo (Commands: Recursion: Options/Recursion): Document special case of -j. * make.texinfo, main.c, job.c: Changed copyright notices to include 1990. * make.texinfo (Top): Fixed introductory paragraph, which said that `make' itself (instead of the manual) has various chapters. (Variables: Advanced: Substitution Refs): When pxref'ing about `patsubst', use node `Text Functions', not `Functions'. Add an xref about `patsubst' after description of $(var:a%b=c%d). (Functions: Syntax of Functions): Explain why mixing delimiters in function/var refs is unwise. Clarify fn arg evaluation order. (Options): Reworded sentence about `-e'. (Implicit: Implicit Variables): Don't say `RM' is unused. Say the dflt values for the flag vars is empty unless otherwise noted, since some have defaults. (Implicit: Pattern Rules: Pattern Examples): Clarified use of $< and $@ in first example. (Implicit: Last Resort): Don't say the .DEFAULT example creates files "silently". It's automatic, but not silent. (Implicit: Search Algorithm): Fixed confusing ungrammatical sentence for item 5.1. (Archives: Archive Update): Added missing `next' pointer. (Archives: Archive Symbols): Note that GNU `ar' deals with this automatically. * job.c (search_path): New fn, to search for an executable file in a search path (broken out of exec_command). (exec_command): Take fourth arg, the shell program to use (if necessary). Use search_path for the program, and the shell program. Pass args "file args ..." to shell program (with no -c), where FILE is the full pathname of the program (script) to be run. (child_execute_job): Pass shell program to exec_command. * main.c (main): Ditto. * main.c (main): Don't write a message if exec_command returns, because it will never return. Fri Dec 22 16:19:58 1989 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * default.c (default_variables: "LINK.cc"): Use $(C++FLAGS) instead of $(CFLAGS). Wed Dec 20 09:58:48 1989 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * job.c (new_job): If start_job set the child's `command_state' to `cs_finished', call notice_finished_file. Sun Dec 17 19:45:41 1989 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * Version 3.57.3. Wed Dec 13 17:57:12 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * rule.c (convert_to_pattern): Accept files with dependencies as suffix rules. Thu Nov 30 15:47:13 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.57.2. * function.c (expand_function: `shell'): Don't clobber BUFFER and then try to free it. * remake.c (update_file_1): Took code to force remake of nonexistent deps out of #if 0, and changed the test to nonexistent non-intermediate deps. In version 4, I think removing this test completely will implement the new feature that if a: b and b: c and c is newer than a, b need not be remade. Sun Nov 26 16:12:41 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * compatMakefile (load.o, remote.o): Use $*.c instead of explicit file names so that using VPATH works. Tue Nov 21 14:57:18 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.57.1. Fri Nov 10 03:28:40 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remake.c (check_dep): Set *MUST_MAKE_PTR if FILE does not exist after being updated. (The exact opposite test was here before; why???) (update_file_1): Set a dep's `changed' member after updating it if it is phony and has commands (because they will then always be executed). Thu Nov 9 13:47:12 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * load.c [UMAX]: #ifdef UMAX_43 include different headers for the `inq_stats' call. * compatMakefile (LOAD_AVG): Document UMAX_43. * Version 3.57.0. * commands.c (chop_commands): New function to chop commands into lines. * job.c (new_job): Break that code out, and call chop_commands. * remake.c (remake_file): Call chop_commands before looking at FILE->cmds->any_recurse. * make.texinfo (Running: Goals): Don't say that the default target won't be taken from an included makefile. * remake.c (update_file_1): #if 0 out setting MUST_MAKE if a dep doesn't exist. Fri Nov 3 15:53:03 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.57. * variable.c (try_variable_definition): Don't calculate useless value. * main.c (define_makeflags): Fixed -j propagation. * commands.c (execute_file_commands): Removed unused variable. Sun Oct 29 11:11:15 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (execute_file_commands): If the commands are empty, call notice_finished_file before returning. Sat Oct 28 23:06:32 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remake.c (update_file_1): Don't always update a target that has no deps. Only do this for double-colon targets. Wed Oct 25 16:36:16 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * main.c (main) [hpux]: hpux == HPUX. * compatMakefile (defines): Document that HPUX should be defined. Tue Oct 24 19:19:48 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.8. * job.c (exec_command): Fixed what mode bits are checked. * remake.c (update_file_1): "No cmds and no deps actually changed" loses if ! FILE->is_target. * make.texinfo (Variables: Setting): Don't say that spaces after a variable definition are ignored (since they aren't). Mon Oct 23 14:34:23 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.7. * remake.c (update_file_1): If, after being updated, any dependency does not exist, remake the target. * remake.c (update_file_1): Always update if FILE has commands but no deps. * commands.c (execute_file_commands): If we return early because there are no commands, set FILE->updated. Thu Oct 19 18:47:37 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * arscan.c (ar_scan) [M_XENIX]: Don't run atoi or atol on the `struct ar_hdr' members that are int or long int on Xenix. Sat Oct 14 10:43:03 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * arscan.c (ar_scan): Cosmetic clean ups. (ar_name_equal): New function to compare names, handling truncated member names and special `.o' truncation. (ar_member_pos): Use ar_name_equal. * ar.c (ar_member_date_1): Use ar_name_equal. * Version 3.56.6. * file.h (struct file): Made `update_status' a `short int', and moved it before `command_state' so the bitfields can be packed better. * remake.c (files_remade): Made global. (notice_finished_file): Don't increment files_remade. * job.c (new_job): Do. * job.c (start_job): Don't return a value. Always set CHILD->file->command_state to either cs_running or cs_finished. (new_job, child_handler): Don't expect start_job to return a value. Instead, look at the file's command_state. * commands.c (chop_commands): Merged into job.c (new_job). * commands.h: Don't declare chop_commands. * job.c (start_job): Made static. (new_job): New function to create a `struct child' and call start_job. (free_child): New function to free a `struct child'. (child_handler, new_job): Call it. * job.h: Don't declare start_job. Do declare new_job. * commands.c (execute_file_commands): Call new_job. * commands.c (execute_file_commands): Don't set FILE->update_status if start_job fails. * function.c (expand_function): Don't use `reading_filename' and `reading_lineno_ptr' if they're nil. Fri Oct 13 18:16:00 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * read.c (find_semicolon): New function to look for an unquoted ; not preceded by an unquoted # in a string. (read_makefile): Call it before expanding the line. If it finds a ;, cut the line short there before expanding it. If not, call it again after expanding. * commands.c (execute_file_commands): Don't check FILE->command_state. We won't get called unless it's cs_not_started. * read.c (read_makefile): Call collapse_line on the variable-expanded rule line after checking for ; and #. * job.c (start_job): When there are no more commands, always return 0. * commands.c (execute_file_commands): Don't put the new child in the `children' chain unless FILE->command_state is cs_running. * read.c (read_makefile): Rewrote ;-handling to only do it once (why did I do it twice??) and to check for a # before the ;. * job.c (start_job): Set CHILD->file->update_status to 0 when we run out of commands. Set it to 1 before returning failure. (child_handler): Don't set C->file->update_status to 0 when start_job returns success and commands are not running. * read.c (read_makefile): If there is a # before the ; for commands, forget the ; and commands. Thu Oct 12 15:48:16 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * job.c (child_execute_job): Pass -c to the shell. Wed Oct 11 18:41:10 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.5. * main.c (define_makeflags): Cleaned up to keep better track of dashes written, etc. * function.c (expand_function: `shell'): When converting newlines to spaces in output, search with `index' calls rather than a simple loop. * main.c (main): Make sure stdout is line-buffered. * main.c (decode_switches): Always check for missing switch arg. Mon Oct 9 17:17:23 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.4. Sat Oct 7 00:32:25 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (set_file_variables): #ifdef NO_ARCHIVES, still set $@ and $%. * commands.c (set_file_variables): Include a trailing slash in the directory variables (@D, etc.). * job.c (child_handler): Call notice_finished_file after changing a child's state to `cs_finished'. * remake.c (update_file_1): Don't call notice_finished_file if FILE->command_state == cs_finished. Wed Oct 4 16:09:33 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.3. Tue Oct 3 21:09:51 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * read.c (read_all_makefiles): When setting elements of MAKEFILES from the contents of read_makefiles, make sure we're using the right element. * dir.c, glob.c [USGr3 || DIRENT]: Don't define d_ino as d_fileno. * Version 3.56.2. * remake.c (update_file_1): Return zero after calling remake_file if FILE->command_state != cs_finished. Test update_status thoroughly. * commands.c (execute_file_commands): Don't call notice_finished_file. * remake.c (remake_file): Return immediately after calling execute_file_commands. Sat Sep 30 14:57:05 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56.1 (alpha). * file.h (struct file): Made `update_status' not be a bitfield, since some broken compilers don't handle it right. * function.c (expand_function: `join'): Don't clobber the pointers and then try to free them. * job.c (exec_command): Fixed & vs = precedence problem. Thu Sep 28 17:29:56 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remake.c (update_file_1): Fixed typo in debugging output. * remake.c (library_file_mtime): Search for /usr/local/lib/libLIB.a after /usr/lib/libLIB.a. Tue Sep 26 16:07:58 1989 Roland McGrath (mcgrath at helen.Berkeley.EDU) * read.c (conditional_line): For `ifeq (a, b)', swallow space after the comma. Sun Sep 24 13:25:32 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * function.c (patsubst_function): If BY_WORD and the match is not a full word, update the text pointer correctly. * function.c (expand_function: `word'): Don't lose track of the second arg's expansion and free something else instead. Fri Sep 22 16:15:29 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.56. Thu Sep 21 14:28:42 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * main.c (main): Make an array of the mtimes of the makefiles before updating them, and compare their file_mtimes against this later. Don't re-exec if a makefile was successfully updated but didn't change. If a makefile failed to be remade and no longer exists, die. If a makefile failed to be remade, but changed anyway, re-exec. If a makefile failed to be remade, but is unchanged, continue on. Wed Sep 20 18:02:07 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.55.6. * implicit.c (pattern_search): Maintain an array CHECK_LASTSLASH of the CHECK_LASTSLASH flag values used to match each member of TRYRULES. When making FILE->stem, if CHECKED_LASTSLASH[FOUNDRULE], prepend the part of FILENAME before LASTSLASH. Tue Sep 19 17:44:08 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * dir.c (dir_file_exists_p): Check for FILENAME being nil before checking for it being "". * main.c (define_makeflags): Fixed test for whether a flag/flag_off option was non-default. Also changed to generate a string that Unix Make will grok (except for FP/int values and new flags). * job.c (child_execute_job): Don't use the shell's -c option. Also fixed an off-by-one bug in the ARGV -> shell arg list copying. Mon Sep 18 15:17:31 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.55.5. * read.c (parse_file_seq): Check the beginning of the file name for a `./', not the two chars after the end of the name (Q rather than P). * job.c (child_execute_job): Include all of ARGV in the arg list for the shell. * main.c (define_makeflags): Don't include floating and positive_int options in !PF. * job.c (exec_command): Set the effective gid to the real gid before execing. * job.c (child_execute_job): Don't clobber the arg list when execing the shell. Sun Sep 17 15:27:19 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * main.c (define_makeflags): Moved all the checking inside the switch. * load.c [LDAV_BASED] (load_average): When we can't get the load average, return zero instead of running off the end. * file.c: Include variables.h. * job.c: Declare dup2 and {block,unblock}_remote_children. * file.h: Declare f_mtime. * job.c: Don't declare construct_command_argv, since job.h does. * function.c, main.c, load.c, remake.c: Include job.h. * load.c [LDAV_BASED] (load_average): Declare nlist. * variable.h: Declare print_file_variables. * job.c [!USG]: Don't declare sigsetmask. [!USG]: Declare getdtablesize. Don't declare load_average. Do declare wait_to_start_job. Declare vfork, gete[gu]id, execve. * commands.c: Declare remote_kill, getpid. * make.h: Declare kill, exit, sigblock, pipe, close, ctime, open, lseek, read. * make.h [not USG]: Declare sigsetmask. * job.h: Declare wait_for_children and {block,unblock}_children. * dir.c (dir_file_exists_p): If FILENAME is nil, read in the whole directory. (find_directory): When we want to read in the whole directory, call dir_file_exists_p with nil instead of "". * file.h (struct file), job.h (struct child), variable.h (struct variable): Use bitfields for flags. * make.h (ENUM_BITFIELD): If GCC or #ifdef ENUM_BITFIELDS, define as :BITS, else empty. * compatMakefile (defines): Document ENUM_BITFIELDS. Sat Sep 16 12:38:58 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.55.4 (alpha). * GNUmakefile (dist): Depend on default and doc. * load.c [LDAV_BASED]: Include rather than ; #ifdef NLIST_NAME_UNION, use n_un.n_name instead of n_name. * compatMakefile (LOAD_AVG): Document NLIST_NAME_UNION. * job.c [USG-ish]: Don't redefine WIF{SIGNALED,EXITED} if they're already defined. Fri Sep 15 13:59:42 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * glob.c, dir.c [USGr3 or DIRENT]: If neither d_ino, nor d_fileno is defined, define d_ino as d_fileno. Thu Sep 14 18:29:38 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * job.c: Don't declare exec_command static. * make.texinfo (Name Index): Changed title to include directives. * Version 3.55.3 (alpha). * make.texinfo (Running: Options): Document -e. * main.c (main): Always give imported environment variables origin `o_env'. * variable.c (define_variable_in_set): Under -e, if ORIGIN, or an existing variable's origin, is `o_env', make it `o_env_override'. * load.c: Use the symbol KERNEL_FILE_NAME instead of KERNEL_FILE. * compatMakefile: Changed the comment for `LOAD_AVG' accordinly. Thu Sep 7 16:46:26 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.55.2 (alpha). * variable.c (print_variable_set), rule.c (print_rule_data_base), file.c (print_file_data_base): If NO_FLOAT is defined, don't use floating-point for printing statistics. * compatMakefile (defines): Document NO_FLOAT. * make.h (HASH): New macro to add the hashing value of one char to a variable.c. * file.c (lookup_file, enter_file, rename_file): Use it. * dir.c (find_directory, dir_file_exists_p, file_impossible_p): Ditto. * variable.c (define_variable_in_set, lookup_variable): Same here. * variable.c, file.c, dir.c: Don't define *_BUCKETS if they are already defined. * compatMakefile (defines): Added comment about defining NO_ARCHIVES. (ARCHIVES, ARCHIVES_SRC): New variables for {ar,arscan}.[oc]. (objs, srcs): Use $(ARCHIVES) and $(ARCHIVES_SRC). * commands.c (set_file_variables), dir.c (file_exists_p), remake.c (touch_file, name_mtime), implicit.c (try_implicit_rule, pattern_search), make.h: If NO_ARCHIVES is #defined, don't do any archive stuff. * commands.c (set_file_variables): Don't kill the last char of directory names in $([@*<%?^]D). Wed Sep 6 15:23:11 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * default.c (default_terminal_rules {%:: %,v}, {%:: RCS/%,v}): Don't run co if the target exists. * glob.c (glob_match): [!xyz], rather than [^xyz], means none of [xyz]. * glob.c: Misc minor cosmetic changes. Tue Sep 5 14:49:56 1989 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * load.c [LDAV_BASED] (load_average): Check for == -1, rather than < 0 to see if lseek fails. On some systems, `avenrun' is at an offset > (2**31)-1, and lseek succeeds, returning a negative value. Mon Sep 4 11:07:58 1989 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * rule.c (new_pattern_rule): Return `int' instead of `void': nonzero if the passed rule was used, zero if not. (install_pattern_rule): Pay attention to the return from new_pattern_rule, and don't set the rule's `terminal' flag or give it commands unless it's used. (create_pattern_rule): Same idea. * dir.c (find_directory): Removed unused variable. * commands.c (execute_file_commands): Removed unused variable. * read.c (record_files): Don't use NAME after freeing it. Sat Sep 2 00:33:19 1989 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * Version 3.55.1 (alpha). * function.c (string_glob): Don't add spaces after file names that aren't added. (Also means don't add spaces without checking the size of the buffer.) * remake.c (update_goal_chain): Don't remove makefiles with cmds and no deps from the chain. * main.c (main): Do it here, before calling update_goal_chain. * remake.c (update_goal_chain): When updating fails, change STATUS even if MAKEFILES is set. Also stop remaking when updating fails if not under -k and MAKEFILES is not set. * remake.c (remake_file, update_file_1, notice_finished_file), commands.c (execute_file_commands), make.h, commands.h: The functions remake_file, notice_finished_file, and execute_file_commands no longer return values, and their callers no longer expect values returned. * remake.c (notice_finished_file): Don't set FILE's modtime to now if it is a non-target with no commands. Fri Sep 1 00:04:39 1989 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * read.c (read_all_makefiles): After freeing each element on MAKEFILES, replace it with the name stored in read_makefiles by read_makefile. * remake.c (update_file_1): Don't decide not to remake if FILE has no cmds and no deps actually changed if FILE doesn't have any deps. * file.c (remove_intermediate): Remove precious files that also have the `dontcare' flag set. * remake.c (update_file_1): Don't always remake if FILE has cmds but no deps; only if FILE is double-colon. (I don't know why this should be done for double-colon targets, but that's what Unix make does.) * load.c [LDAV_BASED] (load_average): Write error messages if the various system calls fail. Keep track of if we've failed before. The first time we fail, write a message saying -l won't be enforced. The first time we succeed after having failed, write a message saying -l will be enforced again. * remake.c [USG]: Don't #include * load.c [generic Unix LDAV_BASED]: #include #ifdef USG, else instead. * job.c [USG && !USGr3 && !HAVE_DUP2]: Remove redundant #include and declaration of `errno'. [...] (dup2): Fixed so it won't always lose. * default.c (default_suffix_rules: .texinfo.dvi): Copy, rather than move, the aux and index files, so the TeX run can use them. * compatMakefile: Remove redundant comment. * load.c [generic Unix LDAV_BASED]: Include instead of , since the `struct nlist' declaration in varies more than the one in . (load_average): Use the `n_un.n_name' field of the `struct nlist', since the declaration uses the union. * main.c (main): For the temporary files made for stdin makefiles, set the `intermediate' and `dontcare' flags. * file.c (remove_intermediates): Don't print any messages for files whose `dontcare' flag is set. (The only files that will be intermediate and `dontcare' will be the temporary files made for stdin makefiles.) * job.c (exec_command): Made global. * job.h: Declare it. * main.c (main): Use exec_command when re-execing. * make.h: Declare environ. * make.c: Don't. * job.c (child_execute_job): New function to perform everything done in the child side of a fork (for a job or `shell' function). (start_job): Call it. * job.h: Declare construct_command_argv and child_execute_job. * function.c (expand_function: `shell'): Use child_execute_job. Thu Aug 31 18:42:51 1989 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * function.c (expand_function: `shell'): Remove a trailing newline instead of turning it into a space. * main.c (main): Do init_siglist #ifdef HAVE_SIGLIST. * job.c [WTERMSIG || (USG && !HAVE_SYS_WAIT)]: Test each W* macro separately and define all those that aren't defined. Sat Aug 26 15:13:21 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * ar.c (ar_name): Return zero for `(foo)'. * Version 3.55. * make.texinfo (Rules: Multiple Targets): Make this node's `next' pointer point to `Static Pattern'. * make.texinfo (Makefiles: MAKEFILES Variable): Make this node's `prev' pointer point to `Makefile Names'. * make.1: Renamed to make.man. * compatMakefile: Define `mandir' and `manext'. (install): Depend on $(mandir)/make.$(manext). ($(mandir)/make.$(manext)): Depend on make.man and copy it to $@. ($(bindir)/make): Use `make' rather than $<; so Unix make can grok it. Thu Aug 24 03:35:48 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * variable.c (target_environment): Allow variables that start with underscores. Wed Aug 23 22:50:32 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * variable.c (target_environment): Reject variables that don't start with letters. Tue Aug 22 04:14:29 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * GNUmakefile (make-$(version).tar.Z): Put make.1 (the Unix manual page) in the tar file. * variable.c (target_environment): Don't write variables with origin o_default (i.e., ones from default.c). * make.texinfo (Commands: Recursion: Variables/Recursion): Document that default variables are not put in the environment. * remake.c (update_file_1): Remake all targets with commands but no deps. Sat Aug 19 06:03:16 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (update_file_1): In the final loop, set the deps' `changed' members if they are newer than FILE. * remake.c (update_goal_chain): Under -d, print a message if we decide not to remake a makefile so as to avoid a possible infinite loop. Fri Aug 18 20:30:14 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (remake_file): Cleaned up. * commands.c (execute_file_commands): If the commands are empty, set FILE->update_status to zero before returning. * remake.c (notice_finished_file): Set `last_mtime' fields to zero instead of calling name_mtime; file_mtime will do that later if anybody cares. Thu Aug 17 10:01:11 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * make.texinfo (Rules: Wildcards: Wildcard Examples): Give this node a `prev' pointer. * Version 3.54.9 (alpha). * make.texinfo: Fixed some @nodes. * remake.c (check_dep): Don't set *MUST_MAKE_PTR if FILE doesn't exist after running update_file. * remake.c (notice_finished_file): If FILE has no commands, pretend its modtime is now. * remake.c (update_file_1): In the loops that call update_file on the deps, compare modtimes before and after (unless deps are still being made) and set the deps' `changed' members. Do not set the `changed' members in the loop that prints the newer/older debugging messages. * remake.c (update_file_1): If no deps changed and FILE has no commands, decide it doesn't need remaking. * remake.c (update_file_1): Print a debugging message if we take commands from default_file. * make.texinfo (Rules: Directory Search: Selective Search): Removed note about warning for `vpath' with a constant pathname, since it isn't warned about anymore. * remake.c (update_goal_chain): If MAKEFILES, remove makefiles which are targets and have no deps. * make.texinfo (Makefiles: Remaking Makefiles): Document that makefiles will not be remade if they are targets but have no dependencies. Tue Aug 15 00:00:08 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) * remake.c (notice_finished_file): Increment files_remade for non-phony files if they didn't exist before (even if they still don't). * job.c: Include and declare errno. * job.c (exec_command): If the execve fails with ENOEXEC (Exec format error), return instead of exiting the child process. * job.c (start_job): In the child side, if exec_command fails, try using the shell. * job.c (start_job): In the child side, call unblock_children instead of sigsetmask. * remake.c (notice_finished_file): Under -n or -q, always increment files_remade for non-phony files. * rule.c (intall_pattern_rule): Use find_percent. * vpath.c (vpath_search): Pass the `percent' members to pattern_matches. Mon Aug 14 23:30:24 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) * vpath.c (struct vpath): New member `percent', to hold a pointer into the pattern where the % is. (construct_vpath_list): Call find_percent on the pattern and set the new `percent' member. * read.c (read_makefile): Don't run find_percent on `vpath' directive patterns. * function.c (pattern_matches): Take new arg PERCENT, a pointer into PATTERN where the % is. If PERCENT is nil, copy PATTERN into local space and run find_percent on it. (expand_function: `filter', `filter-out'): Pass new arg to pattern_matches. * read.c (record_files): Pass PATTERN_PERCENT to pattern_matches for static pattern rules. Save the percent pointer into implicit rule targets, and pass them to create_pattern_rule. * rule.c (convert_to_pattern): Pass new arg to create_pattern_rule. (create_pattern_rule): Take new arg TARGET_PERCENTS, nil or an array of pointers into the corresponding elements of TARGETS, where the %s are. Sun Aug 13 00:29:19 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54.8. * README.templatate, README-doc.template: New files, turned into README and README-doc to go into the two distribution tar files. * GNUmakefile: Added a rule to edit the version number in README.template and README-doc.template, producing README and README-doc. * remake.c (update_goal_chain): If -n or -q is in effect for a makefile, and it got updated, don't change STATUS, so we can still return -1 (meaning nothing was done). This avoids an infinite loop on "make -n Makefile". Sat Aug 12 23:14:24 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (notice_finished_file): Treat -q the same as -n. * remake.c (update_goal_chain): Fixed handling of return from update_file. If -n or -q is in effect, ignore it. * job.c (start_job): Don't test for -t. We should never get called in that case. Fri Aug 11 04:09:14 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * function.c (expand_function): Removed unused variables. (handle_function): Removed unused variable. * main.c (main): Removed unused variable. Wed Aug 9 09:37:10 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54.7. * remake.c (notice_finished_file): If FILE's modtime actually changed, increment files_remade. (remake_file): Don't increment files_remade. * remake.c (update_file): Don't print "up to date" messages for phony files. * job.c (child_handler): Don't set C->file->update_status to 1 if start_job returns nonzero under -n or -t. * expand.c (variable_expand): Count parens in $(foo:a=b) refs. * main.c: Removed old declaration of `glob_tilde' (which hasn't existed for a few months). Tue Aug 8 23:53:43 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * job.c (exec_command): Fixed to not ignore the last path component and to do the right thing with an empty path. Fri Aug 4 15:58:19 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (library_file_mtime): Look for libLIB.a, not /libLIB.a. Do VPATH search on libLIB.a, not /usr/lib/libLIB.a Thu Aug 3 20:42:00 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * job.c [HAVE_SYS_WAIT or not USG]: If WIFSIGNALED is not defined by , define it as (WTERMSIG != 0). Tue Aug 1 19:25:34 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (remake_file): If FILE has no commands and is a target, don't set its time to now. The time gets reset by notice_finished_file anyway, and it isn't needed since check_dep checks for nonexistence. * Version 3.54.6. * read.c (read_makefile): Don't read off the end of the string after an `include'. * job.c (exec_command): New function to search the path for a file and execute it. (start_job): Use exec_command rather than execvp. * read.c (read_makefile): Expand `include' directive args before parsing them. Allow trailing whitespace after filename. * variable.c (target_environment): Put makelevel + 1, rather than makelevel, in the `MAKELEVEL' envariable. Sat Jul 29 10:27:04 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * remake.c (notice_finished_file): Don't get the new modtime of phony files. * remake.c (remake_file): Run commands instead of touching under -t if FILE->cmds->any_recurse is set. * commands.h (struct commands): Add new member `any_recurse', to be set nonzero if any `lines_recurse' element is nonzero. * commands.c (chop_commands): Set the `any_recurse' member. * commands.c (execute_file_commands): Split chopping of commands into lines into new function chop_commands. * commands.h: Declare chop_commands. * read.c (read_makefile): Test for a line beginning with a tab after checking for conditional lines, but before all other checks. Fri Jul 28 18:10:29 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * read.c (read_makefile): Match directives against collapsed line and use that for their args. * read.c (read_makefile): Warn about extra text after `include'. Tue Jul 25 14:34:25 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * make.texinfo (Rules: Directory Search: Selective Search): Fixed example to use correct `vpath' syntax. Mon Jul 24 12:10:58 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54.5. * job.c (start_job): In the child side, unblock SIGCHLD. Fri Jul 21 18:25:59 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * make.h: Don't include #ifdef sun. Mon Jul 17 14:29:10 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * implicit.c (pattern_search): If ar_name (FILENAME), don't check for directory names. * job.c (wait_for_children): Changed "waiting for children" message to "waiting for unfinished jobs". Fri Jul 14 13:17:13 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * load.c (load_average): Use an unsigned offset into kmem. Thu Jul 13 18:44:49 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * variable.c (pop_variable_scope): Don't free the head of the chain of variables in each bucket twice. Tue Jul 11 06:45:24 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * GNUmakefile: Include COPYING in the doc tar file. * variable.c, read.c, misc.c, job.c, function.c: Replace some identical "for" loops with next_token or end_of_token calls. Mon Jul 10 16:55:08 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54.4. * compatMakefile: Documented new conditionals. * job.c: Don't define sys_siglist if HAVE_SIGLIST is defined. Don't define dup2 if HAVE_DUP2 is defined. * job.c (child_handler): Interpret the return from start_job correctly. * remake.c (update_file_1): Don't write "target not remade because of errors" message under -n or -q. * read.c: Declare getpwnam. * glob.c: Use if DIRENT is defined. [USG]: Don't declare memcpy, since does. Fri Jul 7 20:53:13 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * misc.c (collapse_line): Copy the line over in the right place. Fri Jul 7 18:33:24 1989 Roland McGrath (fsf at void.ai.mit.edu) * remake.c: Conditionalize inclusion of on not USG, since HP-UX defines a `struct file' there. Fri Jul 7 12:11:30 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * job.c: If WTERMSIG is defined by , define WAIT_T as int, and don't define other macros; this covers HP-UX. If WTERMSIG is not defined, use int or union wait based on USG and HAVE_SYS_WAIT; this covers BSD and SysV. * Version 3.54.3 (alpha). * job.c [USG and not USGr3]: Include and declare errno. * job.c (unblock_children [USG]): Declare child_handler. * job.c: Renamed WRETCODE to WEXITSTATUS. [HAVE_SYS_WAIT or not USG]: Undefine WTERMSIG, WCOREDUMP, and WEXITSTATUS before defining them. The HP-UX defines them. * main.c (main): If there are no goals, fatal AFTER printing the data base under -p. Thu Jul 6 22:43:33 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) * glob.c [USG]: #define rindex as strrchr. * job.c [USG]: Include and #define getdtablesize() as NOFILE. Wed Jul 5 09:36:00 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54.2 (alpha). * expand.c (variable_expand): When expanding recursive variable references (${${a}}), use the correct delimiters in the constructed variable reference. Mon Jul 3 18:29:26 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) * compatMakefile: Clear out and redefine the .SUFFIXES list because silly Sun 4 make defines .cps.h. * compatMakefile: Fix comment about -DNO_MINUS_C_MINUS_O. * remake.c: Include for O_* on 4.2. * commands.c: Define sigmask if it's not defined. Fri Jun 30 07:33:08 1989 Roland McGrath (roland at apple-gunkies.ai.mit.edu) * remake.c (remake_file): Don't always increment files_remade. * variable.c (push_new_variable_scope): Zero the new variable hash table. Thu Jun 29 17:14:32 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * expand.c (variable_expand): When terminating the variable expansion buffer, use variable_buffer_output instead of a simply zero store, because the buffer may need to be enlarged. Wed Jun 28 16:53:47 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.54. * default.c (default_suffixes): Added `.ln'. (default_suffix_rules): Changed lint rules to use -C. Thu Jun 22 20:49:35 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * job.c (start_job): Set `environ' to CHILD->environment before execing in the child process! Tue Jun 20 17:23:13 1989 Roland McGrath (roland at spiff.ai.mit.edu) * compatMakefile: Put job.h and rule.h in `srcs'. * Version 3.53. Mon Jun 19 16:25:18 1989 Roland McGrath (roland at spiff.ai.mit.edu) * job.c (start_job): If there are no more commands, return nonzero under -n or -t. * compatMakefile (make): Pass `-f' to mv. * GNUmakefile: If `ARCH' or `machine' is defined, make $(ARCH)/*.o and $(ARCH)/make instead of *.o and make. * function.c (string_glob): Don't try to use freed storage! * read.c (readline): If there is only one byte of space in the buffer, enlarge the buffer before reading more. * arscan.c [M_XENIX]: Miscellaneous minor changes for Xenix. Sun Jun 18 13:07:45 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * GNUmakefile (depend): Split commands into two lines so they won't be so long when variable-expanded. * compatMakefile: Documented MINUS_C_MINUS_O meaning. The line describing it got removed when the USG/wait stuff was documented. Sat Jun 17 22:56:54 1989 Roland McGrath (roland at hobbes.ai.mit.edu) * Version 3.52. Mon Jun 12 17:45:11 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remake.c (check_dep): Drop circular dependencies instead of fataling. (update_file_1 already does this.) * default.c (default_suffix_rules): For .s -> .o, put the -o flag to the assembler before the source file name. Sun Jun 11 12:00:52 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.51. * make.texinfo (Features): Noted 1003.2 requirement of `+' meaning. * file.c (remove_intermediates): If !SIG, write a single "rm" command line, listing all files. * read.c (read_makefile): Don't free the storage for the passed filename, since it might not be malloc'd. When doing an included makefile, free the name's storage. (read_all_makefiles): Use variable_expand to find the value of `MAKEFILES'. Free the storage for the names of -f makefiles. (read_makefile): Allocate storage for the makefile name in the `struct file' in read_makefiles. * make.texinfo (Running: Instead of Execution): Document the effect of + and $(MAKE)/${MAKE}. * make.texinfo (Functions: Foreach Function): Document that if the iteration variable was undefined before the `foreach' call, it will be undefined after the call. * commands.c: Split into commands.c, job.h, and job.c. * rule.c (try_implicit_rule, pattern_search): Moved to new file implicit.c. * rule.c: Split into rule.h, rule.c, and default.c. * default.c (install_default_pattern_rules): Renamed to install_default_implicit_rules. * make.h, main.c (main): Renamed uses. * make.c: Renamed to misc.c. * make.c (main, log_working_directory, decode_switches, decode_env_switches, define_makeflags, die, print_version, print_data_base): Moved to new file main.c. * commands.c (execute_file_commands): Don't collapse backslash-newlines here. When chopping the commands up into lines, don't chop at backslash-newlines. (start_job): Collapse backslash-newlines after printing the line. * commands.c (start_job): Don't collapse backslash-newlines here. (execute_file_commands): Collapse backslash-newlines before chopping the commands up into lines. * commands.c (set_file_variables): Initialize the length counters for $^ and $? to zero! * commands.c (start_job): Use vfork instead of fork. Someone else says the child and parent DO have separate file descriptors. * variable.c: Split internals into variable.c, function expansion into function.c, and variable expansion into expand.c. * function.c (handle_function): New function to check for a function invocation and expand it. * expand.c (variable_expand): Use handle_function. * variable.c (push_new_variable_scope): New function to push a new empty variable set onto the current setlist. (pop_variable_scope): New function to pop the topmost set from the current setlist and free its storage. * function.c (expand_function: `foreach'): Push a new variable scope for the iteration variable and pop the scope when finished. * variable.h: Declare new functions. * variable.c (initialize_variable_output): New function to return a pointer to the beginning of the output buffer. (save_variable_output): New function to save the variable output state. (restore_variable_output): New function to restore it. * expand.c (variable_expand): Use initialize_variable_output. (allocated_variable_expand): Use {save,restore}_variable_output. * variable.c (current_setlist): Renamed to current_variable_set_list and made global. Sat Jun 10 00:11:25 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remake.c (library_file_mtime): Check for libNAME.a in the current directory before doing VPATH search. * variable.c (print_variable_set): Don't write "# Variables", and write fewer blank lines. (print_variable_data_base): Precede the variables with "# Variables". * make.c (main): Print the data base under -p after doing everything else, just before exitting. This way it gets info determined in updating the goal targets. * variable.c (print_variable_data_base): Split into print_variable, which prints one variable, and print_variable_set, which prints a set. Replaced with a call to print_variable_set for the global set. (print_file_variables): New function to print a given file's local variables. * file.c (print_file_data_base): Call print_file_variables to print each file's local variables. * commands.c (set_file_variables): Actually define the values for the $^ and $? variables!!! * make.texinfo (Implicit: Pattern Rules: Automatic): Document new D and F versions of $^ and $?. * commands.c (start_job): In the child fork, use getdtablesize and a loop to close all file descriptors other than 0, 1, and 2. We need to do this since not only the bad stdin pipe, but also some directories, may be open. * commands.c (start_job): Use fork instead of vfork, because a vfork parent and child share file descriptors, and our child needs to diddle with stdin. * variable.c (initialize_file_variables): When created a new variable set, zero out the hash table. * variable.c (target_environment): Don't use variables whose names are not made up of alphanumerics and underscores. * remake.c (update_file_1): Set the `parent' member of each dependency to FILE before updating it. * file.h (struct file): Add `parent' member. * variable.c (initialize_file_variables): Don't take second arg PARENT. Use FILE->parent instead. If FILE->parent->variables is nil, recurse to initialize it. * variable.h: Declare {allocated_}variable_expand_for_file. * variable.c (allocated_variable_expand): Now allocated_variable_expand_for_file, calling variable_expand_for_file, and taking second arg FILE. (allocated_variable_expand): New function, a wrapper around allocated_variable_expand_for_file, passing a nil second arg. Fri Jun 9 12:11:45 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (start_job): On the child side of the fork, always close the bad stdin file descriptor. * commands.c (struct child): New member `environment', to hold the environment for the child. (execute_file_commands): Set the new childs `environment' member to nil before calling start_job. (start_job): Set up CHILD->environment before running the commands if it is nil. * make.c (main): Don't call new_environ. `shell' functions will now be run with the environment make was called with. * commands.c (child_handler): Don't check C->command_ptr before calling start_job since we now have to check C->file->cmds->command_lines and it's easier to let start_job handle all that. * commands.c (struct child): New member `command_line', to hold an index into file->cmds->command_lines. (execute_file_commands): Set the new child's `command_line' to 0 and its `commands' and `commands_ptr' to nil. (start_job): When CHILD->command_ptr runs out, increment CHILD->command_line and run the corresponding line from CHILD->file->cmds->command_lines. Run it even under -t, -q, or -n if the CHILD->file->cmds->lines_recurse element for that line is set. * commands.c (execute_file_commands): Chop CMDS up into lines, setting its `command_lines' and `lines_recurse' members, if it wasn't already chopped. * commands.h (struct commands): New members `command_lines' and `lines_recurse'. The first is an array of chopped-up lines; the second is an array of flags, each nonzero if the corresponding line is recursive. * variable.c (variable_expand_for_file): If FILE is nil, just do a vanilla variable_expand. (expand_function: `shell'): Pass second arg (as nil) to construct_command_argv. * commands.c (construct_command_argv): Use variable_expand_for_file on `$(SHELL)' and `$(IFS)' instead of lookup_variable to check those variables. This handles file-local and recursive values correctly. To support this, take an additional argument FILE. * variable.c (initialize_file_variables): New function to initialize FILE's variable set list from PARENT's setlist. PARENT is the immediate dependent that caused FILE to be remade, or nil if FILE is a goal. (When user-level per-file variables are implemented, PARENT should be passed as nil when defining per-file variables.) * variable.c (variable_expand_for_file): New function to expand a line using the variable set of a given file, and reporting error messages for the file and line number of that file's commands. * variable.h: Don't declare lookup_variable_for_file. * variable.c (lookup_variable_*): Turned back into lookup_variable. It now uses current_setlist. (global_setlist): New static `struct variable_set_list', a setlist containing global_variable_set. (current_setlist): New static `struct variable_set_list *', a pointer to the current variable set list. (define_variable): Define in the current top-level set, not the global set. * commands.c (set_file_variables): New function to set up the automatic variables for a file in its own variable set. (execute_file_commands): Use set_file_variables. * variable.c (new_environ): Replaced with target_environment, taking an argument FILE, and returning an environment for FILE's commands. * variable.c, variable.h: Remove all global special variable pointers. * variable.c (define_variable_for_file): New function like define_variable, but takes additional arg FILE, and defines the variable in the variable set at the top of FILE's chain. (lookup_variable_for_file): New function like lookup_variable, but takes additional arg FILE, and looks the variable up in all of FILE's variable sets. * file.h (struct file): New member `variables', a `struct variable_set_list' containing the list of variable sets used in the expansion of the file's commands. * variable.c (variables): Replaced with static `struct variable_set' global_variable_set. (define_variable): Now define_variable_in_set, taking additional argument SET, the `struct variable_set' to define it in. (define_variable): Use define_variable_in_set with global_variable_set. (lookup_variable): Now lookup_variable_in_set, taking additional argument SET, the `struct variable_set' to look it up in. (lookup_variable): Use lookup_variable_in_set with global_variable_set. (lookup_variable_in_setlist): New function to look up a variable in a `struct variable_set_list' using lookup_variable_in_set. * variable.h (struct variable_set): New structure, containing a hash table and the number of hash buckets. (struct variable_set_list): New structure, containing a link for a linked-list, and a `struct variable_set'. * commands.c (start_job): Under -n, return what the recursive start_job call returns, since it might actually start a child. * make.texinfo (Rules: Wildcards): Document ~ and ~USER expansion. * commands.c (execute_file_commands): If start_job returns failure, but -t is set, set FILE->update_status to success. (start_job): If -t is set, and the commands are not recursive, return failure (is is done for -q). * remake.c (touch_file): New function to touch FILE. (remake_file): Use touch_file. When touching a file, still do execute_file_commands. * remake.c (remake_file): Don't check question_flag (-q), since we can't know here if the commands are recursive. * commands.c (start_job): Don't use the `recursive' member of CHILD->file->cmds. Instead, check for leading +s and $(MAKE) or ${MAKE} in the command line here. * commands.h (struct commands): Remove `recursive' member. * rule.c (install_default_pattern_rules): Remove use of `recursive' member. * read.c (record_files): Don't check commands from $(MAKE) and set their `recursive' member. * commands.c (fatal_error_signal): Treat SIGQUIT like SIGINT, SIGHUP, and SIGTERM, but don't send it to ourselves because it will cause a core dump. Thu Jun 8 20:30:04 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.50. * variable.c (variable_expand): Use allocated_variable_expand instead of expand_argument in a few places. * variable.c (allocated_variable_expand): Do static variable shuffling here instead of using expand_argument. (expand_argument): Use allocated_variable_expand. * variable.c (recursively_expand): New function to recursively expand its argument (a `struct variable'), returning the malloc'd value. (variable_expand): Use recursively_expand. Sun May 28 12:49:27 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (main): Fixed buggy fix in deciding to increase space for command-line variable definitions. (First it never did it, then it always did it; now it does it when necessary.) Sat May 27 14:01:54 1989 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * make.c (main): Fixed bug in deciding to increase space for command-line variable definitions. Fri May 26 15:48:01 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * read.c (multi_glob): Use allocated_expand_variable for checking `HOME' variable for ~ expansion, since this may be called from inside a `wildcard' function expansion. * variable.h: Declare allocated_expand_variable. * variable.c (allocated_expand_variable): New function to do variable expansion in an allocated buffer, rather than the static one. * make.c (main): Don't set glob_tilde (it no longer exists). * variable.c (string_glob): Use multi_glob and parse_file_seq. * read.c (multi_glob): Do ~ expansion here. * glob.c (glob_tilde, glob_filename): Removed ~ expansion. * variable.c (define_variable, lookup_variable): Use a smarter hashing algorithm (the same one used for files and directories). (VARIABLE_BUCKETS): Increased to 523. * file.c (enter_file, lookup_file, rename_file): Use a smarter hashing algorithm, spreading the bits about somewhat. * make.c (log_working_directory): Under `-p', precede the directory message with a `#'. * make.c (print_version): Under `-p', precede each line with a `#'. (print_data_base): Precede the header line with a `#' and include the date and time on it. * vpath.c (print_vpath_data_base): Precede non-directive lines with `#'s. * commands.c (print_commands): Precede the non-command line with a `#'. * rule.c (print_rule_data_base), file.c (print_file_data_base): Precede non-rule lines with `#'s. * dir.c (print_dir_data_base): Precede all lines with `#'s. * variable.c (print_variable_data_base): Changed format so that it can be makefile input. Lines that are not variable definitions are preceded with `#'. Nonrecursive variable definitions are made with all dollar signs doubled to reproduce the initial value. Recursive variable definitions containing newlines are done with `define' directives. Nonrecursive variable definitions containing newlines, and variable names containing :, =, or newlines, will come out garbled. Wed May 24 00:20:04 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.49. Tue May 23 19:18:00 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * variable.c (expand_function: `filter'/`filter-out'): Use find_percent instead of pattern_p. * variable.c (expand_function: `patsubst'): Pass new args (both nil) to patsubst_expand. (variable_expand): For $(var:pat%=rep%) references, pass new args to patsubst_expand so as to avoid find_percent and thus disallow quoting the %s. * read.c (record_files): Pass new args to patsubst_expand. * variable.c (patsubst_expand): Take two new args: PATTERN_PERCENT and REPLACE_PERCENT. Each of these, if non-nil, means that PATTERN (or REPLACE) has already been run through find_percent, and PATTERN_PERCENT (or REPLACE_PERCENT) is the result. * make.h: Declare find_percent instead of pattern_p. * read.c (pattern_p): Changed to find_percent, returning a pointer to the %, or nil if there is none. (record_files): Take another arg, PATTERN_PERCENT, a pointer to the % in PATTERN. (read_makefile): Pass PATTERN_PERCENT to record_files. * make.texinfo (Rules: Static Pattern: Static Usage, Rules: Directory Search: Selective Search, Functions: Text Functions): Documented that `%' can be quoted. * variable.c (expand_function: `filter'/`filter-out'): Use pattern_p to allow quoted %s in patterns. * variable.c (patsubst_expand): Use pattern_p on PATTERN and REPLACE to allow quoted %s. Quoting backslashes are removed from REPLACE even if PATTERN contains no unquoted %. * read.c (pattern_p): Made global. * make.h: Declare pattern_p. * read.c (pattern_p): New function to search for an unquoted % in a string. Backslashes quote %s and backslashes. Quoting backslashes are removed from the string by compacting it into itself. Returns nonzero if an unquoted % was found, zero if not. (record_files): Use pattern_p to check for implicit rules. (read_makefile): Use pattern_p to check for static pattern rules. Also use it to allow quoted %s in `vpath' patterns; warn about `vpath' patterns with no %s. Mon May 22 16:31:52 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * glob.c (glob_filename): Replace a `1' with the `l' that should have been there. This incidentally stops it from dumping core. * glob.c (glob_filename): If the path is just a directory, with no file name pattern, return the directory alone. * glob.c (glob_tilde): New global variable (int), defaults to zero. (glob_filename): If glob_tilde is nonzero, expand ~ or ~USER. * variable.c (string_glob): Keep a static allocated buffer for file names taken from the list, instead of allocating and freeing one every time. Fri May 19 18:06:26 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.c (decode_switches): Get floating numbers from the right string. Sun May 14 13:48:04 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * commands.c (delete_child_targets): When deleting `also_make' files, include the target's name in the message: make: *** [foo] Deleting file `bar' Sat May 13 17:34:26 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (max_load_average, default_load_average): Default to -1. * load.c (wait_to_start_job): Return if max_load_average is < 0.0, not equal. Fri May 12 16:08:05 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * variable.c (variable_buffer_output): Don't try to do pointer arithmetic between objects not in the same array. Wed May 10 15:55:29 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * rule.c [M_XENIX] (default_suffix_rules, default_variables): Minor changes to allow for strange compiler syntax. * rule.c (default_variables): Don't include "> $@" in $(PREPROCESS.S), since it's already in the .S.s rule. * file.c (enter_file): Make a new double-colon file the `prev' member of the bottom `prev' file (the one whose `prev' is nil). * read.c (do_define): Append newlines after copying the lines into the value buffer, so we end up with a trailing newline. * make.c (print_version): If the global variable `remote_description' is not nil or "", append "-%s" (its value) to the version number. * remote-*.c: Define remote_description appropriately. Sun May 7 15:15:53 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (error_status): Converted to new function child_error, taking new arguments TARGET_NAME and IGNORED, and writing an error message: "*** [target] Error 1" (or signal #, etc.), appending " (ignored)" if IGNORED is nonzero. (child_handler): Use child_error instead of error_status. * compatMakefile (all): Don't depend on `doc'. * compatMakefile (clean): Don't remove make-info*. (realclean): New rule, depends on `clean', removes tags, TAGS, and all Info and TeX files. Thu May 4 17:00:46 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * variable.c (print_variable_data_base), file.c (print_file_data_base), rule.c (print_rule_data_base), Use floating-point for averages and percentages. * make.c (print_data_base): Print messages before and after the data base information. * commands.c (print_commands): Changed output format to separate lines in commands and prefix them with tabs. * dir.c (print_dir_data_base): Changed output format slightly. * vpath.c (struct vpath, construct_vpath_list, selective_vpath_search): Remove the `exists' member and its uses. * vpath.c (print_vpath_data_base): New function to print all selective and general VPATH search paths (for -p). * make.c (print_data_base): Call print_vpath_data_base. * file.c (print_file_data_base): Changed format to look more like a makefile rule. Now reports all information in the `struct file'. * rule.c (print_rule_data_base): Changed format of display from: %: (terminal) depends on: RCS/%,v to: %: RCS/%,v is terminal. references nonexistent subdirectory. Also include number and percent that refer to nonexistent subdirectories. Thu Apr 27 15:45:40 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.c (main): Figure out the level of recursion before writing the `Entering directory' message. * variable.c (define_automatic_variables): Don't figure out the level of recursion from `MAKELEVEL'. It's now done in main. * Version 3.48. Wed Apr 26 16:39:17 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (child_handler): Set `update_status' to zero when there are no more commands. * make.c (log_working_directory): If MAKELEVEL > 0, indicate the recurson in the message (make[1]: ...). * commands.c (child_handler): Change status to `cs_finished' when commands fail. * commands.c (start_job): Return 0 (success) if there were no more commands for the child. (child_handler): Change the status to `cs_finished' when start_job fails to start the commands. * make.c (main): Don't handle SIGEMT if it's not defined. Do handle SIGDANGER if it is defined. * commands.c (child_handler): Reorganized inner loop so that it doesn't try to inspect the child before finding it. Tue Apr 25 16:28:24 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.c (end_of_token): Fixed bug wherein backslashes caused immediate return. * Version 3.47. * make.texinfo (Implicit: Pattern Rules: Automatic): Document setting of `$*' for explicit rules. Add note clarifying that automatic variables, though referred to in the documentation as `$<', etc. are no different than `$(<)', etc. Fri Apr 21 18:00:12 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * file.c (enter_file): Don't strip leading `./'s. * read.c (parse_file_seq): Strip leading `./'s. Thu Apr 13 17:26:41 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.texinfo (Commands: Parallel, Running: Options): Document that -l with no argument removes a previous load limit. * make.c (struct command_switch): New member `default_value'. (default_job_slots): Default value (of 1) for -j. (default_load_average): Default value (of 0, unlimited) for -l. (command_switches): Use default values for -j and -l. Also, -l without an arg now means no load limit. (define_makeflags): Don't write positive_int or floating options whose values are their defaults. * make.c (main): Under -w, write a `Leaving directory' message before re-execing. Tue Apr 11 16:46:29 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.46. * Makefile: Provide an easy place for system-specific definitions (-DUSG, etc.) and extra object files (for whatever). * make.texinfo: Miscellaneous fixes from RMS. Mon Apr 10 19:31:34 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * rule.c (pattern_search): Put rules with `subdir' flags set in TRYRULES, since these might be valid with VPATHs. In the TRYRULES loop, don't do lookup_file or file_exists_p calls for dependencies of rules with `subdir' flags set, but still do vpath_search calls and intermediate-file searches. Thu Apr 6 16:33:00 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.texinfo (Implicit: Pattern Rules: Automatic): Document the new definition of $* for explicit rules. * commands.c (execute_file_commands): If FILE->stem is nil, figure out if FILE->name ends in a suffix in the .SUFFIXES list; if so, store the name sans suffix in FILE->stem (and $*). Wed Apr 5 15:24:48 1989 Roland McGrath (mcgrath at helen.Berkeley.EDU) * file.c (remove_intermediates): Don't use `file_exists_p' to check for the existence of intermediate files, because the hashed directories will probably be out of date. * commands.c (child_handler): Free the good stdin before running the next command line. * commands.c [USG] (init_siglist): Don't case SIGEMT if it's not defined. Do case SIGDANGER (for IBM RT) if it is defined. * commands.c: Changed `SYS_WAIT' to `HAVE_SYS_WAIT'. (child_handler): Use `wait3' if HAVE_SYS_WAIT is #defined. * file.c (enter_file): If any `./'s are stripped off, allocate a new copy of the shortened name. * rule.c (pattern_search): Allocate the right length strings for `also_make' members. Sat Apr 1 13:28:38 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.45. * GNUmakefile: Make a separate tarfile of the DVI and info files. * make.c (define_makeflags): If a switch that takes an argument has its default value, put the switch in MAKEFLAGS with no arguments. * make.c (command_switches): Pass `-l' in MAKEFLAGS. Wed Mar 29 17:50:05 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * GNUmakefile: Don't include the DVI and info files in the dist. * commands.c (child_handler): Don't call check_changed_{directories,vpaths}. * make.h: Don't declare check_changed_{directories,vpaths}. * vpath.c (check_changed_vpaths): Removed this function. * dir.c (struct directory): Remove `modtime' member. (find_directory): Don't set `modtime' member. (check_changed_directories): Removed this function. * remake.c (update_file_1): Set FILE->command_state to cs_finished if it didn't need to be remade. * remake.c (update_file): Only write the "up to date" message if the target went from `not_started' state to `finished' state without incrementing the count of files remade. * commands.c [USG] (init_siglist): If both SIGCHLD and SIGCLD are defined, don't put them both in the `switch'. Tue Mar 28 15:37:02 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * file.c (rename_file): Change FILE's name!!! * rule.c (create_pattern_rule): Set the `terminal' member of the new rule after calling new_pattern_rule, which zeros it. * rule.c (default_variables): Use $(C++) in $(COMPILE.cc)! Sun Mar 26 15:52:30 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Makefile: Added a `clean' target. Fri Mar 24 15:08:46 1989 Roland McGrath (mcgrath at helen.Berkeley.EDU) * Version 3.44. * file.c (rename_file): If a `struct file' for the renamed-to name exists, and it is a target or has deps or commands, barf. If not just remove the old one for put in the new one. * remake.c (update_file_1, check_dep): Changed it back so that equal modtimes to NOT make dependencies be considered newer. RCS checks out files with equal modtimes as the RCS files, so this screws it. * make.h, glob.c: If __GNUC__ is defined, use __builtin_alloca. * Makefile: Use variables `ALLOCA' and `ALLOCASRC' so systems without a good standard alloca can get it from the Emacs distribution (or somewhere). * dir.c: Don't include , since make.h does. * make.c: Removed debugging version of getwd. Thu Mar 23 16:16:27 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.43. * remake.c (update_file_1): If a dependency loop is found, don't fatal. Emit an error message and remove the dependency. * remake.c (library_file_mtime): Fixed to use the right names. (update_file_1, check_dep): Consider a dependency "newer" than its dependent if they have the same modification time. Wed Mar 22 19:31:35 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * file.c (remove_intermediates): Don't try to remove nonexistent files. Mon Mar 20 10:21:22 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.42. * rule.c (default_variables): Set F77 to $(FC) and F77FLAGS to $(FFLAGS) so explicit rules expecting these (which are in System V) will work. However, there is no way to make setting these affect the implicit rules, unless we trash FC and FFLAGS (which BSD uses). [USG]: Set GET to `get' rather than `/usr/sccs/get'. Sun Mar 19 20:00:27 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * vpath.c (construct_vpath_list): Don't replace VPATH[ELEM] with dir_name (V), because the latter may get freed. Sat Mar 18 15:01:39 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.41. * make.texinfo: Cleaned-up edition 0.1 Beta from RMS and Bob Chassell. * file.c (rename_file): If a file with the new name already existed, use the same storage space, after freeing the old file's name, deps, and `also_make' member, preserving the link in the chain. Also write an error message telling the user to report the incident; I don't think this should be able to happen, but I'm not sure. * file.c (rename_file): Don't add the hash values of the old and new names together! Reset HASHVAL before computing the second value. * dir.c (check_changed_directories): Zero the new file hash table after allocating it. * dir.c (dir_file_exists_p): If FILENAME is "", return 1 if the directory exists. * vpath.c (check_changed_vpaths): New function to run through the search paths of all VPATHs, making the `exists' members correspond to reality. * commands.c (child_handler): Call check_changed_vpaths. * make.h: Declare check_changed_vpaths. * vpath.c (struct vpath): New element `exists', an array of char flags; exists[N] is nonzero if searchpath[N] exists. (construct_vpath_list): Set the `exists' member. (selective_vpath_search): Don't search directories whose `exists' elements are zero. * read.c (read_makefile): Set the `dontcare' flag of makefiles from the MAKEFILES variable if they were not mentioned anywhere but in the MAKEFILES variable. * read.c (read_makefile): Don't write an error message if fopen fails for a makefile from the MAKEFILES variable. * dir.c (struct directory): Add `modtime' member to record the modification time of the directory when it was opened. (check_changed_directories): New function to check all known directories; if their modtimes have changed since they were opened, their file tables are cleared and they are reset to be read in. * commands.c (child_handler): Call check_changed_directories before returning. make.h: Declare check_changed_directories. Tue Mar 14 20:07:13 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.40. * make.c (print_version): Made the copyright say 1988, 1989. * read.c (read_all_makefiles): Don't set *MAKEFILES to the name of the end of the read_makefiles chain, since the latter may be from an included makefile. (Why did I do this before?) * make.c (main): Set argv[0] to "" if it was nil. Don't put the command-line variable definitions into argv[0], only into the MAKE variable! Sun Mar 5 20:44:08 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * ar.c (ar_member_date, ar_touch): Remove the trailing ) from the member name. Fri Mar 3 18:15:15 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (construct_command_argv): Initialize NEW_ARGV to 0. At `slow' label, if NEW_ARGV is not 0, free it; then allocate 4 strings. Tue Feb 28 14:29:39 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.39. * COPYING, make.texinfo: New GNU General Public License, version 1. * *.c, *.h, Makefile: New copyright notices for the new GNU General Public License, version 1. * commands.c [USG]: Define WRETCODE correctly (again). * variable.c (expand_function: `shell'): Don't capture the standard error output of the shell command. * ar.c (ar_touch, ar_member_date): Allocate MEMNAME with the right length. * load.c [not UMAX] (load_average): Don't clobber the first nlist member when trying to set the second! Thu Feb 23 13:13:53 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * commands.c (child_handler): Really ignore errors under -i and for - lines, don't just print a different message. * make.c (decode_switches): Fixed handling of arguments (or lack thereof) to switches. Wed Feb 22 16:25:39 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * commands.c (construct_command_argv): Don't clobber LINE when checking the IFS variable. Sun Feb 19 11:17:07 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * load.c [UMAX, not NO_LDAV] (load_average): Return 0.0 rather than randomness when calls fail. * Version 3.38. * commands.c (fatal_error_signal): If handling a user kill signal (TERM, INT, HUP), wait for the children without printing the "Waiting for children" message, since they will die quickly. * Version 3.37. * remote-stub.c (remote_status): Take another arg, BLOCK. If this is nonzero block waiting for remote children. If not, return 0 if we would have to block. * commands.c (child_handler) [not USG]: If called as a signal handler, use wait3 and don't block. [USG]: If called as a signal handler, return after handling one child. Sat Feb 18 13:37:04 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * file.c (snap_deps): Process all double-colon entries of each file, not just the first one. * Version 3.36. * remote-stub.c: remote.c renamed. remote.c: Just include remote-stub.c * commands.c (child_handler): If we were called as a signal handler, return after handling one child. * commands.c [not USG]: Include and define `sigmask' if doesn't. (block_children, unblock_children): Use sigmask rather than bitshifting explicitly (and incorrectly). * remote.c (remote_kill): New function to send a signal to a remote child. * commands.c (fatal_error_signal): If we get a SIGTERM, send one to each living child. If we get a SIGTERM, SIGINT, or SIGHUP, delete all pending targets before waiting for children. (struct child): Add new member `deleted'. (start_job): Initialize `deleted' member to 0. (delete_child_targets): New function to delete a given child's targets, unless the `deleted' flag in the `struct child' says they have already been deleted. Sets this flag before returning. Thu Feb 16 18:32:07 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c [USG]: Define `WRETCODE' correctly (X & 0xff00). Tue Feb 14 16:05:00 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (construct_command_argv): Don't make the 0th element of the argument list be "sh" when executing /bin/sh, because start_job uses the 0th element as the program name. Sun Feb 12 17:42:05 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.35. * read.c (readline): Put a null in the beginning of the buffer before starting the reading loop. * read.c (read_makefile): Made main reading loop while !feof (infile), and removed EOF check after calling readline. Sun Feb 5 19:52:38 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * remote.c (block_remote_children, unblock_remote_children): New (stub) functions to block and restore asynchronous notification of remote child death. * commands.c (block_children): Call block_remote_children. (unblock_children): Call unblock_remote_children. (child_handler): If called as a signal handler, block remote children on entry and unblock them before returning. * commands.c (child_handler): For unknown children, if they are remote, give their remote ID; if local, give their PID and make's. * commands.c (execute_file_command): Don't put a new child in the chain unless start_job succeeds. Block children before calling start_job, and unblock them after putting the child in the chain and incrementing `job_slots_used' (if start_job succeeded). * commands.c (block_children, unblock_children): Make these globally visible (not `static'). commands.h: Declare block_children and unblock_children. * variable.c (expand_function: `shell'): Use `shell_function_completed'. Block children before forking and unblock after `shell_function_pid' is set properly and `shell_functon_completed' is reset to 0. * commands.c (child_handler): When the child of the `shell' function completes, set `shell_function_completed' to 1 if it actually ran, or -1 if it didn't (due to fork or exec failure). * commands.c (block_children, unblock_children): New functions to block and unblock the child termination signal. (wait_for_children): Use block_children and unblock_children. (execute_file_commands): Block children around the critical section wherein a new child is put on the chain. * make.c (main): Change the environment to contain the correct MAKELEVEL before re-execing. Sat Feb 4 18:28:48 1989 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.34. Fri Feb 3 16:36:49 1989 Roland McGrath (mcgrath at helen.Berkeley.EDU) * rule.c (default_variables): Fixed $(LINK.c). Wed Feb 1 18:05:07 1989 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Version 3.33. * version.c: Removed copyright notice, since this is a one-line file. * commands.c (error_status): Made it return BUF, rather than running off the end (this apparently worked on Sun 3s for some reason). * ar.c, commands.c, dep.h, load.c, make.c, make.h, read.c, remake.c, rule.c, variable.c, Makefile: Changed copyrght notices to cover 1989. Mon Jan 30 15:51:28 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.32. Fri Jan 27 20:09:24 1989 Roland McGrath (mcgrath at tully.Berkeley.EDU) * remake.c (remake_file): Don't touch phony targets. * rule.c (convert_to_pattern): Fixed an incorrect length passed to savestring. * variable.c (expand_function: `shell'): Close the read side of the pipe on the parent side of the fork. * commands.c (start_job): On the child of the fork, close the BAD_STDIN fd if we're not using it. * read.c (record_files): A file beginning with a dot can be a default target if it also contains a slash (as in `../foo'). * commands.c (wait_for_children): For BSD, block SIGCHLD rather than ignoring it to avoid a race condition when child_handler is returning. * commands.c (child_handler): Do blocking waits. (error_status): Return a string describing exit status. (Split out of child_handler). * read.c (multi_glob): Change VECTOR to VEC for Alliant. Thu Jan 5 00:06:51 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.31. * make.texinfo (Features): Noted $(foo:PAT=SUB) from SunOS 4.0. * make.texinfo (Options/Recursion): -d and -p go in the environment. * load.c: Include "commands.h". Wed Jan 4 17:49:25 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * make.c (switches): -d and -p can come from the environment and are put into it. * read.c (record_files): Fixed the checking for duplicate deps so it doesn't clobber the first one. * make.texinfo: Documented default implicit rule changes. * rule.c: Revamped default suffix rules. They now use Sun's style of using variables `COMPILE.c', `LINK.c', etc. for each suffix, and use `TARGET_ARCH' and `TARGET_MACH' variable where appropriate. Also support Modula-2 compilation (suffixes .sym, .def, and .mod). Ratfor Yacc support is gone, since nobody has yacc -r. All EFL support is gone, since nobody uses EFL. * ar.c, arscan.c: Don't assume `long int' and `int' are the same. * commands.c [USG]: Fixed wait status bit encoding. [USG and not USGr3] (dup2): Define this for SysVr2. * make.h, dep.h, make.c [iAPX286]: Make allowances for this brain-damaged compiler. * make.texinfo (Variables: Flavors): Fixed a typo. Tue Jan 3 18:09:31 1989 Roland McGrath (mcgrath at homer.Berkeley.EDU) * ar.c (ar_member_date, ar_touch): Truncate member names to 15 chars. * Version 3.30. * commands.c [SYS_WAIT]: If this is defined, use BSD and wait3 even if USG. * read.c (record_files): Defining .DEFAULT with no deps or commands clears its commands. * rule.c (default_suffixes): Added `.sh'. (default_suffix_rules): Added single-suffix .sh rule, copies source to target and makes target executable. make.texinfo (Catalogue of Rules): Documented .sh rule and its use in conjunction with SCCS. * rule.c (set_default_suffixes): Define variable `SUFFIXES' to the default list ("" under -r). make.texinfo (Suffix Rules): Document `SUFFIXES' variable. * rule.c (default_variables), make.texinfo (Implicit Variables): Variable AR defaults to `ar', ARFLAGS to `rv', and RM to `rm -f'. * rule.c (install_default_pattern_rules): Default variables are made recursive. (default_variables): Added "CPP", defined to "$(CC) -E". (default_suffixes): Added `.S', before `.s'. (default_suffix_rules): New rule for .S to .s, runs CPP. All rules that use CPP now include "$(CPPFLAGS)". make.texinfo (Catalogue of Implicit Rules, Implicit Variables): Documented above changes. * commands.c [USG] (sys_siglist): Don't define. [USG] (init_siglist): New function to initialize sys_siglist. * make.texinfo (Variables: Reference): Documented `$(foo:PAT=SUB)' references. * variable.c (variable_expand): A reference `$(foo:PAT=SUB)' is equivalent to `$(patsubst PAT,SUB,$(foo))'. * variable.c (variable_expand): Free the storage for the expansion of a recursive variable when it is nod longer needed. * variable.c (variable_expand): When checking for `$($(foo))', use lindex so as not to search for the second `$' outside the parens. * make.c (struct stringlist, main, decode_switches): Changed `index' member to `idx'. Sat Dec 24 16:02:32 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (wait_for_children [USG]): Handle SIGCLD with SIG_DFL, rather than SIG_IGN. Ignoring SIGCLD reportedly makes wait return -1. * arscan.c [USGr3]: Define PORTAR to 1 (as with sun386). (ar_scan [USGr3]): Remove trailing slashes from member names. Thu Dec 22 17:54:05 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * make.texinfo (Makefiles: Overriding Makefiles): New node documenting use of .DEFAULT to have one makefile defer unmakeable targets to another. * make.texinfo (Implicit: Using Implicit, Implicit: Last Resort): Mention empty commands and xref node `Empty Commands'. Wed Dec 21 20:12:40 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.29. * make.c (struct command_switch, command_switches, et al): New member `noarg_value', if not nil, ptr to value to use if no arg is given to a switch that would otherwise require one. The -j option can now be given w/o an arg, to mean infinite jobs. * commands.c: If job_slots is zero, infinite jobs. * read.c (read_all_makefiles, read_makefile): Make makefiles precious. * make.c (decode_switches): For a positive_int or floating option, if we moved to the next argument word, but found no argument for the option, move back to the correct word. * make.c (decode_switches): If we got any unknown options, die after processing all arguments. * GNUmakefile: Moved `include depend' to the end, so the default goal will be set before then. * load.c (wait_to_start_job [Unix, UMAX]): Merged into one version under #ifdef LDAV_BASED. Only loop while we have jobs running. Sleep for increasing amounts (increase one second per iteration) before checking the load average (after the first check). Get the load average from function load_average. (wait_to_start_job [not LDAV_BASED]): Always return. (load_average [UMAX]): Fetch load average for Encore UMAX. (load_average [not NO_LDAV]): Fetch load average from /dev/kmem. [not NO_LDAV]: Define LDAV_BASED. Tue Dec 20 18:54:50 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.28. * commands.c (wait_for_children): Take second arg, ERROR. If nonzero, and there are children, print a message on stderr. (execute_file_commands, fatal_error_signal): Pass second arg. * make.c (die), remake.c (update_goal_chain), variable.c (expand_function: `shell'): Ditto. Sat Dec 17 01:05:38 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * commands.c (start_job): Call wait_to_start_job before forking. * load.c (load_average): Converted to wait_to_start_job. * remote.c: New file for remote execution functions. (start_remote_job_p): Return nonzero if the next job should be run remotely. (start_remote_job): Start a remote job and return an ID for it. (remote_status): Get status of dead remote children. Fri Dec 16 16:51:07 1988 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * commands.c (start_job): If start_remote_job_p () returns nonzero, call start_remote_job to start the job rather than fork and exec. (child_handler): * commands.c (execute_file_commands): Moved load average checking to start_job. * commands.c (child_handler: USG): Record the pid wait returns. * load.c (UMAX): Added some #include's needed for UMAX. * read.c (multi_glob), variable.c (string_glob): Ignore a (char **) -1 return from glob_filename. * variable.c (variable_expand): Make sure we don't increment past the end of the string we were passed. * variable.c (variable_expand): Terminate the expansion. * file.c (rename_file): If there is already a file under the new name, set its contents equal to FILE's (ick). * variable.c (define_automatic_variables): Pass all the args to define_variable when defining MAKELEVEL! * commands.c (execute_file_commands): If max_load_average > 0, and we have children running, don't start up another child until the load average goes below max_load_average. * make.c: New variable `max_load_average'. (struct command_switch, decode_switches, decode_env_switches): Handle floating-point (double) args. (command_switches): Added `-l' switch to set `max_load_average'. * load.c (load_average): New file and function to return a double that is the current load average (1.00 scale). * GNUmakefile, oldMakefile: Pass flags in $(LOAD_AVG) for load.c. Thu Dec 15 15:22:08 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Makefile: Renamed to oldMakefile. * GNUmakefile: Make Makefile from oldMakefile and depend. * read.c (read_all_makefiles): When putting the default makefiles in the read_makefiles chain so they will be remade, put them in the right order. * remake.c (update_goal_chain): If MAKEFILES is nonzero, always make in serial, and return as soon as one goal whose `changed' member is nonzero is successfully remade. * commands.c: Don't include . * commands.c (construct_command_argv): Added ` to sh_chars. * make.h: Don't declare construct_makeflags. * make.c (main): Set up MAKEFLAGS and MFLAGS and make an environment both before and after reading the makefiles, so the makefiles can use them and possible change them, and later children will get the right information. (construct_makeflags): Replaced with define_makeflags (static void), which defines the two variables. * variable.c (define_automatic_variables): Don't define MAKEFLAGS and MFLAGS. Mon Dec 12 14:40:31 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * Version 3.27. * commands.c (child_handler): Reset the handler to ourselves when called for USG, since it has no safe signals. * commands.c: For USG, use an int rather than a `union wait' for wait calls, and dissect it with bitmasks. (child_handler): No wait3 system call in USG. Since we can't protect from hanging, always return immediately if we have no children we know about and we're not running a `shell' function. (There is still the danger of hanging waiting for a child that died without our being notified.) * remake.c: Include instead of . What we need is really in , and while BSD includes , USG doesn't. * make.c (main): Figure out the program name before doing anything which might need it (in a call to error or fatal). * dir.c, glob.c: Use `struct dirent' and for USGr3. * arscan.c (ar_scan): Added missing & before buf (which is an int) if SARMAG is not defined (SysV). Fri Dec 9 18:44:13 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Version 3.26. * dir.c (find_directory, dir_file_exists_p): Keep track of how many directories we have open and don't let it be more than MAX_OPEN_DIRECTORIES (currently 10). * variable.c (expand_function: `foreach'): Use expand_argument rather than variable_expand so each repetition doesn't clobber the last!!! Mon Dec 5 15:58:46 1988 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * Version 3.25. * Makefile: Define `install' target. * GNUmakefile: Don't include GNUmakefile or depend in the distribution file. Wed Nov 30 15:53:42 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * commands.c (execute_file_commands): Don't clobber a null into random storage if there were no $^ and/or $? words. * remake.c (check_dep): Set *MUST_MAKE_PTR nonzero if a dependency doesn't exist. * ar.c (ar_member_date, ar_touch): Make sure the modtime of the archive file itself is known before we fetch or change the modtime of one of its members. * read.c (read_makefile): Expand variable and function references before parsing rules so variable can contain special characters (colons and semicolons). Sat Nov 26 11:36:31 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * variable.c (expand_function: `filter', `filter-out'): Fixed so that filter-out works right. * variable.c (expand_function: `filter', `filter-out'): Made these functions use each word of their first argument as a pattern. Fri Nov 25 10:51:47 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.24. * read.c (record_files): If a target is listed more than once in a single rule (that defines commands), give a warning message rather than the counter-intuitive message saying commands were already defined (in the same place). * make.c (fatal, error): Made them both take 6 args since there is at least one error message that need that many. Too bad vfprintf is not universal! * Version 3.23. * read.c (read_makefile): Moved the construction of the `struct commands' into record_files. Call record_files before recursing for an included makefile so the higher-up will determine the default goal. (record_files): Take arguments COMMANDS, COMMANDS_IDX and COMMANDS_STARTED and construct a `struct commands. Thu Nov 24 14:36:33 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.22. * make.c (main): Made it a fatal error if we can't move back to the directory we started in before re-execing. * make.c (main): Get the current directory before doing anything else, so we know it even if we don't need it for the value of `MAKE', since we might want it when re-execing. Wed Nov 23 13:34:44 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.21. * read.c (record_files): Eliminate duplicate deps in a chain. * variable.c (expand_function: `sort'): Pass the right number to qsort, not one less. * remake.c (remake_file): Always call notice_finished_file if FILE->command_state == cs_finished. * commands.c (execute_file_commands): Call notice_finished_file to set FILE's status correctly when start_job fails (because it's out of commands or running under -n). Fri Nov 18 15:31:12 1988 Roland McGrath (mcgrath at saffron.Berkeley.EDU) * Version 3.20. * remake.c (update_file_1): Set the `update_status' of FILE to nonzero and set FILE's `updated' bit if we have decided to give up on remaking FILE because of errors in the dependencies. * rule.c (pattern_search): Debugging messages use `dependency' (vs. `dependent') properly. * make.texinfo (Conditionals: Conditional Syntax): Function index entries for `ifndef' and `ifneq'. * variable.c (define_automatic_variables): Define `MAKELEVEL' to the decimal number of the makelevel, since it may be malformed or blank. * remake.c (remake_file): Call notice_finished_file after touching. Sat Nov 12 19:29:34 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.19. * GNUmakefile (dist): Pass the `-f' flag to compress. * vpath.c (build_vpath_lists): Check for VPATHS being nil after constructing the general VPATH list from the `VPATH' variable. Fri Nov 11 08:02:26 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (fatal, error): Made error messages for recursive runs be shorter. Thu Nov 10 16:51:36 1988 Roland McGrath (mcgrath at basil.Berkeley.EDU) * Version 3.18. * read.c (read_makefile): Made it eat leading spaces and formfeeds (but not tabs), like it's documented to. * read.c (read_makefile): Let included makefiles determine the default goal, as is done by System V Make. Tue Nov 1 19:03:08 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * variable.c (new_environ): Don't increment VCNT when a variable is rejected. Fri Oct 28 16:54:15 1988 Roland McGrath (mcgrath at basil.Berkeley.EDU) * Version 3.17. * rule.c (convert_to_pattern): Don't use the same storage for a name in two rules since new_pattern_rule may free this storage when a rule is discarded. * rule.c (new_pattern_rule): Undid useless change I made Oct 25. Thu Oct 27 19:17:53 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.16. * GNUmakefile, Makefile: Fixed a typo in a comment. * Makefile: Removed malloc.o from object file list. * variable.c: Removed old debugging #define's for xmalloc and xrealloc so non-ANSI cpp's won't barf. * make.c (main): Made local array for temp file name static so compilers that don't do auto aggregate initialization won't barf. * read.c: Removed static declaration of copy_dep_chain since it is no longer static. Tue Oct 25 16:59:30 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * rule.c (new_pattern_rule): If we threw out the new rule because it matched an old one and OVERRIDE was zero, don't put the freed pointer in the chain! Wed Oct 19 15:07:43 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Version 3.15. * variable.c (expand_function: `sort'): Don't do the sorting and writing out if there were no words in the first place. * remake.c (remake_file): Only fail with a "no way to make" message for a dependency (non-target) file. If we don't know how to remake a target file, pretend it was successfully remade and is very new. * remake.c (remake_file): Don't increment `files_remade' for a non-target file we don't know how to remake. * read.c (record_files): Don't die with "both : and :: entries" for a file whose `is_target' flag is not set. Tue Oct 18 17:24:11 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * variable.c (expand_function: `patsubst', `subst'): Free the right things! * variable.c (expand_function: `subst'): Don't clobber the pointer to the end of the second arg and then try to use it!!! Mon Oct 17 16:44:45 1988 Roland McGrath (mcgrath at catnip.Berkeley.EDU) * variable.c (expand_function: `patsubst'): Don't clobber the pointer to the end of the second arg and then try to use it!!! * variable.c (expand_function: `word' function): Made it parse its second argument correctly. * ar.c (ar_touch): Return 1 rather than -1 for on errors. Sat Oct 15 15:12:16 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.14. * GNUmakefile: Removed explicit rule for make.dvi since the built-in implicit rule now works. * rule.c (default_suffix_rules): Fixed .texinfo.dvi rule yet again so that it really works, now that parens are counted. * remake.c (update_file_1): Set FILE's `updated' flag after calling remake_file if it failed or finished immediately. * remake.c (update_file): Use the `updated' flag rather than the command state to decide if a file was fully considered, and therefore might give an "up to date" message. * variable.c (expand_function): Made all functions that take more than one argument count parens of the appropriate flavor in their args and ignore commands nested in parens. Fri Oct 14 18:35:00 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * read.c (read_all_makefiles): Pass second arg to read_makefile for default makefiles. Thu Oct 13 16:40:08 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.13. * GNUmakefile: Added an explicit rule for make.dvi since the built-in .texinfo.dvi implicit rule is screwed up. * rule.c (default_suffix_rules): Added a comment that the .texinfo.dvi rule does not work because of an ahem, feature of Make that at some point will be fixed--er, enhanced to alleviate this difficulty. * rule.c (default_suffix_rules): Fixed Texinfo -> DVI rule (again). * make.texinfo (Commands: Execution): Documented new competing for standard input among children. * commands.c (struct child): Added `good_stdin' flag to tell if this child has the stdin that doesn't point into nirvana. (good_stdin_used): New variable to tell if any child has the good standard input. (child_handler): Reset `good_stdin_used' if a dead child's `good_stdin' flag is set. (start_job): Give the new child the good standard input if `good_stdin_used' is no set, and set the child's `good_stdin' flag appropriately. * rule.c (default_suffix_rules): Changed Texinfo -> DVI rule to work better (I hope). * read.c (read_all_makefiles): Stop reading default makefiles after one is found. * read.c (read_makefile): Reset `reading_filename' and `reading_lineno_ptr' after recursing for an included makefile. * GNUmakefile: New GNU Make-specific makefile that does everything Makefile does plus distribution stuff, and doesn't contain any hacks to try to work with Unix make. * Makefile: Removed distribution stuff. * make.c (main): Use mktemp to construct the names of temporary files used for standard input makefiles. * make.c (main): Don't turn standard input into a broken pipe. * commands.c (start_job): Keep two extra file descriptors around: a good standard input, and a bad one that reads from a broken pipe. On the child side of the fork, if there are other children, give this one the broken pipe so they won't compete; if this is the only one, give it the good standard input. * make.h: Declare notice_finished_file. * commands.c (execute_file_commands): Use noticed_finished_file after waiting for the child when there is only one job slot. * remake.c (notice_finished_file): New function to re-check mtime's and such things to be done when commands finish. (update_file_1): Use notice_finished_file. * commands.c (child_handler, execute_file_commands): Use new variable `job_slots_used' to record the number of jobs currently running, rather than diddling with `job_slots'. (execute_file_commands): Increment `job_slots_used' before calling start_job and decrement it on failure to avoid race condition. If there is only one job slot, wait for the child to finish and return its status so commands are run in linear order, as if there were no parallelism. Wed Oct 12 15:59:03 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * remake.c (remake_file): Don't print a "No way to make" message for targets whose `dontcare' flags are set. * read.c (read_all_makefiles): Set the `dontcare' flag of the `struct file' each default makefile added to the chain. * file.h (struct file): Add `dontcare' member. * read.c (read_all_makefiles): When no default makefiles are found, put the names of all those tried in the `read_makefiles' chain so they will be updated if possible, giving their `struct dep's' `changed' members the value of 0 so we won't care if they cannot be found or remade. * make.texinfo (Makefiles: Remaking Makefiles): Documented that default makefiles will be remade if not found. * read.c (read_all_makefiles): If no default makefiles can be found, go through the list of default names, trying to make one, stopping if one is made. * remake.c (remake_file): Set STATUS to 0 after successfully touching. * dir.c (file_impossible, file_impossible_p): Don't clobber FILENAME to "" and then try to to a strcmp on it!!! Mon Oct 10 16:09:18 1988 Roland McGrath (mcgrath at cinnamon.Berkeley.EDU) * make.c (main): Don't do `dir_load (".")'. * rule.c (count_implicit_rule_limits), vpath.c (construct_vpath_list): Test the existence of a given directory by `dir_file_exists_p (DIR, ".")' and assume that if this returns zero, it means the directory really does not exist. * dir.c (struct dirdata): Replaced with `struct directory' for directories, each containing a chain of `struct dirfiles', one for each file (real or impossible). (dir_load): Removed. (find_directory): New function to find the `struct directory' for a named directory and return it (possibly creating a new one). (dir_file_exists_p): Read the directory on the fly if its stream is still valid (and ever was) if the file we're looking for is not already in the hash tables. (file_impossible, file_impossible_p, dir_name, print_dir_data_base): Use the new directory/file scheme. * make.texinfo: Miscellaneous editorial changes and clarifiactions. * commands.c (struct child): Remove `environ' member. (child_handler, start_job, execute_file_commands): Remove use of `environ' member and new_environ. * make.c (main): Call new_environ after reading makefiles. * variable.h: Declare `new_environ' to return void. * variable.c (new_environ): Put the environment in `environ' and return void. Fri Oct 7 15:48:39 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Version 3.12. * Makefile: Don't make the uncompressed tar file. * variable.c (expand_function: `shell' function): Made it not expect read to null-terminate the buffer. * Makefile: Made it use a temporary symlink to . rather than a temporary directory to make the distribution tar file. Thu Oct 6 17:52:35 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.11. * make.texinfo: Fixed a line that got garbaged somehow. Mon Oct 3 16:14:39 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * make.c (main): Try to move back to the directory we started in before re-exec ourself. * remake.c (update_file_1): A double-colon target with no deps always needs to be remade. * remake.c (remake_file): Changed "No way to make" message to say `target' rather than `file'. Sun Oct 2 12:50:47 1988 Roland McGrath (mcgrath at catnip.Berkeley.EDU) * remake.c (update_file_1): Set FILE->update_status to the return value of remake_file. * rule.c (convert_to_pattern): Fixed swapped lengths passed to xmalloc for source/target suffixes. * make.texinfo: Documented that MAKEFLAGS and MFLAGS are read in from makefiles. Updated the `Features' section a bit. * make.c (main): Read switches from MAKEFLAGS and MFLAGS variables after reading in makefiles. * make.c (main): Put a line "/tmp/foo:;" rather than ".PHONY: /tmp/foo" in front of temp files made for stdin makefiles. * remake.c (update_file): Test the state of the right `struct file' for double-colon files. * make.c (main): Put a ".PHONY: /tmp/foo" line in front of temp files made for stdin makefiles so they won't be remade when we re-exec. Kludge-o-matic!! * remake.c (update_goal_chain): Judge files as being finished based on their `updated' flag, not their state. * read.c (read_makefile): Don't check for FILENAME being "-". (read_all_makefiles): Set each element of MAKEFILES to the name put in READ_MAKEFILES by read_makefile, since read_makefile may free the storage for the name it is passed, and someone might want to look at the elements of MAKEFILES again. * make.c (main): For each `-f' flag with arg `-' (standard input), read standard input into a temp file and pass the temp file's name to read_all_makefiles, after making sure it will not be remade. * make.c (construct_makeflags): Always put out `-j1'. Sat Oct 1 00:19:59 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * commands.c (execute_file_commands): If commands are nothing but whitespace, set the state to `cs_finished' before returning 0. * make.c (decode_switches): Allocate space for args in stringlists so they can be freed later. * make.h: Declare `makelevel'. * variable.c (makelevel): Moved to make.c (and made global). * make.c (fatal, error): Print the makelevel if it's > 0. (perror_with_name): Use error rather than calling fprintf directly. (pfatal_with_name): Use fatal rather than fprintf and die. * variable.c (new_environ): Don't put default variables (origin `o_default') into the environment; they just take up space. * read.c (read_makefile): Don't add FILENAME to the chain of read makefiles if it's "-" (standard input). * remake.c (update_goal_chain): Set STATUS correctly when nothing happens (as well as in all other situations). * make.c (construct_makeflags): Put a `-' before each switch and spaces between them. * Version 3.10. * commands.c (wait_for_children): Don't check if `children' is nil. This is the case when waiting for the child of a `shell' function. * dir.c (dir_load): Don't add a hash-table entry for directory DIRNAME and filename "" if DIRNAME doesn't exist. * commands.c (execute_file_commands): Return 0 after start_job returns 1 (failure) under the -n flag. * remake.c (remake_file): Set the state to `cs_finished' when not calling execute_file_commands. * remake.c (update_goal_chain): Second arg is now MAKEFILES, nonzero meaning to disable -t, -q, and -n for each target unless the target was also given on the command-line. * read.c (read_makefile): Enter the `struct file's for the makefiles added to the `read_makefiles' `struct dep' chain. * remake.c (update_goal_chain): Made it not enter the files for the goals in the chain. It will already have been done. * rule.c (convert_to_pattern): Null-terminate the names of targets and deps of the pattern rules properly. Fri Sep 30 18:56:20 1988 Roland McGrath (mcgrath at nutmeg.Berkeley.EDU) * make.c (main): Call install_default_pattern_rules. * make.h: Declare copy_dep_chain. * read.c (copy_dep_chain): Moved to make.c (and made global). * make.c (main): Call update_goal_chain to update goals. Update read makefiles and re-exec self if they change. * remake.c (update_file): Make this function static. (update_goal_chain): New function to update a `struct dep' chain of goals, waiting until they are all finished before returning. * make.h: Don't declare update_file. Declare update_goal_chain. * make.c (main): Call snap_deps, etc. that were in read_all_makefiles. * read.c (find_makefile): Removed this function. (read_all_makefiles): Don't update makefiles, don't diddle with pattern rules, don't call snap_deps, etc. Return a `struct dep' chain of all makefiles read. (read_makefile): Now takes two args: FILENAME and TYPE, which is 0 for a normal makefile, 1 for MAKEFILES variable or 2 for an included makefile. Add a `struct dep' containing the name of the makefile (as it was found in the search path for type 2s), and TYPE in the `changed' member to the global `read_makefiles' chain. * make.h, rule.c (displace_pattern_rules, add_displaced_pattern_rules): Removed these functions. * read.c (read_makefile): Variable-expand the name of an `include'd makefile before calling find_makefile on it. * file.c (snap_deps): If the `struct file' for a `struct dep' already exists, free the `struct dep's `name' member before setting it to nil (since this info is in the `struct file'). * read.c (copy_dep_chain): Made it copy each name rather than leaving multiple `struct dep's with the same pointers. Thu Sep 29 19:08:13 1988 Roland McGrath (mcgrath at catnip.Berkeley.EDU) * make.c (decode_switches): Fixed second decode_env_switches call to use correct length of "MFLAGS" (6, not 5). * read.c (read_makefile): Don't stop reading when readline returns zero lines read. Only stop when the stream reaches EOF. This makes it recognize the last line of a makefile without a newline. * remake.c (remake_file): If we don't know how to make FILE, set its command state to `cs_finished'. * remake.c (update_file): Don't write the "up to date" message if update_file_1 returned a nonzero status. Wed Sep 28 16:30:07 1988 Roland McGrath (mcgrath at catnip.Berkeley.EDU) * commands.c (child_handler): Set the `update_status' member properly for ignored errors. * rule.c (convert_to_pattern): Made it not care about if the target suffix comes before the source suffix in the .SUFFIXES list. * make.texinfo: Misc editorial changes. * commands.c (wait_for_children): Return immediately if `children' is nil (there are no children). Tue Sep 27 15:33:14 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Version 3.09. * commands.c (struct child): New member `command_ptr' to hold the current position in the commands. The `commands' member is never changed. (start_job, child_handler, execute_file_commands): Use new method for `commands' and `command_ptr' members. * make.c (decode_env_switches): Skip past an invalid letter (instead of looping forever). * commands.c (struct child): Add `environ' member to hold the environment for this child. (execute_file_commands): Get a new environment from new_environ and put in the the new `struct child's `environ' member. (child_handler): When freeing a child, free its `commands' member, the elements of its `environ' array and its `environ' member itself. (start_job): Set `environ' to the child's `environ' member before exec'ing the command. * variable.h, variable.c (new_environ): Made it return the new environment, not putting it in `environ'. * remake.c (update_file): Don't give a "is up to date" message unless no files were remade and the state went from `cs_not_started' to `cs_finished', so repeat calls to finish jobs won't get the message. Mon Sep 26 16:26:08 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * Version 3.08. * make.texinfo (Commands: Execution): Documented that children will be waited for rather than killed. * commands.c (fatal_error_signal): Wait for children. (kill_children): Removed this function. * make.c (main, die): Wait for children to die, don't kill them. * variable.c (expand_function): Use wait_for_children. * make.c (main): Use wait_for_children rather than child_handler. * commands.c (wait_for_children): New function to block waiting for children, insuring that child_handler is not called recursively. (execute_file_commands, kill_children): Use wait_for_children. * commands.c (child_handler): Start up additional commands in a sequence after an ignored error. * remake.c (update_file): Don't print "`foo' is up to date" messages when update_file_1 returns while commands are executing. * remake.c (update_file_1): Pass the file name to name_mtime, not the bloody `struct file', dammit!! * commands.c (child_handler): Print out the "*** ..." error message when not under -i. (I somehow forgot this.) * remake.c (update_file_1): Use name_mtime rather than file_mtime to re-get the mtime of a file whose commands have finished. * make.c (command_switches, decode_switches, decode_env_switches): Make all switches that take string args allow them right after the switch letter. * commands.c (child_handler): Check for a child being the `shell' function's command returning and set the global variable for expand_function to check. * variable.c (expand_function): For the `shell' function, instead of waiting for the child shell ourselves, let child_handler do it and loop around waiting for something to happen. * make.c (print_version): Made the copyright year static, not dynamic. * make.h, make.c: Remove construct_argv function. * make.c (main): Say "no goal target" instead of "no target". * make.texinfo (Commands: Parallel): Don't send SIGKILL. * commands.c (kill_children): Don't send SIGKILL to children that aren't killed by the first signal. * make.c (main), commands.c (kill_children): Decide between SIGCHLD and SIGCLD based on whether or not SIGCHLD is defined, not on USG. * Makefile: Link make with $(LOADLIBES). * read.c (construct_include_path): Fixed another bad xrealloc call. * make.c (decode_switches): Fixed an xrealloc call with no first arg. Sat Sep 24 01:16:21 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * Version 3.07. * remake.c (update_file_1): If deps are running, set state to `cs_deps_running' and return 0. If deps are done, run commands. * commands.c (child_handler): Made it delete non-precious targets killed by fatal signals. * make.texinfo: Documented parallelism. Fri Sep 23 16:52:27 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * remake.c (update_file_1): Don't return if FILE's state is `cs_deps_running'. In that case, we need to run through and check the states of all our dependencies. * commands.c (execute_file_commands): Decrement `job_slots' after starting a new job to run file commands. * commands.c (start_job): Made it set the state to `cs_running'. * make.c (main): Fixed usage of `g', `lastgoal', and `goals' in the goal-making loop. * commands.c (child_handler): When commands finish, set the corresponding file's `update_status' and `updated' flags as appropriate, and reset the modtimes of the file and any `also_make' files it has. * remake.c (remake_file): Don't re-set `last_mtime' and set `updated'. * commands.c (fatal_error_signal): Don't swallow all the children with a loop around `wait ((union wait *) 0)'!!! * make.c (struct command_switch): Added `positive_int' type. (switches): Added -j (job_slots). (construct_makeflags, decode_switches, decode_env_switches): Handle`positive_int'-type switches. * glob.c (glob_vector): Rename local variable `vector' to `VeCtOr'. This is said to avoid a conflict with some system's global `vector' variable. * variable.c (expand_function): Made the `shell' function use construct_command_argv and do its own child control and piping. * make.c (main): Turn standard input into a broken pipe after reading in all makefiles (the last time it will be needed). * commands.c (struct child): Remove `pipe_fd' member. We don't use pipes any more. (start_job): Return 0 for success, 1 or failure (rather than void). Don't use pipes. Don't turn the child's stdin into a broken pipe. (child_handler): Print "*** Error" messages when necessary. Die on failed commands when -k was not given. (execute_file_commands): Check the return of start_job and remove the child from the chain and return failure if it is nonzero. * make.c (die): New function to clean up and exit. (fatal, pfatal_with_name): Use die. Thu Sep 22 14:27:11 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * commands.c (struct child): Added `commands', `pipe_fd', and `noerror' members to keep track of info about a command thread. (start_job): New function to start a job and update the argument `struct child' to reflect its status. (execute_file_commands): Merged run_file_commands back in. Made it use new start_job function. * rule.c (freerule): Don't free the `struct commands' of the discarded rule. It may be used in more than one place. * commands.c (execute_command_line): Made it not try to delete the possibly partly-made file. The child_handler function will do this. (fatal_error_signal): Ditto + call kill_children. * make.h: Declare job_slots. * make.c (main): Collect goals in a dep chain and run through this chain waiting for a child, eliminating finished goals, updating all remaining goals, and quitting if they fail and not -k. * commands.c (child_handler): If called with SIG < 0, - SIG is the max number of children to bury. * commands.c (child_handler): If called with SIG as zero, block waiting for running children. (kill_children): Call child_handler with zero rather than SIGCHLD. * remake.c (update_file_1): Use the `command_state' member of FILE and its dependencies to determine what commands are running, what to do, etc. If commands or dep commands are running when we are called, return success (0). If commands finished since the last time we were called, return their status. * commands.h: Declare kill_children. * commands.c: Define `struct child' to keep track of child processes, with the chain in `children'. (child_handler): New function to catch child-termination signals (SIGCHLD, or SIGCLD for USG), store the returned status in the appropriate structure, take the now-obsolete `struct child' out of the chain, and free its storage. (execute_file_commands): Put all of the stuff invloving running the commands into new function run_file_commands. Execute_file_commands now does process management for the commands, while run_file_commands (which is run in a subprocess) runs the commands. (kill_children): New function to kill all running children by sending them signal SIG. If there are any children still living after they are all sent SIG, they are all sent SIGKILL. * make.c (main): Catch SIGCHLD (SIGCLD for USG) with child_handler. * commands.h: Declare child_handler function. * commands.c (execute_file_commands): Check the `command_state' member of FILE and return 0 if it is `cs_running' or `cs_deps_running' and return the stored status if it is `cs_finished'. * file.h (struct file): Added `command_state' member. * commands.c (execute_command_line): Add `$' to the list of characters special to the shell. Wed Sep 21 15:57:41 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * read.c (read_all_makefiles): Call convert_to_pattern before recomputing the limits after adding the displaced rules. * make.c (main): Move calls to snap_deps, convert_to_pattern, and build_vpath_lists to read_all_makefiles. * read.c (read_all_makefiles): Install the default pattern rules before checking to remake the makefiles, displace these rules before reading in the makefiles, and then add the displaced rules to the chain after reading in all the makefiles. * make.c (main): Don't call install_default_pattern_rules or count_implicit_rule_limits. * make.h: Declare displace_pattern_rules and add_displaced_pattern_rules. * rule.c (displace_pattern_rules, add_displaced_pattern_rules): New functions to stow the chain and add the stowed chain on the end of the current chain. * make.texinfo (Implicit: Search Algorithm): Fixed PREV reference. * make.c (main): Call construct_include_path right after decoding the switches. * read.c (find_makefile): Use rename_file. * file.h: Declare rename_file. * file.c (rename_file): New function to rename a `struct file' and put it in the correct hash bucket. * read.c (find_makefile): New function to find and update a makefile. (read_all_makefilese): Use find_makefile. (read_makefile): Don't do updating. Removed UPDATEIT arg. * remake.c (update_file_1): Took out setting the `updated' member to -1 rather than 1 sometimes. * make.c (main): Made it print version info before doing anything else. * remake.c (library_file_mtime, f_mtime): Removed use of last two arguments to vpath_search. * rule.c (pattern_search): Removed use of last two arguments to vpath_search. * vpath.c (vpath_search, selective_vpath_search): Removed unused DIRPREFIX and DPLEN args. * read.c (read_makefile): Also turn off -n when updating makefiles. Tue Sep 20 17:01:10 1988 Roland McGrath (mcgrath at pepper.Berkeley.EDU) * Makefile: Put tags files in the tarfile. * read.c (read_makefile): Get the modtime of the makefile via a stat call so that a later file_mtime call won't do VPATH search for it. * read.c (read_makefile): Don't turn off -t and -q if the makefile was a command-line target. * make.c (main): Enter command-line targets as files and set their `cmd_target' members. * file.h (struct file): Added `cmd_target' member. * read.c (read_makefile): Temporarily turn off -t and -q while updating makefiles. * make.c (main): Don't use arg 0 from other_args (which is now argv[0]; i.e., the program's name). * read.c (read_makefile): Only return nonzero if commands were actually run to remake the makefile. * remake.c (update_file_1): Set FILE->updated to -1 if no commands were actually run (because no update was done or -t was given). * make.c (decode_switches): Fixed bug wherein xrealloc was passed bad args if it tried to expand other_args->list. * read.c (read_all_makefiles): Made it not look at the `MAKE' variable, just use argv[0]. Sun Sep 18 17:34:11 1988 Roland McGrath (mcgrath at paris.Berkeley.EDU) * read.c (rerun_make): New function to re-exec make. * make.c (construct_makeflags, construct_argv): New functions to construct the `MAKEFLAGS' variable and to construct an arg list from parsed info. * read.c (read_makefile): New arg UPDATEIT, if nonzero, says to update the makefile as a target before reading it in. When reading included makefiles, pass this as zero. Now returns nonzero if the makefile was updated, zero if not. (read_all_makefiles): Pass a nonzero UPDATEIT arg to read_makefile for all default and -f makefiles and all makefiles from the `MAKEFILES' variable. If any of the makefiles has changed, re-exec self to re-read them. * remake.c (update_file): Print a "File `foo' up to date'" message under -p. * commands.c (execute_file_commands): Allocate one byte for each of $^ and $< rather than zero if they are to be empty. Fri Sep 16 13:59:59 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Version 3.06. * make.c (command_switches): Fixed entry for `-o' switch. * make.texinfo: Renamed -c switch to -C. * make.c: Renamed -c switch to -C. * Miscellaneous de-linting. * read.c (record_files): Made it not free the storage for the name if it started with `./' and was therefore not quite the same as in the `struct file'. * read.c (record_files): If commands were specified twice, the error message specifies in what files and at what line numbers. * make.c (main): If any of the signals we usually fatal on were ignored by the parent (probably a shell), ignore them. * make.c (main): Print version info for -v, -p, or -d. (print_data_base): Don't print version info. It will be done in main. * variable.c: Increased number of hash buckets to 257. * file.c: Increased number of hash buckets to 1007. * rule.c (count_implicit_rule_limits): Moved comptation of `maxsuffix' to convert_to_pattern, since that function uses `maxsuffix', and must be called before count_implicit_rule_limits. * rule.c (pattern_search): If an existent (non-intermediate) dependendency was found via a terminal rule, set its `tried_implicit' flag, so it will never have implicit rule search done. * glob.c: Bug fix to avoid alloca(0). * arscan.c: USG and Sun386i fixes. Thu Sep 15 19:40:26 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * make.texinfo: Fixed some typos and spelling errors. Wed Sep 7 14:20:39 1988 Roland McGrath (mcgrath at helen.Berkeley.EDU) * make.c (decode_switches): Fixed bug wherein a bad option would give a useless error message and loop forever. Tue Sep 6 14:36:02 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.texinfo: Documented `shell' function. * variable.c (expand_function): New function `shell', does backquote-style command expansion of its arg. * commands.c (execute_command_line): Second arg OUTBUF, if not nil, gets filled in with a malloc'd buffer containing the piped stdout of the command. (execute_file_commands): Use above (pass nil). Mon Sep 5 17:03:49 1988 Roland McGrath (mcgrath at hecuba.Berkeley.EDU) * Makefile: Added copyright notice. Added a comment about defining `NO_MINUS_C_MINUS_O' if necessary. * Version 3.05. * rule.c (default_suffix_rules): Don't pass `-o' switches with `-c' switches if `NO_MINUS_C_MINUS_O' is #define'd. * make.texinfo: Documented `GNUmakefile'. * read.c (read_all_makefiles): Made it try default makefile `GNUmakefile' before others. * make.texinfo: Added new-style Texinfo header thingies. Sat Sep 3 18:09:39 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * Version 3.04. * make.texinfo (Chained Rules): Added a @cindex about using .PRECIOUS to preserve intermediate files. * remake.c (update_file_1): Made it not just return before executing commands under -p. * rule.c (default_pattern_rules, default_variables): Made it use `$(AR)' for `ar r' (to put files in archives). * vpath.c (build_vpath_lists): Made it recursively expand the `VPATH' variable (by using variable_expand instead of lookup_variable). * read.c (conditional_line): Made it not swallow whitespace after the comma in an `ifeq' using the `(a,b)' syntax. * rule.c (count_implicit_rule_limits): Made it not crash if a pattern rule dep begins with `/'. Sun Aug 28 15:51:12 1988 Roland McGrath (mcgrath at homer.Berkeley.EDU) * make.texinfo: Clarified that the arg to the `origin' function is a variable *name*, not a reference. * make.texinfo: Clarified that both -Idir and -I dir are allowed. Sat Aug 27 13:49:28 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * remake.c (remake_file): Made touching phonies work right. Wed Aug 24 20:40:48 1988 Roland McGrath (mcgrath at nutmeg.Berkeley.EDU) * make.texinfo: Removed reference to `RANLIB' variable. * Version 3.03. * variables.c (expand_function): Added `origin' function. * make.texinfo: Documented same. * read.c (record_files): Made double-colon entries work. Sat Aug 20 21:09:39 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (collapse_continuations): Bug fix from RMS. * rule.c (install_default_pattern_rules): Made it set the `in_use' flag of the created rules to zero, rather than letting it be random garbage. * rule.c (pattern_search): Fixed putting `also make' targets into file strucutres. * read.c (record_files): Fixed bug which made double-colon entries make it read off into space. * make.c (decode_switches): Made it understand `ignored' switches rather than dumping core. Sun Aug 14 16:49:00 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * read.c (read_makefile): Made `include' filenames be variable-expanded. * read.c (read_makefile): Fixed an error message. * read.c (read_makefile): Made it accept ^L's as whitespace. * make.c (next_token, end_of_token): Ditto. * vpath.c (vpath_search): Fixed it so that the general VPATH (from the variable) is always checked, even if a selective VPATH (from a directive) matched the filename. Sat Aug 13 14:20:46 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (decode_switches, main): Made the command switches be processed from a table of switches, variables, and types. No functions are passed argc and argv any more. They are passed arrays of strings they need to process. * read.c (read_all_makefiles): Made it take an array rather than argc and argv. (construct_include_path): Ditto. * make.c (collapse_continuations): Made it work right (I hope). * make.texinfo: Minor editorial changes. * read.c (read_makefile): Minor speed improvement by freeing and then mallocing something rather than reallocing it to avoid the unnecessary bcopy. Thu Aug 11 00:10:43 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.texinfo: Fixed some unquoted @'s. * make.texinfo: Documented multiple-target pattern rules. Miscellaneous minor editorial changes and corrections. * make.texinfo (Implicit: Catalogue of Rules): Removed the list of variables. That's what the next section is for. (Implicit: Implicit Variables): Made it agree with reality. Wed Aug 10 00:55:39 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * variable.c (print_variable_data_base): Fixed bug which made -p dump core. (This was a really idiotic bug.) * rule.c (pattern_search): Fixed a bug which made it make the `also_make' member of the file in question nil if the first of the successful rule's targets was the matching one. Made it use only as much storage as necessary in the `also_make' member. (create_pattern): Made it use only as much storage as necessary in the `lens' and `suffixes' members of the created rule. * remake.c (library_file_mtime): Made it `static'. * file.c: Added a declaration for `errno', which is declared in some 's, but not all. * file.h (struct file): Added `also_make' member for multiple-target implicit rules. * rule.c (pattern_search): Made it put the names of files updated by the given file's commands in its `also_make' member. * remake.c (update_file_1): Made it mark the files in a file's `also_make' member as updated when the file is updated. * variable.c (try_variable_definition): Fixed a bug which made it define a variable with the name of the whole definition when there was no space before the = or :=. * make.texinfo (Features): Made the changes which were made in RCS revision 2.7 but somehow lost since then. Added -W. Tue Aug 9 10:04:50 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * variable.h: Added `o_default' to `enum variable_origin'. * variable.c (print_variable_data_base): Made it print the origins of the variables. * rule.c (install_default_pattern_rules): Made it define the default variables with origin `o_default'. * make.texinfo: Documented -W. * make.c (decode_switches, main): Added the -W flag to give files a time-stamp of now, for a `what if' effect when used with -n. * commands.c (print_commands): Made it say `(built-in)' for commands that are built into the default ruleset. * read.c (record_file): Made .SUFFIXES get its deps frontwards (again). * rule.c (set_default_suffixes, convert_to_pattern): Made it read .SUFFIXES's deps frontwards, so the converted rules will not be in reverse order. * rule.c (new_pattern_rule): Fixed a bug wherein it would keep searching after it had removed a matching rule and ended up diddling with freed storage. * rule.c (freerule): Made it take the given rule off the chain. (new_pattern_rule, count_implicit_rule_limits): Use freerule to remove rules from the chain. * vpath.c (construct_vpath_list): Made it return after cleaning out all previous searchpaths when given a nil DIRPATH arg, so it won't go into the construction code and dump core dereferencing a nil pointer. * variable.c (patsubst_expand): Fixed a bug which made it not match correctly and sometimes dump core. Mon Aug 8 16:35:48 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * rule.c (default_suffix_rules): Made the .texinfo.dvi rule remove the files used in the comparison to determine whether or not a second TeX run is necessary. * make.texinfo: Fixed some overfull TeX hboxes. * make.texinfo (Implicit: Catalogue of Rules): Fixed a Texinfo error. * rule.c (create_pattern_rule): Fixed bug wherein index was not being passed its second arg. * read.c (getline): Merged back into readline. * rule.c (default_suffixes, default_suffix_rules, default_variables): Added .texinfo.info rule. * make.texinfo (Implicit: Catalogue of Rules): Documented .texinfo.dvi and .texinfo.info rules. * make.texinfo (Top): Changed `last updated' date to be correct (for the last time it was updated, not today). Changed `for version 3.00' since it's not going to be called that. Sat Aug 6 19:51:10 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * commands.c (print_commands): Added this function to print the contents of a `struct commands' for -p. * rule.c (print_rule_data_base): Use above. * file.c (print_file_data_base): Ditto. * rule.c (count_implicit_rule_limits, new_pattern_rule, install_pattern_rule, print_rule_data_base): Made it understand the changed `struct rule' and act accordingly. (freerule): Added this function to free all the storage used by a rule. * rule.c (pattern_search): Made it grok multiple targets of pattern rules. The matching is done properly, but at present, only the matching pattern's target is used to give deps and commands. Fri Aug 5 18:00:29 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * rule.c (struct rule): Changed name, namelen, and patsuffix members to targets, lens, and suffixes, which are arrays, for multiple targets. (create_pattern_rule): Now takes first arg TARGETS, a nil-terminated array of targets, rather than a single target and patsuffix pointer. * read.c (record_files): If it finds an implicit pattern rule, it collects all the targets into an array and passes the whole thing to create_pattern_rule. If there are non-pattern targets, it is a fatal error. Tue Aug 2 15:06:38 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (readline): Split backslash-newline checking from reading and buffer-expanding. (getline): Created to do the reading and buffer-expanding formerly done in readline. * rule.c (pattern_search): Made it reject nonterminal match-anything rules when a specific rule has matched, rather than rejecting terminal match-anything rules in this case. * rule.c (convert_to_pattern): Fixed a bug caused when the change to make it only recognize two-suffix rules whose target suffixes precede their dependency suffixes which made it work in the opposite direction (even worse than it started out). * rule.c (pattern_search): Made it reject nonterminal match-anything rules as intermediate targets when searching for both real and intermediate dependencies, rather than only when searching for intermediate ones. Sun Jul 31 00:33:56 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * rule.c (convert_to_pattern): Made it only recognize two-suffix rules whose target suffix comes before the dependency suffix in the .SUFFIXES list. * variable.c (define_automatic_variables): Made all automatic variables be defined with origin `o_automatic'. * variable.h: Added `o_automatic' to `enum variable_origin' * file.c (remove_intermediates): Made it not print an error message if the error was that the file does not exist. * rule.c: Removed `recursive' member from `struct rule'. * remake.c (library_file_mtime): Made it not use the directory hash functions, as reading in and hashing /usr/lib and /lib is slow and most likely unnecessary. * remake.c (remake_file): Changed message from ``No specification for making'' to ``No way to make'' so it will be short enough that most filenames will fit on a line. Made it look at the `recursive' member of the `struct commands', rather than of the `struct file' (which no longer has one). * commands.c (execute_file_commands): Made it look at the `recursive' member of the `struct commands', rather than of the `struct file' (which no longer has one). * file.h: Removed `recursive' member from `struct file'. * commands.h: Added `recursive' member to `struct commands'. * dep.h: Removed unused `quotedparen' member from `struct nameseq' and `struct dep'. * read.c (dequote): Removed this function. (multi_glob): Removed reference to `quotedparen' member of a `struct nameseq' and calls to dequote. * read.c (record_files): Made it set the stem for $* for all static pattern rules, not just those with commands given at that time. Removed check for recursive commands. Made it check for pairs of .SUFFIXES dependencies to reject as default goals as well as single ones (that don't start with dots). (read_makefile): Added checks for recursive commands to set the `recursive' flag in the `struct commands'. Sat Jul 30 15:47:23 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (find_next_token): Made the LENGTHPTR arg optionally nil. * make.c: Removed `files_made' variable which is defined static in remake.c and used only there. (main): Cleaned up somewhat. (decode_switches): Cleaned up a bit. Made an unknown option be a non-fatal error. (decode_env_switches): Made LEN arg unsigned. Cleaned up. (print_version): Made it say ``see the source'' rather than ``see the source file'', since there is more than one. * file.h: Made `num_intermediates' declared unsigned. * file.c: Made `num_intermediates' variable unsigned. (remove_intermediates): Removed unused FORMAT arg. (enter_file): Made it handle double-colon files properly, adding the new entry as the old entry's prev pointer. * dir.c: Re-indented the `struct dir' definition to be right. (dir_load): Cleaned up slighty. (file_exists_p): Removed comment saying we could use `access', since that is a bad idea (except for setuid programs). Cleaned up slightly. * commands.c: Changed some comments slightly. (execute_file_commands): Cleaned up a bit. Changed some comments, added others. Moved freeing of storage for $^ and $? to the same place as for the other automatic variables. (execute_command_line): Made `#' trigger a shell. Added some comments. Cleaned up a bit. Put all the special chars that trigger shells into an array easily changeable at the top. * ar.c: Added comments explaining each function. (ar_scan_1): Merged into ar_member_date. (ar_member_date): Changed call to ar_scan_1 to the body of that function. (ar_member_date_1): Simplified to a ?: expression rather than an if-else statement. (ar_member_touch): Changed error handling around a bit. None of these errors are fatal now. * variable.c (subst_expand): Added a new arg BY_WORD, to do substs only on full words. (patsubst_expand): Fixed bug which made calls whose patterns contained no `%' to not work correctly, by using above. (variable_expand): Pass extra arg to `subst_expand'. * variable.c (expand_function): Fixed bug which made `foreach' calls with one-word lists run off into never-never land. Fri Jul 29 20:12:36 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * variable.c (expand_function): Made a very minor speed improvement by avoiding an unnecessary strlen call. Wed Jul 27 16:01:47 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * rule.c (default_suffixes): Rearranged the list somewhat; added `.el' and `.elc' to speed things up (especially when building Emacs), for the same reason `.h' is there. * read.c (record_files): Changed `lineno' from `long' to `unsigned int'. Sun Jul 24 02:15:30 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * variable.c (expand_function): Eliminated use of `wstok' because it is non-reentrant and unreliable. Fixed a minor bug which would cause something not to be freed. * make.c (wstok): Removed `wstok' because it is no longer used. * variable.c (expand_function): Made `foreach' function put spaces between output texts like it's supposed to. Sat Jul 23 17:32:55 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * rule.c (default_suffixes, default_suffix_rules): Added rule to make %.dvi from %.texinfo. * dir.c (print_dir_data_base): Made it say a bit more. Fri Jul 22 23:13:16 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * make.c (print_data_base): Split this function up into one for each thing. * variable.c (print_variable_data_base): One of the above. * rule.c (print_rule_data_base): Ditto. * file.c (print_file_data_base): Ditto. * dir.c (print_dir_data_base): Ditto. * rule.c (install_pattern_rule): Fixed a bug which caused the terminal and recursive flags to always be zero for rules entered by this function. * make.texinfo (Rules: Double-colon): Added a paragraph explaining the purpose of double-colon rules. * make.texinfo (Implicit: Catalogue of Rules): Updated to reflect new C++, TeX, Web, and Texinfo rules. Other slight editorial changes. * commands.c (execute_file_commands): Fixed a bug wherein random memory could get written for files with no deps. Wed Jul 20 19:30:31 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * read.c (readline): Fix bug wherein it would not recognize a backslash-newline if the buffer filled up and was enlarged right before reading the newline. Tue Jul 19 19:55:02 1988 Roland McGrath (mcgrath at chilli.Berkeley.EDU) * read.c: Added default suffix rules for .cc (using $(C++), which defaults to `g++', and $(C++FLAGS)), .tex, .dvi, .web and .cweb (using $(TEX), $(WEAVE), $(TANGLE), $(CWEAVE) and $(CTANGLE)). Sat Jul 16 21:24:28 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Made error formats use %u rather than %ld for line numbers, which are now unsigned int's rather than long's. * read.c (conditional_line): Fixed some bugs caused by use of unsigned int rather than int in one place. * read.c (conditional_line): Put the info about active conditionals in a struct. (read_makefile): Make a new struct of info about conditionals for included makefiles and restore the old one after the included makefile has been read. * read.c (read_makefile): Don't try to read a makefile with name "" after giving an error message because an `include' directive gave no filename. * read.c (read_makefile): Give an error message for non-whitespace text after the filename in an `include' directive. * make.c (error): Take five args, like `fatal'. It managed to lose with only two. Is there a better way to do this without vfprintf? * read.c (read_makefile): Commands consisting of only whitespace are not the same as no commands. I thought I'd fixed this bug months ago; it seems to have come back. * make.c (collapse_continuations): All whitespace around a backslash-newline combination is turned into a single space. * Added COPYING file and copyright notices to all files. * make.texinfo (Running: Goals): Fix a typo. * read.c (do_define): Take an arg for the origin of the variable being defined. (read_makefile): Grok `override define'. * make.texinfo (Variables: Override Directive, Defining): Document the `override define' combination directive. * ar.c (ar_member_date): Make a 0 return from `ar_scan' return (time_t) -1 (nonexistent file), rather than (time_t) 0, which, when put in the `struct file', makes `file_mtime' try to get the mtime over and over again. * variable.c (pattern_matches): Fix a bug that made patterns not beginning with `%' never match. Fri Jul 15 21:01:44 1988 Roland McGrath (mcgrath at tully.Berkeley.EDU) * Took Make out of RCS. * Split the monolithic `make.c' into several smaller files. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/ChangeLog.2000066400000000000000000007517621317072305000167270ustar00rootroot000000000000002000-06-22 Paul D. Smith * job.c (start_job_command): Increment commands_started before the special check for ":" (empty command) to avoid spurious "is up to date" messages. Also move the test for question_flag after we expand arguments, and only stop if the expansion provided an actual command to run, not just whitespace. This fixes PR/1780. 2000-06-21 Paul D. Smith * read.c (read_makefile): If we find a semicolon in the target definition, remember where it was. If the line turns out to be a target-specific variable, add back the semicolon and everything after it. Fixes PR/1709. 2000-06-19 Paul D. Smith * config.h-vms.template: #define uintmax_t for this system. * config.ami.template: Ditto. * config.h.W32.template: Ditto. * configure.in: We don't use select(2) anymore, so don't bother checking for it. * acconfig.h: Ditto. * acinclude.m4: Ditto. * file.c (all_secondary): New static global; if 1 it means .SECONDARY with no prerequisites was seen in the makefile. (snap_deps): Set it appropriately. (remove_intermediates): Check it. (num_intermediates): Remove this global, it's not used anywhere. (considered): Move this to remake.c and make it static. * NEWS: Document the change to .SECONDARY. * make.texinfo (Special Targets): Document the change to .SECONDARY. * implicit.c (pattern_search): Remove the increment of num_intermediates; it's not used. * filedef.h: Remove num_intermediates and considered. * function.c (handle_function): If the last argument was empty, we were pretending it didn't exist rather than providing an empty value. Keep looking until we're past the end, not just at the end. * implicit.c (pattern_search): Multi-target implicit rules weren't expanding the "also made" targets correctly if the pattern didn't contain a slash but the target did; in that case the directory part wasn't being added back to the stem on the "also made" targets. Reported by Seth M LaForge , with a patch. 2000-06-17 Eli Zaretskii * Makefile.DOS.template (DESTDIR, bindir, datadir, libdir) (infodir, mandir, includedir): Support installation under a non-default DESTDIR. * remake.c (f_mtime): Fix the spelling of __MSDOS__. * configh.DOS.template (HAVE_FDOPEN, HAVE_MKSTEMP): Define. 2000-06-14 Paul D. Smith * acinclude.m4 (pds_WITH_GETTEXT): rewrite fp_WITH_GETTEXT and rename it to avoid confusion. This version is very specific: it won't accept any gettext that isn't GNU. If the user doesn't explicitly ask for the included gettext, we look to see if the system gettext is GNU (testing both the actual libintl library, and the libintl.h header file). Only if the system gettext is really GNU gettext will we allow it to be used. (pds_CHECK_SYSTEM_GETTEXT): A helper function. 2000-06-13 Paul D. Smith * gettext.h: If we have libintl.h, use that instead of any of the contents of gettext.h. We won't check for libintl.h unless we're using the system gettext. * function.c (func_word): Clarify error message. 2000-06-10 Paul Eggert Support nanosecond resolution on hosts with 64-bit time_t and uintmax_t (e.g. 64-bit Sparc Solaris), by splitting FILE_TIMESTAMP into a 30-bit part for nanoseconds, with the rest for seconds, if FILE_TIMESTAMP is at least 64 bits wide. * make.h: Always define FILE_TIMESTAMP to be uintmax_t, for simplicity. * filedef.h (FILE_TIMESTAMP_HI_RES, FILE_TIMESTAMP_LO_BITS) (UNKNOWN_MTIME, NONEXISTENT_MTIME, OLD_MTIME) (ORDINARY_MTIME_MIN, ORDINARY_MTIME_MAX): New macros. (FILE_TIMESTAMP_STAT_MODTIME): Now takes fname arg. All uses changed. (FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD) (FILE_TIMESTAMP_FROM_S_AND_NS): Remove. (FILE_TIMESTAMP_S, FILE_TIMESTAMP_NS): Use shifts instead of multiplication and division. Offset the timestamps by ORDINARY_MTIME_MIN. (file_timestamp_cons): New decl. (NEW_MTIME): Now just the maximal timestamp value, as we no longer use -1 to refer to nonexistent files. * file.c (snap_deps, print_file): Use NONEXISTENT_MTIME, UNKNOWN_MTIME, and OLD_MTIME instead of magic constants. * filedef.h (file_mtime_1): Likewise. * main.c (main): Likewise. * remake.c (update_file_1, notice_finished_file, check_dep) (f_mtime, name_mtime, library_search): Likewise. * vpath.c (selective_vpath_search): Likewise. * remake.c (f_mtime): Do not assume that (time_t) -1 equals NONEXISTENT_MTIME. When futzing with time stamps, adjust by multiples of 2**30, not 10**9. Do not calculate timestamp adjustments on DOS unless they are needed. * commands.c (delete_target): Do not assume that FILE_TIMESTAMP_S yields -1 for a nonexistent file, as that is no longer true with the new representation. * file.c (file_timestamp_cons): New function, replacing FILE_TIMESTAMP_FROM_S_AND_NS. All uses changed. (file_timestamp_now): Use FILE_TIMESTAMP_HI_RES instead of 1 < FILE_TIMESTAMPS_PER_S to determine whether we're using hi-res timestamps. (print_file): Print OLD_MTIME values as "very old" instead of as a timestamp. 2000-05-31 Paul Eggert * remake.c (name_mtime): Check for stat failures. Retry if EINTR. 2000-05-24 Paul D. Smith * main.c (decode_switches): The "positive_int" switch uses atoi() which succeeds for any input, and doesn't notice if extra, non-digit text is after the number. This causes make to mis-parse command lines like "make -j 5foo" as "make -j5" (ignoring "foo" completely) instead of "make -j0 5foo" (where "5foo" is a target). Fix this by checking the value by hand. We could use strtol() if we were sure of having it; this is the only questionable use of atoi() I found so we'll just stick with that. Fixes PR/1716. * i18n/ja.po, i18n/nl.po, i18n/pt_BR.po: New translation files. * configure.in (ALL_LINGUAS): Added pt_BR. 2000-05-22 Paul Eggert * remake.c (f_mtime): Fix bug when handling future odd timestamps in the WINDOWS32 case. Do not bother initializing static var to zero. Simplify code that works around WINDOWS32 and __MSDOS__ time skew brain damage. 2000-05-22 Paul Eggert * job.c: Don't include time.h, as make.h already does this. 2000-05-22 Paul Eggert * configure.in (AC_CHECK_HEADERS): Add sys/time.h. (AC_HEADER_TIME): Add. (clock_gettime): Prefer -lrt to -lposix4, for Solaris 7. (gettimeofday): Add check for standard version of gettimeofday. This merges changes written by Paul D. Smith. * file.c (file_timestamp_now): Use gettimeofday if available and if clock_gettime does not work. Don't bother with high-resolution clocks if file timestamps have only one-second resolution. * make.h : Include, conditionally on the usual TIME_WITH_SYS_TIME and HAVE_SYS_TIME_H macros. This is needed for gettimeofday. 2000-05-20 Paul D. Smith * read.c (read_makefile): We weren't keeping makefile names around unless there was a rule defined in them; but now we need to keep them for variables as well. Forget trying to be fancy: just keep every makefile name we successfully open. * remote-cstms.c (start_remote_job_p): Change DB_EXTRA (?) to DB_JOBS. 2000-05-17 Paul Eggert * commands.c (chop_commands): Ensure ctype macro args are nonnegative. * expand.c (variable_expand_string): Likewise. * function.c (subst_expand, lookup_function, msdos_openpipe): Likewise. * job.c (vms_redirect, start_job_command, new_job, child_execute_job, construct_command_argv_internal, construct_command_argv): Likewise. * main.c (decode_env_switches, quote_for_env): Likewise. * misc.c (collapse_continuations, end_of_token, end_of_token_w32, next_token): Likewise. * read.c (read_makefile, do_define, conditional_line, find_char_unquote,get_next_mword): Likewise. * variable.c (try_variable_definition): Likewise. * vpath.c (construct_vpath_list): Likewise. * w32/pathstuff.c (convert_vpath_to_windows32): Likewise. 2000-05-10 Eli Zaretskii * main.c (main) [__MSDOS__]: Add SIGFPE to signals we block when running child programs, to prevent Make from dying on Windows 9X when the child triggers an FP exception. 2000-05-08 Paul D. Smith * dir.c (find_directory) [WINDOWS32]: If we strip a trailing "\" from the directory name, remember to add it back. The argument might really be inside a longer string (e.g. %Path%) and if you don't restore the "\" it'll be truncated permanently. Fixes PR/1722. Reported by 2000-05-02 Paul D. Smith * job.c (construct_command_argv_internal) [WINDOWS32]: Added "rd" and "rmdir" to the list of command.com commands. Reported by Elod Horvath 2000-04-24 Paul D. Smith * i18n/ja.po: New translation file from the Japanese language team. 2000-04-18 Paul D. Smith * remake.c (f_mtime): If ar_member_date() returns -1 (the member doesn't exist), then return (FILE_TIMESTAMP)-1 rather than returning the timestamp calculated from the value -1. Fixes PR/1696. Reported by Gilles Bourhis . 2000-04-17 Paul D. Smith * config.h.W32.template: Add LOCALEDIR macro resolving to "". * w32/subproc/sub_proc.c (process_begin): Remove reference to debug_flag; change it to a DB() call. Fixes PR/1700. Reported by Jim Smith 2000-04-17 Bruno Haible * arscan.c [BeOS]: Add replacement for nonexistent from GNU binutils. 2000-04-11 Paul D. Smith * function.c (expand_builtin_function): If no arguments were provided, just quit early rather than changing each function to test for this. (function_table[]): Change the min # of arguments to 0 for all those functions for which it makes sense (currently everything that used to take a minimum of 1 argument, except $(call ...)). Fixes PR/1689. 2000-04-09 Eli Zaretskii * README.DOS: Add instructions to install a binary distro. Mention latest versions of Windows. 2000-04-07 Eli Zaretskii * main.c (main): Rename TMP_TEMPLATE into DEFAULT_TMPDIR, and use it for the directory of the temporary file. If P_tmpdir is defined, use it in preference to "/tmp/". Try $TMPDIR, $TEMP, and $TMP in the environment before defaulting to DEFAULT_TMPDIR. (print_version): Add year 2000 to the Copyright line. 2000-04-04 Paul D. Smith * Version 3.79 released. * make.texinfo: Update documentation with new features for 3.79. * function.c (func_wordlist): Don't re-order arguments to wordlist. 2000-04-03 Paul D. Smith * remake.c (f_mtime): Archive member timestamps are stored as time_t, without nanoseconds. But, f_mtime() wants to return nanosecond info on those systems that support it. So, convert the return value of ar_member_date() into a FILE_TIMESTAMP, using 0 as the nanoseconds. 2000-03-28 Paul D. Smith * Version 3.78.92 released. * build.template: Updates for gettext support; some bugs fixed. 2000-03-27 Paul D. Smith * config.guess, config.sub: Updated from config CVS archive at :pserver:anoncvs@subversions.gnu.org:/home/cvs as of today. * read.c (record_files): Check if expanding a static pattern rule's prerequisite pattern leaves an empty string as the prerequisite, and issue an error if so. Fixes PR/1670. (read_makefile): Store the starting linenumber for a rule in TGTS_STARTED. (record_waiting_files): Use the TGTS_STARTED value for the file location passed to record_file() instead of the current linenumber, so error messages list the line where the target was defined instead of the line after the end of the rule definition. * remake.c (start_updating, finish_updating, is_updating): Fix PR/1671; circular dependencies in double-colon rules are not diagnosed. These macros set the updating flag in the root double-colon file instead of the current one, if it's part of a double-colon list. This solution provided by Tim Magill ; I just changed the macro names :). (update_file_1): Call them. (check_dep): Call them. The change to not automatically evaluate the $(call ...) function's arguments breaks recursive use of call. Although using $(if ...) and $(foreach ...) in $(call ...) macros is important, the error conditions generated are simply to obscure for me to feel comfortable with. If a method is devised to get both working, we'll revisit. For now, remove this change. * function.c (function_table): Turn on the expand bit for func_call. (func_call): Don't expand arguments for builtin functions; that will have already been done. 2000-03-26 Paul D. Smith * file.c (remove_intermediates): Never remove targets explicitly requested on the command-line by checking the cmd_target flag. Fixed PR/1669. 2000-03-23 Paul Eggert * filedef.h (FILE_TIMESTAMP_STAT_MODTIME): Use st_mtime instead of st_mtim.tv_sec; the latter doesn't work on Unixware. 2000-03-18 Paul D. Smith * file.c (file_hash_enter): If we're trying to change a file into itself, just return. We used to assert this wasn't true, but someone came up with a weird case involving archives. After playing with it for a while I decided it was OK to ignore it. * default.c: Define COFLAGS to empty to avoid spurious warnings. * filedef.h: Change #if ST_MTIM_NSEC to #ifdef; this is a macro containing the name of the nsec field, not true/false. * make.h: Ditto. Reported by Marco Franzen . 2000-03-08 Tim Magill * remake.c (update_file): Return the exit status of the pruned file when pruning, not just 0. Fixes PR/1634. 2000-02-24 Paul D. Smith * configure.in: Close a minor potential security hole; if you're reading makefiles from stdin (who does that?) you could run into a race condition with the temp file using mktemp() or tmpnam(). Add a check for mkstemp() and fdopen(). * main.c (open_tmpfile): New function to open a temporary file. If we have mkstemp() (and fdopen()), use that. If not use mktemp() or tmpnam(). If we have fdopen(), use open() to open the file O_CREAT|O_EXCL. If not, fall back to normal fopen() (insecure). (main): Call it. * job.c (child_execute_job) [VMS]: Call it. * variable.c (lookup_variable): If we find a variable which is being expanded, then note it but keep looking through the rest of the set list to see if we can find one that isn't. If we do, return that. If we don't, return the original. Fix for PR/1610. While implementing this I realized that it also solves PR/1380 in a much more elegant way. I don't know what I was smoking before. So, remove the hackage surrounding the original fix for that (see below). Change this function back to lookup_variable and remove the extra setlist argument. * variable.h (recursively_expand_setlist): Remove the macro, rename the prototype, and remove the extra setlist argument. (lookup_variable): Ditto. * expand.c (recursively_expand): Rename and remove the extra setlist argument. (reference_variable): Use lookup_variable() again. (allocated_variable_append): Remove the extra setlist argument. 2000-02-21 Paul D. Smith * README.template: A few updates. * i18n/de.po: New version from the German translation team. 2000-02-09 Paul D. Smith * Version 3.78.91 released. 2000-02-07 Paul D. Smith * read.c (read_makefile): Reset *p2 to ':', not *colonp. If any filenames contained backslashes the resulting output (without backslashes) will be shorter, so setting *colonp doesn't change the right character. Fix for PR/1586. For += target-specific variables we need to remember which variable set we found the variable in, so we can start looking from there in the next iteration (otherwise we might see it again in recursively_expand and fail!). This is turning into a hack; if it gets any worse we'll have to rethink this entire algorithm... implementing expansion of these references separately from the "normal" expansion, say, instead of using the same codepath. Actually, it's already "worse enough" :-/. Fix for PR/1380. * variable.h (recursively_expand_setlist): Rename recursively_expand to add a struct variable_set_list argument, and make a macro for recursively_expand. (lookup_variable_setlist): Rename lookup_variable to add a struct variable_set_list argument, and make a macro for lookup_variable. * expand.c (recursively_expand_setlist): Take an extra struct variable_set_list argument and pass it to allocated_variable_append(). (reference_variable): Use lookup_variable_setlist() and pass the returned variable_set_list to recursively_expand_setlist. (allocated_variable_append): Take an extra setlist argument and use this as the starting place when searching for the appended expansion. If it's null, use current_variable_set_list as before. * variable.c (lookup_variable_setlist): If the LISTP argument is not nil, set it to the list containing the variable we found. 2000-02-04 Paul D. Smith * variable.c (print_variable): Write out filename/linenumber information for the variable definition if present. (define_variable_in_set): Store filename information if provided. (define_variable, define_variable_for_file): Removed. (try_variable_definition): Use define_variable_loc() to keep variable definition location information. * read.c (read_makefile): Keep variable definition location info. (do_define): Ditto. (record_target_var): Ditto. * variable.h (define_variable_in_set): New fileinfo argument. (define_variable, define_variable_loc, define_variable_for_file): Declare new macros. Fix PR/1407: * filedef.h (struct file): Rename patvar to pat_variables and make it just a variable_set_list; we need our own copy of the pattern variable's variable set list here to avoid overwriting the global one. * variable.c (initialize_file_variables): Move the instantiation of the pat_variables pointer here. Only do the search after we're done reading the makefiles so we don't search too early. If there's a pat_variables value, set up the variables next ptr. * expand.c (variable_expand_for_file): Remove the setup of the pat_variables info; it's done earlier now to ensure the parent's pattern variables are set up correctly as well. 2000-02-03 Paul D. Smith * job.c (sh_chars_dos) [WINDOWS32]: Add "&" as a shell metacharacter for the W32 DOS shell. Reported by Warren Jones . 2000-02-02 Paul D. Smith Fixes for the OpenVMS port from Hartmut Becker * config.h-vms [VMS]: Define LOCALEDIR to something; needed for the expansion of bindtextdomain() even though it's a no-op. * vmsfunctions.c (strcmpi): Remove duplicate definition of strcmpi(). (readdir): Use DB() instead of testing debug_flag. * dir.c (file_impossible) [VMS]: Search "p" not "name". * job.c [VMS]: Switch from debug_flag to the new DB macro. Add some i18n _() macros (even though VMS doesn't yet support it). * function.c (patsubst_expand): Change "len" to not be unsigned to avoid type mismatches. * main.c (main): Declare signame_init() if we're going to call it. 2000-01-29 Eli Zaretskii * Makefile.DOS.template: Track changes in Makefile.in (install-recursive, uninstall-recursive): Add missing targets. (DESTDIR): Define. (install-binPROGRAMS, uninstall-binPROGRAMS): Use $(DESTDIR). * default.c (default_variables) [__MSDOS__]: Define CXX to gpp. 2000-01-27 Paul D. Smith * gettext.c: Some warning cleanups, and a fix for systems which don't define HAVE_ALLOCA (the workaround code was included twice). 2000-01-26 Paul D. Smith * Version 3.78.90 released. 2000-01-25 Paul D. Smith Change gettext support to use the simplified version in libit 0.7. * getopt.c, make.h: Use gettext.h instead of libintl.h. * ABOUT-NLS, gettext.h, gettext.c: New files from libit 0.7. Modified to remove some static declarations which aren't defined. * acconfig.h: Use new gettext #defines. * acinclude.m4: Add fp_WITH_GETTEXT; remove AM_GNU_GETTEXT. * configure.in: Call fp_WITH_GETTEXT instead. * Makefile.am: New gettext stuff. Also force inclusion of glob files for systems which have LIBC glob. * i18n/Makefile.am, i18n/.cvsignore: New dir for translation files. * i18n/de.po, i18n/es.po, i18n/fr.po, i18n/ko.po, i18n/nl.po: * i18n/pl.po, i18n/ru.po: Import translations already done for earlier versions of GNU make. Thanks for that work!! * po/Makefile.in.in, po/POTFILES.in: Removed. 2000-01-23 Paul D. Smith * main.c (decode_debug_flags): If debug_flag is set, enable all debugging levels. (debug_flag): Resurrect this flag variable. (switches): Make -d give the old behavior of turning on all debugging. Change --debug alone to emit basic debugging and take optional arguments to expand debugging. * NEWS: Document the new debugging options. * remake.c (no_rule_error): Remove this function. This tries to fix a real problem--see the description with the introduction of this function below. However, the cure is worse than the disease and this approach won't work. (remake_file): Put the code from no_rule_error back here. (update_file_1): Remove call to no_rule_error. * filedef.h (struct file): Remove mfile_status field. 2000-01-22 Paul D. Smith Integrate GNU gettext support. * configure.in: Add AM_GNU_GETTEXT. * Makefile.am: Add options for setting LOCALEDIR, -Iintl, etc. * acinclude.m4: Add gettext autoconf macros. * acconfig.h: Add new gettext #defines. * make.h: Include libintl.h. Make sure _() and N_() macros are declared. Make gettext() an empty macro is NLS is disabled. * main.c (struct command_switch switches[]): Can't initialize static data with _() (gettext calls), so use N_() there then use gettext() directly when printing the strings. * remake.c (no_rule_error): The string constants can't be static when initializing _() macros. * file.c (print_file): Reformat a few strings to work better for translation. * po/POTFILES.in, po/Makefile.in.in: New files. Take Makefile.in.in from the latest GNU tar distribution, as that version works better than the one that comes with gettext. * NEWS: Mention i18n ability. 2000-01-21 Paul D. Smith Installed patches for the VMS port. Patches provided by: Hartmut Becker * readme.vms, arscan.c, config.h-vms, default.c, dir.c, file.c: * implicit.c, job.c, make.h, makefile.com, makefile.vms, rule.c: * variable.c, vmsdir.h, vmsfunctions.c, vmsify.c, glob/glob.c: * glob/glob.h: Installed patches. See readme.vms for details. 2000-01-14 Andreas Schwab * dir.c (read_dirstream): Initialize d_type if it exists. 2000-01-11 Paul D. Smith Resolve PR/xxxx: don't automatically evaluate the $(call ...) function's arguments. While we're here, clean up argument passing protocol to always use simple nul-terminated strings, instead of sometimes using offset pointers to mark the end of arguments. This change also fixes PR/1517. Reported by Damien GIBOU . * function.c (struct function_table_entry): Remove the negative required_args hack; put in explicit min and max # of arguments. (function_table): Add in the max value. Turn off the expand bit for func_call. (expand_builtin_function): Test against minimum_args instead of the obsolete required_args. (handle_function): Rewrite this. We don't try to be fancy and pass one style of arguments to expanded functions and another style to non-expanded functions: pass pointers to nul-terminated strings to all functions. (func_call): Rewrite this. If we are invoking a builtin function and it's supposed to have its arguments expanded, do that (since it's not done by handle_function for $(call ...) anymore). For non-builtins, just add the variables as before but mark them as recursive so they'll be expanded later, as needed. (func_if): All arguments are vanilla nul-terminated strings: remove trickery with "argv[1]-1". (func_foreach): Ditto. * expand.c (expand_argument): If the second arg is NULL, expand the entire first argument. * job.c (new_job): Zero the child struct. This change was just made to keep some heap checking software happy, not because there was an actual bug (the important memory was being cleared properly). 1999-12-15 Paul D. Smith * variable.c (print_variable): Print the variable with += if the append flag is set. * implicit.c (pattern_search): Remove the extra check of the implicit flag added on 8/24/1998. This causes problems and the reason for the change was better resolved by the change made to check_deps() on 1998-08-26. This fixes PR/1423. 1999-12-08 Paul D. Smith * dir.c (dir_setup_glob): On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a macro for stat64(). Assignment doesn't work in that case. So, stat is a macro, make a local wrapper function to invoke it. (local_stat): Wrapper function, if needed. Reported by Andrej Borsenkow . 1999-12-02 Paul D. Smith * remake.c (update_file): Move the considered test outside the double-colon loop, _but_ make sure we test the double_colon target not the "current" target. If we stop early because one double-colon target is running, mark all the rest considered and try to start their prerequisites (so they're marked considered). Fix for PR/1476 suggested by Tim Magill . 1999-11-22 Rob Tulloh * function.c (windows32_openpipe, func_shell): Correct Windows32 problem where $(shell nosuchfile) would incorrectly exit make. The fix is to print the error and let make continue. Reported by David Masterson . * w32/subproc/misc.c (arr2envblk): Memory leak fix. 1999-11-21 Paul D. Smith Rework GNU make debugging to provide different levels of output. * NEWS: mention it. * debug.h: New file. Define various debugging levels and macros. * function.c, implicit.c, job.c, main.c, misc.c, read.c, remake.c * remote-cstms.c, vmsfunctions.c: Replace all code depending on debug_flag with invocations of debugging macros. * make.h: Remove debug_flag and DEBUGPR, add db_level. 1999-11-18 Paul Eggert * acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): Work around a problem with the QNX 4.25 shell, which doesn't propagate exit status of failed commands inside shell assignments. 1999-11-17 Paul D. Smith * function.c (func_if): Find the end of the arg list by testing the next item for NULL; any other test is not correct. Reported by Graham Reed (PR/1429). Fix += when used in a target-specific variable context. * variable.h: New bitfield APPEND set if we have a += target-specific variable. * variable.c (try_variable_definition): Add an argument to specify if we're trying a target-specific variable. If we are and it's an append style, don't append it, record it as normal recursive, but set the APPEND flag so it'll be expanded later. * main.c (handle_non_switch_argument): Use new try_variable_definition() signature. * read.c (read_makefile,record_target_var): Ditto. * expand.c (allocated_variable_append): New function: like allocated_variable_expand(), but we expand the same variable name in the context of the ``next'' variable set, then we append this expanded value. (recursively_expand): Invoke it, if the APPEND bit is set. 1999-11-10 Paul D. Smith * file.c (snap_deps): If the .NOTPARALLEL target is defined, turn off parallel builds for this make only (still allow submakes to be run in parallel). * main.c: New variable, ``not_parallel''. * make.h: Add an extern for it. * job.c (new_job): Test NOT_PARALLEL as well as JOB_SLOTS. * NEWS: Add info on .NOTPARALLEL. * make.texinfo (Special Targets): Document it. * configure.in (GLOBDIR): Set to "glob" if we need to build the glob library. * Makefile.am (SUBDIRS): Use the GLOBDIR variable instead of "glob" so we don't try to build glob if we don't need to (if we have GLIBC glob). Reported by Lars Hecking . * main.c (main): Don't put "***" in the clock skew warning message. Reported by karl@gnu.org. * make.h: Remove unneeded signal setup. * signame.c: Remove extraneous #includes; some versions of Ultrix don't protect against multiple inclusions and it causes compile errors. Reported by Simon Burge . 1999-10-15 Paul D. Smith * main.c (quote_for_env): Rename from quote_as_word(). * make.h, *.c: Prefer strchr() and strrchr() in the code rather than index() and rindex(). Define strchr/strrchr in terms of index/rindex if the former aren't supported. * default.c (CHECKOUT,v): Replace the fancy, complicated patsubst/filter expression with a simple $(if ...) expression. * main.c (print_usage): Add the bug reporting mailing address to the --help output, as per the GNU coding standards. Reported by Paul Eggert . * README.customs: Installed information on running Customs-ized GNU make and setuid root, collected by Ted Stern . * read.c (read_all_makefiles): PR/1394: Mark the end of the next token in the MAKEFILES value string _before_ we dup it. 1999-10-13 Paul D. Smith * configure.in (make_cv_sys_gnu_glob): We used to add the -Iglob flag to CPPFLAGS, but that loses if the user specifies his own CPPFLAGS; this one gets added _after_ his and if he happens to have an old or broken glob.h--boom. Instead, put it in GLOBINC and SUBST it. * Makefile.am (INCLUDES): Add @GLOBINC@ to the INCLUDES macro; these things get on the compile line well before the user's CPPFLAGS. 1999-10-12 Paul D. Smith * remake.c (notice_finished_file): If we get here and -n is set, see if all the command lines are marked recursive. If so, then we ran every command there is, so check the mtime on this file just like we would normally. If not, we assume the command we didn't run would updates the target and set mtime of the target to "very new". * job.c (start_job_command): Update lines_flags in the file's cmds structure with any per-line tokens we found (`@', `-', `+'). 1999-10-08 Paul D. Smith * variable.c (initialize_file_variables): Always recurse to initialize the parent's file variables: the parent might not have any rules to run so it might not have been initialized before this--we need this to set up the chain properly for target-specific variables. 1999-09-29 Paul Eggert * main.c (quote_as_word): Always quote for decode_env_switches instead of for the shell, so that arguments with strange characters are are passed to submakes correctly. Remove double_dollars arg; we always double dollars now. All callers changed. (decode_env_switches): Don't run off the end of an environment variable whose contents ends in a unescaped backslash. 1999-09-23 Paul D. Smith * commands.c, function.c, job.c, read.c: Cast arguments to ctype.h functions/macros to _unsigned_ char for portability. * remake.c, function.c: Compiler warning fixes: the second argument to find_next_token() should be an _unsigned_ int*. Reported by Han-Wen Nienhuys . 1999-09-23 Paul D. Smith * Version 3.78.1 released. * make.texinfo: Update version/date stamp. * main.c (main): Argh. For some reason we were closing _all_ the jobserver pipes before we re-exec'd due to changed makefiles. This means that any re-exec got a "jobserver unavailable" error :-/. I can't believe we didn't notice this before. 1999-09-22 Paul D. Smith * Version 3.78 released. * main.c (main): Only fail on multiple --jobserver-fds options if they aren't all the same. Some makefiles use things like $(MAKE) $(MFLAGS) which will cause multiple, identical copies of --jobserver-fds to show up. 1999-09-16 Paul D. Smith * main.c (define_makeflags): Zero out FLAGSTRING to avoid uninitialized memory reads when checking *p != '-' in the loop. 1999-09-15 Paul D. Smith * Version 3.77.97 released. * configure.in (MAKE_HOST): AC_SUBST this so it will go into the makefile. * Makefile.am (check-local): Print a success banner if the check succeeds. (check-regression): A bit of fine-tuning. 1999-09-15 Eli Zaretskii * README.DOS.template: Document requirements for the test suite. * Makefile.DOS.template: Updates to allow the test suite to run from "make check". * main.c (main): Handle it if argv[0] isn't an absolute path. 1999-09-13 Paul D. Smith * Version 3.77.96 released. * Makefile.am (loadavg): Use CPPFLAGS, etc. to make sure we get all the right #defines to compile. (check-regression): Look for the regression test suite in the make package itself. If we're building remotely, use symlinks to make a local copy. (dist-hook): Put the test suite into the tar file. * configure.in: Look for perl for the test suite. 1999-09-10 Paul Eggert * acinclude.m4 (AC_SYS_LARGEFILE_FLAGS): If on HP-UX 10.20 or later, and using GCC, define __STDC_EXT__; this works around a bug in GCC 2.95.1. 1999-09-08 Paul D. Smith * main.c (print_version): Ugh. GLIBC's configure tries to check make version strings and is too aggressive with their matching expressions. I've struck a deal with them to leave the version output as-is for 3.78, and they'll change their configure checks so that I can change this back in the future. 1999-09-07 Eli Zaretskii * job.c (construct_command_argv_internal) [__MSDOS__]: Add "echo" and "unset" to the list of builtin shell commands. * configh.DOS.template (MAKE_HOST): Define to "i386-pc-msdosdjgpp" which is the canonical name of the DJGPP host. 1999-09-05 Paul D. Smith * Version 3.77.95 released. * make.texinfo (Make Errors): Document some new jobserver error messages. 1999-09-04 Eli Zaretskii * make.texinfo (Make Errors): Document the hint about 8 spaces instead of a TAB. (Call Function, Quick Reference): Use @code{$(1)}, not @var. * main.c (main) [__MSDOS__]: Say "on this platform" instead of "on MS-DOS", since the MSDOS version could run on Windows. 1999-09-03 Paul D. Smith * remake.c (notice_finished_file): Always set mtime_before_update if it's not been set, not just if we ran some rules. Otherwise we may have a situation where a target's prerequisite was rebuilt but not changed, so this target's rules weren't run, then update_goal_chain() sees mtime_before_update != last_mtime and thinks that the top-level target changed when it really didn't. This can cause an infinite loop when remaking makefiles. (update_goal_chain): If we get back to the top and we don't know what the goal's last_mtime was, find it now. We need to know so we can compare it to mtime_before_update later (this is only crucial when remaking makefiles--should we only do it then?) 1999-09-02 Paul D. Smith * read.c (read_makefile): If "override" appears as the first prerequisite, look further to ensure this is really a target-specific variable definition, and not just some prerequisite named "override". 1999-09-01 Paul D. Smith * function.c (IS_PATHSEP) [WINDOWS32]: Allow backslash separators for W32 platforms. * read.c (record_files) [WINDOWS32]: Allow backslash separators for W32 platforms. * implicit.c (pattern_search) [WINDOWS32]: Allow backslash separators for W32 platforms. * configure.in (MAKE_HOST): Define it to be the canonical build host info, now that we need AC_CANONICAL_HOST anyway (for large file support). * version.c (make_host): Define a variable to MAKE_HOST so we're sure to get it from the local config.h. * main.c (print_version): Use it in the version information. * config.ami.template: Add MAKE_HOST. * configh.dos.template: Ditto. * config.h.W32.template: Ditto. * config.h-vms.template: Ditto. * main.c (main): Close the jobserver file descriptors if we need to re-exec ourselves. Also print more reasonable error if users force -jN for submakes. This may be common for a while until people use the jobserver feature. If it happens, we ignore the existing jobserver stuff and use whatever they specified on the commandline. (define_makeflags): Fixed a long-standing bug: if a long name only option comes immediately after a single letter option with no argument, then the option string is constructed incorrectly. For example, with -w and --jobserver-fds you get "-w-jobserver-fds..." instead of "-w --jobserver-fds..."; add in an extra " -". * make.texinfo (Phony Targets): Add another example of using .PHONY with subdirectories/recursive make. 1999-08-30 Paul D. Smith * README.W32.template: Renamed from README.W32 so it's autogenerated during the dist. A few minor modifications. * configure.in: Check for kstat_open before AC_FUNC_GETLOADAVG since the latter needs to know whether the former exists to give an accurate result. 1999-08-26 Rob Tulloh * NMakefile [WINDOWS32]: Now more robust. If you change a file under w32/subproc, the make.exe will be relinked. Also added some tests to make sure erase commands won't fail when executed in a pristine build environment. * w32/subproc/sub_proc.c [WINDOWS32]: Added support for HAVE_CYGWIN_SHELL. If you are using the Cygwin B20.1 release, it is now possible to have have native support for this shell without having to rely on klutzy BATCH_MODE_ONLY_SHELL. * config.h.W32 [WINDOWS32]: Added HAVE_CYGWIN_SHELL macro which users can define if they want to build make to use this shell. * README.W32 [WINDOWS32]: Added informaton about HAVE_CYGWIN_SHELL. Cleaned up text a bit to make it more current. 1999-08-26 Paul Eggert Support large files in AIX, HP-UX, and IRIX. * acinclude.m4 (AC_LFS): Remove. Superseded by AC_SYS_LARGEFILE. (AC_SYS_LARGEFILE_FLAGS, AC_SYS_LARGEFILE_SPACE_APPEND, AC_SYS_LARGEFILE_MACRO_VALUE, AC_SYS_LARGEFILE): New macros. (jm_AC_TYPE_UINTMAX_T): Check for busted compilers that can't shift or divide unsigned long long. (AM_PROG_CC_STDC): New macro; a temporary workaround of a bug in automake 1.4. * configure.in (AC_CANONICAL_HOST): Add; required by new AC_SYS_LARGEFILE. (AC_SYS_LARGEFILE): Renamed from AC_LFS. (AM_PROG_CC_STDC): Add. * config.guess, config.sub: New files, needed for AC_CANONICAL_HOST. 1999-08-25 Paul Eggert * make.h (CHAR_MAX): New macro. * main.c (struct command_switch): c is now int, so that it can store values greater than CHAR_MAX. (switches): Replace small numbers N with CHAR_MAX+N-1, to avoid problems with non-ASCII character sets. (short_option): New macro. (init_switches, print_usage, define_makeflags): Use it instead of isalnum. 1999-08-25 Paul D. Smith * Version 3.77.94 released. * main.c (main) [__MSDOS__]: If the user uses -j, warn that it's not supported and reset it. * make.h (ISDIGIT): Obtained this from the textutils distribution. * main.c (decode_switches): Use it. * function.c (is_numeric): Use it. * main.c (struct command_switch): Store the switch char in an unsigned char to shut up GCC about using it with ctype.h macros. Besides, it _is_ always unsigned. 1999-08-24 Paul D. Smith * make.texinfo: Change "dependency" to "prerequisite" and "dependencies" to "prerequisites". Various other cleanups related to the terminology change. * file.c: Change debugging and error messages to use "prerequisite" instead of "dependency". * implicit.c: Ditto. * remake.c: Ditto. * NEWS: Document it. 1999-08-23 Paul D. Smith * remake.c (update_file): Move the considered check into the double-colon rule loop, so we consider double-colon rules individually (otherwise after the first is pruned, the rest won't get run). * README.template: Minor changes. Remove the debugging features of the jobserver, so it no longer writes distinct tokens to the pipe. Thus, we don't need to store the token we get. A side effect of this is to remove a potential "unavailable token" situation: make-1 invokes make-2 with its special token and make-3 with a normal token; make-2 completes. Now we're waiting for make-3 but using 2 tokens; our special token is idle. In the new version we don't have special tokens per se, we merely decide if we already have a child or not. If we don't, we don't need a token. If we do, we have to get one to run the next child. Similar for putting tokens back: if we're cleaning up the last child, we don't put a token back. Otherwise, we do. * main.c: Add a new, internal flag --jobserver-fds instead of overloading the meaning of -j. Remove job_slots_str and add the stringlist jobserver_fds. (struct command_switch): We don't need the int_string type. (switches[]): Add a new option for --jobserver-fds and remove conditions around -j. Make the description for the former 0 so it doesn't print during "make --help". (main): Rework jobserver parsing. If we got --jobserver-fds make sure it's valid. We only get one and job_slots must be 0. If we're the toplevel make (-jN without --jobserver-fds) create the pipe and write generic tokens. Create the stringlist struct for the submakes. Clean up the stringlist where necessary. (init_switches): Remove int_string handling. (print_usage): Don't print internal flags (description ptr is 0). (decode_switches): Remove int_string handling. (define_makeflags): Remove int_string handling. * job.c: Remove my_job_token flag and all references to the child->job_token field. (free_job_token): Remove this and merge it into free_child(). (reap_children): Rework the "reaped a child" logic slightly. Don't call defunct free_job_token anymore. Always call free_child, even if we're dying. (free_child): If we're not freeing the only child, put a token back in the pipe. Then, if we're dying, don't bother to free. (new_job): If we are using the jobserver, loop checking to see if a) there are no children or b) we get a token from the pipe. * job.h (struct child): Remove the job_token field. 1999-08-20 Paul D. Smith * variable.c (try_variable_definition): Allocate for variable expansion in f_append with a simple variable: if we're looking at target-specific variables we don't want to trash the buffer. Noticed by Reiner Beninga . 1999-08-16 Eli Zaretskii * main.c (main) [__MSDOS__]: Mirror any backslashes in argv[0], to avoid problems in shell commands that use backslashes as escape characters. 1999-08-16 Paul D. Smith * Version 3.77.93 released. 1999-08-13 Paul D. Smith Another jobserver algorithm change. We conveniently forgot that the blocking bit is shared by all users of the pipe, it's not a per-process setting. Since we have many make processes all sharing the pipe we can't use the blocking bit as a signal handler flag. Instead, we'll dup the pipe's read FD and have the SIGCHLD handler close the dup'd FD. This will cause the read() to fail with EBADF the next time we invoke it, so we know we need to reap children. We then re-dup and reap. * main.c (main): Define the job_rfd variable to hold the dup'd FD. Actually dup the read side of the pipe. Don't bother setting the blocking bit on the file descriptor. * make.h: Declare the job_rfd variable. * job.c (child_handler): If the dup'd jobserver pipe is open, close it and assign -1 to job_rfd to notify the main program that we got a SIGCHLD. (start_job_command): Close the dup'd FD before exec'ing children. Since we open and close this thing so often it doesn't seem worth it to use the close-on-exec bit. (new_job): Remove code for testing/setting the blocking bit. Instead of EAGAIN, test for EBADF. If the dup'd FD has been closed, re-dup it before we reap children. * function.c (func_shell): Be a little more accurate about the length of the error string to allocate. * expand.c (variable_expand_for_file): If there's no filenm info (say, from a builtin command) then reset reading_file to 0. 1999-08-09 Paul D. Smith * maintMakefile: Use g in sed (s///g) to replace >1 variable per line. * Makefile.DOS.template [__MSDOS__]: Fix mostlyclean-aminfo to remove the right files. 1999-08-01 Eli Zaretskii * function.c (msdos_openpipe) [__MSDOS__]: *Really* return a FILE ptr. 1999-08-01 Paul D. Smith New jobserver algorithm to avoid a possible hole where we could miss SIGCHLDs and get into a deadlock. The original algorithm was suggested by Roland McGrath with a nice refinement by Paul Eggert. Many thanks as well to Tim Magill and Howard Chu, who also provided many viable ideas and critiques. We all had a fun week dreaming up interesting ways to use and abuse UNIX syscalls :). Previously we could miss a SIGCHLD if it happened after we reaped the children but before we re-entered the blocking read. If this happened to all makes and/or all children, make would never wake up. We avoid this by having the SIGCHLD handler reset the blocking bit on the jobserver pipe read FD (normally read does block in this algorithm). Now if the handler is called between the time we reap and the time we read(), and there are no tokens available, the read will merely return with EAGAIN instead of blocking. * main.c (main): Set the blocking bit explicitly here. * job.c (child_handler): If we have a jobserver pipe, set the non-blocking bit for it. (start_waiting_job): Move the token stuff back to new_job; if we do it here then we're not controlling the number of remote jobs started! (new_job): Move the check for job slots to _after_ we've created a child structure. If the read returns without getting a token, set the blocking bit then try to reap_children. * make.h (EINTR_SET): Define to test errno if EINTR is available, or 0 otherwise. Just some code cleanup. * arscan.c (ar_member_touch): Use it. * function.c (func_shell): Use it. * job.c (reap_children): Use it. * remake.c (touch_file): Use it. 1999-07-28 Paul D. Smith * make.h: Define _() and N_() macros as passthrough to initiate NLS support. * : Add _()/N_() around translatable strings. 1999-07-27 Paul D. Smith * read.c: Make sure make.h comes before other headers. 1999-07-26 Paul D. Smith * make.texinfo (Quick Reference): Update with the new features. 1999-07-25 Eli Zaretskii * remake.c [__MSDOS__]: Don't include variables.h, it's already included. * function.c (msdos_openpipe) [__MSDOS__]: Return FILE ptr. (func_shell) [__MSDOS__]: Fix the argument list. * Makefile.DOS.template: Update from Makefile.in. * README.DOS.template: Configure command fixed. * configh.dos.template: Update to provide definitions for uintmax_t, fd_set_size_t, and HAVE_SELECT. 1999-07-24 Paul D. Smith * Version 3.77.91 released. * configure.in: Changes to the boostrapping code: if build.sh.in doesn't exist configure spits an error and generates an empty build.sh file which causes make to be confused. * maintMakefile: Don't build README early. 1999-07-23 Paul D. Smith * job.c (my_job_token): This variable controls whether we've handed our personal token to a subprocess or not. Note we could probably infer this from the value of job_slots_used, but it's clearer to just keep it separately. Job_slots_used isn't really relevant when running the job server. (free_job_token): New function: free a job token. If we don't have one, no-op. If we have the personal token, reclaim it. If we have another token, write it back to the pipe. (reap_children): Call free_job_token. (free_child): Call free_job_token. (start_job_command): Remove duplicate test for '+' in the command. If we don't appear to be running a recursive make, close the jobserver filedescriptors. (start_waiting_job): If our personal token is available, use that instead of going to the server pipe. (*): Add the token value to many debugging statements, and print the child target name in addition to the ptr hex value. Change the default "no token" value from '\0' to '-' so it looks better in the output. * main.c (main): Install the child_handler with sigaction() instead of signal() if we have it. On SysV systems, signal() uses SysV semantics which are a pain. But sigaction() always does what we want. (main): If we got job server FDs from the environment, test them to see if they're open. If not, the parent make closed them because it didn't think we were a submake. Print a warning and suggestion to use "+" on the submake invocation, and hard-set to -j1 for this instance of make. (main): Change the algorithm for assigning slots to be more robust. Previously make checked to see if it thought a subprocess was a submake and if so, didn't give it a token. Since make's don't consume tokens we could spawn many of makes fighting for a small number of tokens. Plus this is unreliable because submakes might not be recognized by the parent (see above) then all the tokens could be used up by unrecognized makes, and no one could run. Now every make consumes a token from its parent. However, the make can also use this token to spawn a child. If the make wants more than one, it goes to the jobserver pipe. Thus there will never be more than N makes running for -jN, and N*2 processes (N makes and their N children). Every make can always run at least one job, and we'll never deadlock. (Note the closing of the pipe for non-submakes also solves this, but this is still a better algorithm.) So! Only put N-1 tokens into the pipe, since the topmost make keeps one for itself. * configure.in: Find sigaction. Disable job server support unless the system provides it, in addition to either waitpid() or wait3(). 1999-07-22 Rob Tulloh * arscan.c (ar_member_touch) [WINDOWS32]: The ar_date field is a string on Windows, not a timestamp. 1999-07-21 Paul D. Smith * Version 3.77.90 released. * Makefile.am (AUTOMAKE_OPTIONS): Require automake 1.4. * function.c: Rearrange so we don't need to predeclare the function_table array; K&R C compilers don't like that. * acinclude.m4 (AC_FUNC_SELECT): Ouch; this requires an ANSI C compiler! Change to work with K&R compilers as well. * configure.in (AC_OUTPUT): Put build.sh back. I don't know how I thought it would work this way :-/. We'll have to think of something else. * Makefile.am: Remove rule to create build.sh. * default.c (default_suffix_rules): Rearrange the default command lines to conform to POSIX rules (put the filename argument $< _after_ the OUTPUT_OPTION, not before it). * various: Changed !strncmp() calls to strneq() macros. * misc.c (sindex): Make slightly more efficient. * dir.c (file_impossible): Change savestring(X,strlen(X)) to xstrdup(). * implicit.c (pattern_search): Ditto. * main.c (enter_command_line_file): Ditto. (main): Ditto. * misc.c (copy_dep_chain): Ditto. * read.c (read_makefile): Ditto. (parse_file_seq): Ditto. (tilde_expand): Ditto. (multi_glob): Ditto. * rule.c (install_pattern_rule): Ditto. * variable.c (define_variable_in_set): Ditto. (define_automatic_variables): Ditto. * vpath.c (construct_vpath_list): Ditto. * misc.c (xrealloc): Some reallocs are non-standard: work around them in xrealloc by calling malloc if PTR is NULL. * main.c (main): Call xrealloc() directly instead of testing for NULL. * function.c (func_sort): Don't try to free NULL; some older, non-standard versions of free() don't like it. * configure.in (--enable-dmalloc): Install some support for using dmalloc (http://www.dmalloc.com/) with make. Use --enable-dmalloc with configure to enable it. * function.c (function_table_entry): Whoops! The function.c rewrite breaks backward compatibility: all text to a function is broken into arguments, and extras are ignored. So $(sort a,b,c) returns "a"! Etc. Ouch. Fix it by making a positive value in the REQUIRED_ARGS field mean exactly that many arguments to the function; any "extras" are considered part of the last argument as before. A negative value means at least that many, but may be more: in this case all text is broken on commas. (handle_function): Stop when we've seen REQUIRED_ARGS args, if >0. (expand_builtin_function): Compare number of args to the absolute value of REQUIRED_ARGS. 1999-07-20 Paul D. Smith * job.c (start_job_command): Ensure that the state of the target is cs_running. It might not be if we skipped all the lines due to -n (for example). * commands.c (execute_file_commands): If we discover that the command script is empty and succeed early, set cs_running so the modtime of the target is still rechecked. * rule.c (freerule): Free the dependency list for the rule. * implicit.c (pattern_search): When turning an intermediate file into a real target, keep the also_make list. Free the dep->name if we didn't use it during enter_file(). 1999-07-16 Paul D. Smith * read.c (read_makefile): Don't allocate the commands buffer until we're sure we found a makefile and won't return early (mem leak). * job.c (start_job_command): Broken #ifdef test: look for F_SETFD, not FD_SETFD. Close-on-exec isn't getting set on the bad_stdin file descriptor and it's leaking :-/. * getloadavg.c (getloadavg): Ditto. 1999-07-15 Paul D. Smith * read.c (read_makefile): Fix some potential memory stomps parsing `define' directives where no variable name is given. * function.c (func_call): Rename from func_apply. Various code cleanup and tightening. (function_table): Add "call" as a valid builtin function. * make.texinfo (Call Function): Document it. * NEWS: Announce it. 1999-07-09 Eli Zaretskii * variable.c (try_variable_definition) [__MSDOS__, WINDOWS32]: Treat "override SHELL=" the same as just "SHELL=". 1999-07-09 Paul D. Smith * job.c (start_waiting_job): Don't get a second job token if we already have one; if we're waiting on the load to go down start_waiting_job() might get called twice on the same file. * filedef.h (struct file): Add new field, mtime_before_update. When notice_finished_file runs it assigns the cached last_mtime to this field. * remake.c (update_goal_chain): Notice that a file wasn't updated by asking if it changed (g->changed) and comparing the current cached time (last_mtime) with the previous one, stored in mtime_before_update. The previous check ("did last_mtime changed during the run of update_file?") fails for parallel builds because last_mtime is set during reap_children, before update_file is run. This causes update_goal_chain to always return -1 (nothing rebuilt) when running parallel (-jN). This is OK during "normal" builds since our caller (main) treats these cases identically in that case, but if when rebuilding makefiles the difference is very important, as it controls whether we re-exec or not. * file.c (file_hash_enter): Copy the mtime_before_update field. (snap_deps): Initialize mtime_before_update to -1. * main.c (main): Initialize mtime_before_update on old (-o) and new (-W) files. 1999-07-08 Paul D. Smith * main.c (switches): Define a new switch -R (or --no-builtin-variables). This option disables the defining of all the GNU make builtin variables. (main): If -R was given, force -r as well. * default.c (define_default_variables): Test the new flag. * make.h: Declare global flag. * make.texinfo (Options Summary): Document the new option. (Implicit Variables): Ditto. 1999-07-06 Paul D. Smith * make.texinfo (Options Summary): Correct examples in --print-data-base option summary (problem reported by David Morse ). * arscan.c: Add support for archives in Windows (VC++). Frank Libbrecht provided info on how to do this. * NMakefile.template (CFLAGS_any): Remove NO_ARCHIVES from the compile line. * build_w32.bat: Ditto. * remake.c (no_rule_error): Fix -include/sinclude so it doesn't give errors if you try to -include the same file twice. (updating_makefiles): New variable: we need to know this info in no_rule_error() so we know whether to print an error or not. (update_file_1): Unconditionally call no_rule_error(), don't try to play games with the dontcare flag. 1999-06-14 Paul D. Smith * make.texinfo (Remaking Makefiles): Add a description of how to prevent implicit rule searches for makefiles. * make.1: Remove statement that make continues processing when -v is given. 1999-06-14 Paul D. Smith * read.c (read_makefile): Cast -1 arguments to variable_expand_string() to long. Alexandre Sauve reports that without casts, this breaks on a NEC SUPER-UX SX-4 system (and it's wrong without a cast anyway). Of course, (a) I'd really love to start using function prototypes, and (b) there's a whole slew of issues related to int vs. long and signed vs. unsigned in the length handling of variable buffers, etc. Gross. Needs a complete mucking-out. * expand.c (variable_expand): Ditto. * acinclude.m4 (AC_FUNC_SELECT): Slight enhancement for AIX 3.2 by Lars Hecking . * read.c (get_next_mword): Allow colons to be escaped in target names: fix for regression failure. 1999-04-26 Paul D. Smith * main.c (main): Reset read_makefiles to empty after processing so we get the right error message. 1999-04-25 Paul D. Smith * make.texinfo: Updates to @dircategory and @direntry suggested by Karl Berry . 1999-04-23 Eli Zaretskii * job.c (start_job_command) [__MSDOS__]: Call unblock_sigs before turning off dos_command_running, so child's signals produce the right effect. * commands.c (fatal_error_signal) [__MSDOS__]: Use EXIT_FAILURE instead of 1. 1999-04-18 Eli Zaretskii * configh.dos.template: Update to recognize that version 2.02 of DJGPP contains sys_siglist stuff. 1999-04-14 Paul D. Smith * make.texinfo (Options/Recursion): Document the job server. (Parallel): Tweaks. 1999-04-13 Paul D. Smith Implement a new "job server" feature; the implementation was suggested by Howard Chu . * configure.in (job-server): New disable option for job server support--it's enabled by default. If it works well this will go away. * NEWS: Summarize the new feature. * acconfig.h: New definition MAKE_JOBSERVER if job server support is enabled. * config.h-vms.template: Undef MAKE_JOBSERVER for this port. * config.h.W32.template: Ditto. * config.ami.template: Ditto. * main.c (struct command_switch): Add a new type: int_string. (switches[]) Use int_string for -j if MAKE_JOBSERVER. (init_switches): Initialize the new int_string switch type. (print_usage): New function, extracted from decode_switches(). (decode_switches): Call it. Decode the new int_string switch type. (define_makeflags): Add new int_string switch data to MAKEFLAGS. (job_fds[]) Array to contain the pipe file descriptors. (main): Parse the job_slots_str option results. If necessary, create the pipe and seed it with tokens. Set the non-blocking bit for the read fd. Enable the signal handler for SIGCHLD even if we have a non-hanging wait; it's needed to interrupt the select() in job.c:start_waiting_job(). * make.h: Declare job_fds[]. * job.h (struct child): Add job_token field to store the token for this job (if any). * job.c (reap_children): When a child is fully reaped, release the token back into the pipe. (free_child): If the child to be freed still has a token, put it back. (new_job): Initialize the job_token member. (start_waiting_job): For local jobs, if we're using the pipe, get a token before we check the load, etc. We do this by performing a non-blocking read in a loop. If the read fails, no token is available. Do a select on the fd to wait for a token. We need to re-enable the signal handler for SIGCHLD even if we have a non-hanging waitpid() or wait3(), so that the signal will interrupt the select() and we can wake up to reap children. (child_handler): Re-enable the signal handler. The count is still kept although it's not needed or used unless you don't have waitpid() or wait3(). 1999-04-10 Paul D. Smith * main.c (main): Reset the considered bit on all the makefiles if something failed to update; we need to examine them again if they appear as normal targets in order to get the proper error message. 1999-04-09 Paul D. Smith Performance enhancement from Tim Magill . * remake.c (update_file): If you have large numbers of dependencies and you run in parallel, make can spend considerable time each pass through the graph looking at branches it has already seen. Since we only reap_children() when starting a pass, not in the middle, if a branch has been seen already in that pass nothing interesting can happen until the next pass. So, we toggle a bit saying whether we've seen this target in this pass or not. (update_goal_chain): Initially set the global considered toggle to 1, since all targets initialize their boolean to 0. At the end of each pass, toggle the global considered variable. * filedef.h (struct file): Per-file considered toggle bit. * file.c: New global toggle variable considered. 1999-04-05 Paul D. Smith * arscan.c (ar_scan): Added support for ARFZMAG (compressed archives?) for Digital UNIX C++. Information provided by Patrick E. Krogel . (ar_member_touch): Ditto. 1999-04-03 Paul D. Smith * remake.c (f_mtime): If: a) we found a file and b) we didn't create it and c) it's not marked as an implicit target and d) it is marked as an intermediate target, then it was so marked due to an .INTERMEDIATE special target, but it already existed in the directory. In this case, unset the intermediate flag so we won't delete it when make is done. It feels like it would be cleaner to put this check in update_file_1() but I worry it'll get missed... 1999-04-01 Paul D. Smith * job.c (construct_command_argv_internal): Use bcopy() to copy overlapping strings, rather than strcpy(). ISO C says the latter is undefined. Found this in a bug report from 1996! Ouch! 1999-03-31 Paul D. Smith * read.c (readline): Ignore carriage returns at the end of the line, to allow Windows-y CRLF line terminators. 1999-03-30 Paul D. Smith * configure.in: Don't put build.sh here, since build.sh.in doesn't exist initially. This cause autoreconf and automake to fail when run on a clean CVS checkout. Instead, we create build.sh in the Makefile (see below). * Makefile.am: Remove BUILT_SOURCES; this is no longer relevant. Put those files directly into EXTRA_DIST so they're distributed. Create a local build rule to create build.sh. Create a local maintainer-clean rule to delete all the funky maintainers files. * maintMakefile: Makefile.in depends on README, since automake fails if it doesn't exist. Also don't remove glob/Makefile.in here, as it causes problems. 1999-03-26 Paul D. Smith * configure.in: Substitute GLOBLIB if we need the link the glob/libglob.a library. * Makefile.am (make_LDADD): Use the subst variable GLOBLIB so we don't link the local libglob.a at all if we don't need it. * build.template: Don't compile glob/*.o unless we want globlib. * maintMakefile (build.sh.in): Substitute the glob/*.o files separately. 1999-03-25 Paul D. Smith * make.texinfo: Various typos and additions, pointed out by James G. Sack . 1999-03-22 Paul D. Smith * make.texinfo (Functions): Add a new section documenting the new $(error ...) and $(warning ...) functions. Also updated copyright dates. * NEWS: Updated for the new functions. * function.c (func_error): Implement the new $(error ...) and $(warning ...) functions. (function_table): Insert new functions into the table. (func_firstword): Don't call find_next_token() with argv[0] itself, since that function modifies the pointer. * function.c: Cleanups and slight changes to the new method of calling functions. 1999-03-20 Han-Wen Nienhuys * function.c: Rewrite to use one C function per make function, instead of a huge switch statement. Also allows some cleanup of multi-architecture issues, and a cleaner API which makes things like func_apply() simple. * function.c (func_apply): Initial implementation. Expand either a builtin function or a make variable in the context of some arguments, provided as $1, $2, ... $N. 1999-03-19 Eli Zaretskii 1999-03-19 Rob Tulloh * job.c (construct_command_argv_internal): Don't treat _all_ backslashes as escapes, only those which really escape a special character. This allows most normal "\" directory separators to be treated normally. 1999-03-05 Paul D. Smith * configure.in: Check for a system strdup(). * misc.c (xstrdup): Created. Suggestion by Han-Wen Nienhuys . * make.h: Prototype xstrdup(). * remake.c (library_search): Use it. * main.c (main): Use it. (find_and_set_default_shell): Use it. * job.c (construct_command_argv_internal): Use it. * dir.c (find_directory): Use it. * Makefile.am, configure.in: Use AC_SUBST_FILE to insert the maintMakefile instead of "include", to avoid automake 1.4 incompatibility. 1999-03-04 Paul D. Smith * amiga.c, amiga.h, ar.c, arscan.c, commands.c, commands.h, * default.c, dep.h, dir.c, expand.c, file.c, filedef.h, function.c, * implicit.c, job.c, job.h, main.c, make.h, misc.c, read.c, remake.c * remote-cstms.c, remote-stub.c, rule.h, variable.c, variable.h, * vpath.c, Makefile.ami, NMakefile.template, build.template, * makefile.vms: Updated FSF address in the copyright notice. * variable.c (try_variable_definition): If we see a conditional variable and we decide to set it, re-type it as recursive so it will be expanded properly later. 1999-02-22 Paul D. Smith * NEWS: Mention new .LIBPATTERNS feature. * make.texinfo (Libraries/Search): Describe the use and ramifications of the new .LIBPATTERNS variable. * remake.c (library_search): Instead of searching only for the hardcoded expansion "libX.a" for a library reference "-lX", we obtain a list of patterns from the .LIBPATTERNS variable and search those in order. * default.c: Added a new default variable .LIBPATTERNS. The default for UNIX is "lib%.so lib%.a". Amiga and DOS values are also provided. * read.c: Remove bogus HAVE_GLOB_H references; always include vanilla glob.h. 1999-02-21 Paul D. Smith * function.c (expand_function): Set value to 0 to avoid freeing it. * variable.c (pop_variable_scope): Free the value of the variable. (try_variable_definition): For simple variables, use allocated_variable_expand() to avoid stomping on the variable buffer when we still need it for other things. * arscan.c: Modified to support AIX 4.3 big archives. The changes are based on information provided by Phil Adams . 1999-02-19 Paul D. Smith * configure.in: Check to see if the GNU glob library is already installed on the system. If so, _don't_ add -I./glob to the compile line. Using the system glob code with the local headers is very bad mojo! Rewrite SCCS macros to use more autoconf facilities. * Makefile.am: Move -Iglob out of INCLUDES; it'll get added to CPPFLAGS by configure now. Automake 1.4 introduced its own "include" feature which conflicts with the maintMakefile stuff. A hack that seems to work is add a space before the include :-/. * build.template: Move -Iglob out of the compile line; it'll get added to CPPFLAGS by configure now. 1999-02-16 Glenn D. Wolf * arscan.c (ar_scan) [VMS]: Initialized VMS_member_date before calling lbr$get_index since if the archive is empty, VMS_get_member_info won't get called at all, and any leftover date will be used. This bug shows up if any member of any archive is made, followed by a dependency check on a different, empty archive. 1998-12-13 Martin Zinser * config.h-vms [VMS]: Set _POSIX_C_SOURCE. Redefine the getopt functions so we don't use the broken VMS versions. * makefile.com [VMS]: Allow debugging. * dir.c (dir_setup_glob) [VMS]: Don't extern stat() on VMS. 1998-11-30 Paul D. Smith * signame.c (init_sig): Check the sizes of signals being set up to avoid array overwrites (if the system headers have problems). 1998-11-17 Paul D. Smith * read.c (record_files): Clean up some indentation. 1998-11-08 Han-Wen Nienhuys * rule.c (print_rule_data_base): Fix arguments to fatal() call. 1998-10-13 Paul D. Smith * job.c (start_job_command): If the command list resolves to no chars at all (e.g.: "foo:;$(empty)") then command_ptr is NULL; quit early. 1998-10-12 Andreas Schwab * rule.c (print_rule_data_base): Ignore num_pattern_rules if it is zero. 1998-10-09 Paul D. Smith * read.c (read_makefile): Allow non-empty lines to expand to the empty string after variable, etc., expansion, and be ignored. 1998-09-21 Paul D. Smith * job.c (construct_command_argv_internal): Only add COMMAND.COM "@echo off" line for non-UNIXy shells. 1998-09-09 Paul D. Smith * w32/subproc/sub_proc.c: Add in missing HAVE_MKS_SHELL tests. 1998-09-04 Paul D. Smith * read.c (read_makefile): If we hit the "missing separator" error, check for the common case of 8 spaces instead of a TAB and give an extra comment to help people out. 1998-08-29 Paul Eggert * configure.in (AC_STRUCT_ST_MTIM_NSEC): Renamed from AC_STRUCT_ST_MTIM. * acinclude.m4 (AC_STRUCT_ST_MTIM_NSEC): Likewise. Port to UnixWare 2.1.2 and pedantic Solaris 2.6. * acconfig.h (ST_MTIM_NSEC): Renamed from HAVE_ST_MTIM, with a new meaning. * filedef.h (FILE_TIMESTAMP_FROM_S_AND_NS): Use new ST_MTIM_NSEC macro. 1998-08-26 Paul D. Smith * remake.c (check_dep): For any intermediate file, not just secondary ones, try implicit and default rules if no explicit rules are given. I'm not sure why this was restricted to secondary rules in the first place. 1998-08-24 Paul D. Smith * make.texinfo (Special Targets): Update documentation for .INTERMEDIATE: if used with no dependencies, then it does nothing; old docs said it marked all targets as intermediate, which it didn't... and which would be silly :). * implicit.c (pattern_search): If we find a dependency in our internal tables, make sure it's not marked intermediate before accepting it as a found_file[]. 1998-08-20 Paul D. Smith * ar.c (ar_glob): Use existing alpha_compare() with qsort. (ar_glob_alphacompare): Remove it. Modify Paul Eggert's patch so we don't abandon older systems: * configure.in: Warn the user if neither waitpid() nor wait3() is available. * job.c (WAIT_NOHANG): Don't syntax error on ancient hosts. (child_handler, dead_children): Define these if WAIT_NOHANG is not available. (reap_children): Only track the dead_children count if no WAIT_NOHANG. Otherwise, it's a boolean. * main.c (main): Add back signal handler if no WAIT_NOHANG is available; only use default signal handler if it is. 1998-08-20 Paul Eggert Install a more robust signal handling mechanism for systems which support it. * job.c (WAIT_NOHANG): Define to a syntax error if our host is truly ancient; this should never happen. (child_handler, dead_children): Remove. (reap_children): Don't try to keep separate track of how many dead children we have, as this is too bug-prone. Just ask the OS instead. (vmsHandleChildTerm): Fix typo in error message; don't mention child_handler. * main.c (main): Make sure we're not ignoring SIGCHLD/SIGCLD; do this early, before we could possibly create a subprocess. Just use the default behavior; don't have our own handler. 1998-08-18 Eli Zaretskii * read.c (read_makefile) [__MSDOS__, WINDOWS32]: Add code to recognize library archive members when dealing with drive spec mess. Discovery and initial fix by George Racz . 1998-08-18 Paul D. Smith * configure.in: Check for stdlib.h explicitly (some hosts have it but don't have STDC_HEADERS). * make.h: Use HAVE_STDLIB_H. Clean up some #defines. * config.ami: Re-compute based on new config.h.in contents. * config.h-vms: Ditto. * config.h.W32: Ditto. * configh.dos: Ditto. * dir.c (find_directory) [WINDOWS32]: Windows stat() fails if directory names end with `\' so strip it. 1998-08-17 Paul D. Smith * make.texinfo: Added copyright year to the printed copy. Removed the price from the manual. Change the top-level reference to running make to be "Invoking make" instead of "make Invocation", to comply with GNU doc standards. * make.h (__format__, __printf__): Added support for these in __attribute__ macro. (message, error, fatal): Use ... prototype form under __STDC__. Add __format__ attributes for printf-style functions. * configure.in (AC_FUNC_VPRINTF): Check for vprintf()/_doprnt(). * misc.c (message, error, fatal): Add preprocessor stuff to enable creation of variable-argument functions with appropriate prototypes, that works with ANSI, pre-ANSI, varargs.h, stdarg.h, v*printf(), _doprnt(), or none of the above. Culled from GNU fileutils and slightly modified. (makefile_error, makefile_error): Removed (merged into error() and fatal(), respectively). * amiga.c: Use them. * ar.c: Use them. * arscan.c: Use them. * commands.c: Use them. * expand.c: Use them. * file.c: Use them. * function.c: Use them. * job.c: Use them. * main.c: Use them. * misc.c: Use them. * read.c: Use them. * remake.c: Use them. * remote-cstms.c: Use them. * rule.c: Use them. * variable.c: Use them. * make.h (struct floc): New structure to store file location information. * commands.h (struct commands): Use it. * variable.c (try_variable_definition): Use it. * commands.c: Use it. * default.c: Use it. * file.c: Use it. * function.c: Use it. * misc.c: Use it. * read.c: Use it. * rule.c: Use it. 1998-08-16 Paul Eggert * filedef.h (FILE_TIMESTAMP_PRINT_LEN_BOUND): Add 10, for nanoseconds. 1998-08-16 Paul Eggert * filedef.h (FLOOR_LOG2_SECONDS_PER_YEAR): New macro. (FILE_TIMESTAMP_PRINT_LEN_BOUND): Tighten bound, and try to make it easier to understand. 1998-08-14 Paul D. Smith * read.c (read_makefile): We've already unquoted any colon chars by the time we're done reading the targets, so arrange for parse_file_seq() on the target list to not do so again. 1998-08-05 Paul D. Smith * configure.in: Added glob/configure.in data. We'll have the glob code include the regular make config.h, rather than creating its own. * getloadavg.c (main): Change return type to int. 1998-08-01 Paul Eggert * job.c (reap_children): Ignore unknown children. 1998-07-31 Paul D. Smith * make.h, filedef.h, dep.h, rule.h, commands.h, remake.c: Add prototypes for functions. Some prototypes needed to be moved in order to get #include order reasonable. 1998-07-30 Paul D. Smith * make.h: Added MIN/MAX. * filedef.h: Use them; remove FILE_TIMESTAMP_MIN. 1998-07-30 Paul Eggert Add support for sub-second timestamp resolution on hosts that support it (just Solaris 2.6, so far). * acconfig.h (HAVE_ST_MTIM, uintmax_t): New undefs. * acinclude.m4 (jm_AC_HEADER_INTTYPES_H, AC_STRUCT_ST_MTIM, jm_AC_TYPE_UINTMAX_T): New defuns. * commands.c (delete_target): Convert file timestamp to seconds before comparing to archive timestamp. Extract mod time from struct stat using FILE_TIMESTAMP_STAT_MODTIME. * configure.in (C_STRUCT_ST_MTIM, jm_AC_TYPE_UINTMAX_T): Add. (AC_CHECK_LIB, AC_CHECK_FUNCS): Add clock_gettime. * file.c (snap_deps): Use FILE_TIMESTAMP, not time_t. (file_timestamp_now, file_timestamp_sprintf): New functions. (print_file): Print file timestamps as FILE_TIMESTAMP, not time_t. * filedef.h: Include if available and if HAVE_ST_MTIM. (FILE_TIMESTAMP, FILE_TIMESTAMP_STAT_MODTIME, FILE_TIMESTAMP_MIN, FILE_TIMESTAMPS_PER_S, FILE_TIMESTAMP_FROM_S_AND_NS, FILE_TIMESTAMP_DIV, FILE_TIMESTAMP_MOD, FILE_TIMESTAMP_S, FILE_TIMESTAMP_NS, FILE_TIMESTAMP_PRINT_LEN_BOUND): New macros. (file_timestamp_now, file_timestamp_sprintf): New decls. (struct file.last_mtime, f_mtime, file_mtime_1, NEW_MTIME): time_t -> FILE_TIMESTAMP. * implicit.c (pattern_search): Likewise. * vpath.c (vpath_search, selective_vpath_search): Likewise. * main.c (main): Likewise. * remake.c (check_dep, name_mtime, library_search, f_mtime): Likewise. (f_mtime): Use file_timestamp_now instead of `time'. Print file timestamp with file_timestamp_sprintf. * vpath.c (selective_vpath_search): Extract file time stamp from struct stat with FILE_TIMESTAMP_STAT_MODTIME. 1998-07-28 Paul D. Smith * Version 3.77 released. * dosbuild.bat: Change to DOS CRLF line terminators. * make-stds.texi: Update from latest version. * make.texinfo (Options Summary): Clarify that the -r option affects only rules, not builtin variables. 1998-07-27 Paul D. Smith * make.h: Make __attribute__ resolve to empty for non-GCC _and_ for GCC pre-2.5.x. * misc.c (log_access): Print UID/GID's as unsigned long int for maximum portability. * job.c (reap_children): Print PIDs as long int for maximum portability. 1998-07-24 Eli Zaretskii * Makefile.DOS (*_INSTALL, *_UNINSTALL): Replace `true' with `:'. 1998-07-25 Paul D. Smith * Version 3.76.94 released. 1998-07-23 Paul D. Smith * config.h.W32.template: Make sure all the #defines of macros here have a value (e.g., use ``#define HAVE_STRING_H 1'' instead of just ``#define HAVE_STRING_H''. Keeps the preprocessor happy in some contexts. * make.h: Remove __attribute__((format...)) stuff; using it with un-prototyped functions causes older GCC's to fail. * Version 3.76.93 released. 1998-07-22 Paul D. Smith * file.c (print_file_data_base): Fix average calculation. 1998-07-20 Paul D. Smith * main.c (die): Postpone the chdir() until after remove_intermediates() so that intermediate targets with relative pathnames are removed properly. 1998-07-17 Paul D. Smith * filedef.h (struct file): New flag: did we print an error or not? * remake.c (no_rule_error): New function to print error messages, extraced from remake_file(). * remake.c (remake_file): Invoke the new error print function. (update_file_1): Invoke the error print function if we see that we already tried this target and it failed, but that an error wasn't printed for it. This can happen if a file is included with -include or sinclude and couldn't be built, then later is also the dependency of another target. Without this change, make just silently stops :-/. 1998-07-16 Paul D. Smith * make.texinfo: Removed "beta" version designator. Updated ISBN for the next printing. 1998-07-13 Paul Eggert * acinclude.m4: New AC_LFS macro to determine if special compiler flags are needed to allow access to large files (e.g., Solaris 2.6). * configure.in: Invoke it. 1998-07-08 Eli Zaretskii * Makefile.DOS: track changes in Makefile.in. 1998-07-07 Paul D. Smith * remote-cstms.c (start_remote_job): Move gethostbyaddr() to the top so host is initialized early enough. * acinclude.m4: New file. Need some special autoconf macros to check for network libraries (-lsocket, -lnsl, etc.) when configuring Customs. * configure.in (make_try_customs): Invoke new network libs macro. 1998-07-06 Paul D. Smith * Version 3.76.92 released. * README.customs: Added to the distribution. * configure.in (make_try_customs): Rewrite to require an installed Customs library, rather than looking at the build directory. * Makefile.am (man_MANS): Install make.1. * make.1: Renamed from make.man. * make.texinfo (Bugs): New mailing list address for GNU make bug reports. 1998-07-02 Paul D. Smith * Version 3.76.91 released. * default.c: Added default rule for new-style RCS master file storage; ``% :: RCS/%''. Added default rules for DOS-style C++ files with suffix ".cpp". They use the new LINK.cpp and COMPILE.cpp macros, which are set by default to be equal to LINK.cc and COMPILE.cc. 1998-06-19 Eli Zaretskii * job.c (start_job_command): Reset execute_by_shell after an empty command was skipped. 1998-06-09 Paul D. Smith * main.c (main): Keep track of the temporary filename created when reading a makefile from stdin (-f-) and attempt to remove it as soon as we know we're not going to re-exec. If we are, add it to the exec'd make's cmd line with "-o" so the exec'd make doesn't try to rebuild it. We still have a hole: if make re-execs then the temporary file will never be removed. To fix this we'd need a brand new option that meant "really delete this". * AUTHORS, getopt.c, getopt1.c, getopt.h, main.c (print_version): Updated mailing addresses. 1998-06-08 Paul D. Smith * main.c (main): Andreas Luik points out that the check for makefile :: rules with commands but no dependencies causing a loop terminates incorrectly. * maintMakefile: Make a template for README.DOS to update version numbers. 1998-05-30 Andreas Schwab * remake.c (update_file_1): Don't free the memory for the dependency structure when dropping a circular dependency. 1998-05-30 Eli Zaretskii * dir.c (file_exists_p, file_impossible_p, file_impossible) [__MSDOS__, WINDOWS32]: Retain trailing slash in "d:/", and make dirname of "d:foo" be "d:". 1998-05-26 Andreas Schwab * read.c (read_makefile): Avoid running past EOS when scanning file name after `include'. 1998-05-26 Andreas Schwab * make.texinfo (Flavors): Correct description of conditional assignment, which is not equivalent to ifndef. (Setting): Likewise. 1998-05-24 Paul D. Smith * arscan.c (ar_name_equal): strncmp() might be implemented as a macro, so don't put preprocessor conditions inside the arguments list. 1998-05-23 Eli Zaretskii * read.c (read_makefile) [__MSDOS__, WINDOWS32]: Skip colons in drive specs when parsing targets, target-specific variables and static pattern rules. A colon can only be part of drive spec if it is after the first letter in a token. 1998-05-22 Eli Zaretskii * remake.c (f_mtime) [__MSDOS__]: Allow up to 3 sec of skew before yelling bloody murder. * dosbuild.bat: Use -DINCLUDEDIR= and -DLIBDIR= where appropriate. * read.c (parse_file_seq): Combine the special file-handling code for WINDOWS32 and __MSDOS__ into a single snippet. (get_next_mword) [__MSDOS__, WINDOWS32]: Allow a word to include a colon as part of a drive spec. * job.c (batch_mode_shell) [__MSDOS__]: Declare. 1998-05-20 Paul D. Smith * Version 3.76.90 released. 1998-05-19 Paul D. Smith * make.texinfo (Make Errors): Added a new appendix describing common errors make might generate and how to resolve them (or at least more information on what they mean). * maintMakefile (NMAKEFILES): Use the new automake 1.3 feature to create a dependency file to construct Makefile.DOS, SMakefile, and NMakefile. (.dep_segment): Generate the dependency fragment file. 1998-05-14 Paul D. Smith * make.man: Minor changes. 1998-05-13 Paul D. Smith * function.c (pattern_matches,expand_function): Change variables and types named "word" to something else, to avoid compilation problems on Cray C90 Unicos. * variable.h: Modify the function prototype. 1998-05-11 Rob Tulloh * job.c (construct_command_argv_internal) [WINDOWS32]: Turn off echo when using a batch file, and make sure the command ends in a newline. 1998-05-03 Paul D. Smith * configure.in (make_try_customs): Add some customs flags if the user configures custom support. * job.c, remote-cstms.c: Merge in changes for custom library. * remote-stub.c: Add option to stub start_remote_job_p(). 1998-05-01 Paul D. Smith * remake.c (f_mtime): Install VPATH+ handling for archives; use the hname field instead of the name field, and rehash when appropriate. 1998-04-30 Paul D. Smith * rule.c (print_rule_data_base): Print out any pattern-specific variable values into the rules database. * variable.c (print_variable_set): Make this variable extern, to be called by print_rule_data_base() for pattern-specific variables. * make.texinfo (Pattern-specific): Document pattern-specific variables. 1998-04-29 Paul D. Smith * expand.c (variable_expand_for_file): Make static; its only called internally. Look up this target in the list of pattern-specific variables and insert the variable set into the queue to be searched. * filedef.h (struct file): Add a new field to hold the previously-found pattern-specific variable reference. Add a new flag to remember whether we already searched for this file. * rule.h (struct pattern_var): New structure for storing pattern-specific variable values. Define new function prototypes. * rule.c: New variables pattern_vars and last_pattern_var for storage and handling of pattern-specific variable values. (create_pattern_var): Create a new pattern-specific variable value structure. (lookup_pattern_var): Try to match a target to one of the pattern-specific variable values. 1998-04-22 Paul D. Smith * make.texinfo (Target-specific): Document target-specific variables. 1998-04-21 Paul D. Smith * variable.c (define_variable_in_set): Made globally visible. (lookup_variable_in_set): New function: like lookup_variable but look only in a specific variable set. (target_environment): Use lookup_variable_in_set() to get the correct export rules for a target-specific variable. (create_new_variable_set): Create a new variable set, and just return it without installing it anywhere. (push_new_variable_scope): Reimplement in terms of create_new_variable_set. * read.c (record_target_var): Like record_files, but instead of files create a target-specific variable value for each of the listed targets. Invoked from read_makefile() when the target line turns out to be a target-specific variable assignment. 1998-04-19 Paul D. Smith * read.c (read_makefile): Rewrite the entire target parsing section to implement target-specific variables. In particular, we cannot expand the entire line as soon as it's read in, since we may want to evaluate parts of it with different variable contexts active. Instead, start expanding from the beginning until we find the `:' (or `::'), then determine what kind of line this is and continue appropriately. * read.c (get_next_mword): New function to parse a makefile line by "words", considering an entire variable or function as one word. Return the type read in, along with its starting position and length. (enum make_word_type): The types of words that are recognized by get_next_mword(). * variable.h (struct variable): Add a flag to specify a per-target variable. * expand.c: Make variable_buffer global. We need this during the new parsing of the makefile. (variable_expand_string): New function. Like variable_expand(), but start at a specific point in the buffer, not the beginning. (variable_expand): Rewrite to simply call variable_expand_string(). 1998-04-13 Paul D. Smith * remake.c (update_goal_chain): Allow the rebuilding makefiles step to use parallel jobs. Not sure why this was disabled: hopefully we won't find out :-/. 1998-04-11 Paul D. Smith * main.c (main): Set the CURDIR makefile variable. * make.texinfo (Recursion): Document it. 1998-03-17 Paul D. Smith * misc.c (makefile_fatal): If FILE is nil, invoke plain fatal(). * variable.c (try_variable_definition): Use new feature. 1998-03-10 Paul D. Smith * main.c (main): Don't pass included, rebuilt makefiles to re-exec'd makes with -o. Reopens a possible loop, but it caused too many problems. 1998-03-02 Paul D. Smith * variable.c (try_variable_definition): Implement ?=. * make.texinfo (Setting): Document it. 1998-02-28 Eli Zaretskii * job.c (start_job_command): Reset execute_by_shell after an empty command, like ":", has been seen. Tue Oct 07 15:00:00 1997 Phil Brooks * make.h [WINDOWS32]: make case sensitivity configurable * dir.c [WINDOWS32]: make case sensitivity configurable * README.W32: Document case sensitivity * config.ami: Share case warping code with Windows Mon Oct 6 18:48:45 CDT 1997 Rob Tulloh * w32/subproc/sub_proc.c: Added support for MKS toolkit shell (turn on HAVE_MKS_SHELL). * read.c [WINDOWS32]: Fixed a problem with multiple target rules reported by Gilbert Catipon (gcatipon@tibco.com). If multiple path tokens in a rule did not have drive letters, make would incorrectly concatenate the 2 tokens together. * main.c/variable.c [WINDOWS32]: changed SHELL detection code to follow what MSDOS did. In addition to watching for SHELL variable updates, make's main will attempt to default the value of SHELL before and after makefiles are parsed. * job.c/job.h [WINDOWS32]: The latest changes made to enable use of the GNUWIN32 shell from make could cause make to fail due to a concurrency condition between parent and child processes. Make now creates a batch file per job instead of trying to reuse the same singleton batch file. * job.c/job.h/function.c/config.h.W32 [WINDOWS32]: Renamed macro from HAVE_CYGNUS_GNUWIN32_TOOLS to BATCH_MODE_ONLY_SHELL. Reworked logic to reduce complexity. WINDOWS32 now uses the unixy_shell variable to detect Bourne-shell compatible environments. There is also a batch_mode_shell variable that determines whether not command lines should be executed via script files. A WINDOWS32 system with no sh.exe installed would have unixy_shell set to FALSE and batch_mode_shell set to TRUE. If you have a unixy shell that does not behave well when invoking things via 'sh -c xxx', you may want to turn on BATCH_MODE_ONLY_SHELL and see if things improve. * NMakefile: Added /D DEBUG to debug build flags so that unhandled exceptions could be debugged. Mon Oct 6 00:04:25 1997 Rob Tulloh * main.c [WINDOWS32]: The function define_variable() does not handle NULL. Test before calling it to set Path. * main.c [WINDOWS32]: Search Path again after makefiles have been parsed to detect sh.exe. * job.c [WINDOWS32]: Added support for Cygnus GNU WIN32 tools. To use, turn on HAVE_CYGNUS_GNUWIN32_TOOLS in config.h.W32. * config.h.W32: Added HAVE_CYGNUS_GNUWIN32_TOOLS macro. Sun Oct 5 22:43:59 1997 John W. Eaton * glob/glob.c (glob_in_dir) [VMS]: Globbing shouldn't be case-sensitive. * job.c (child_execute_job) [VMS]: Use a VMS .com file if the command contains a newline (e.g. from a define/enddef block). * vmsify.c (vmsify): Return relative pathnames wherever possible. * vmsify.c (vmsify): An input string like "../.." returns "[--]". Wed Oct 1 15:45:09 1997 Rob Tulloh * NMakefile: Changed nmake to $(MAKE). * subproc.bat: Take the make command name from the command line. If no command name was given, default to nmake. * job.c [MSDOS, WINDOWS32]: Fix memory stomp: temporary file names are now always created in heap memory. * w32/subproc/sub_proc.c: New implementation of make_command_line() which is more compatible with different Bourne shell implementations. Deleted the now obsolete fix_command_line() function. * main.c [WINDOWS32]: Any arbitrary spelling of Path can be detected. Make will ensure that the special spelling `Path' is inserted into the environment when the path variable is propagated within itself and to make's children. * main.c [WINDOWS32]: Detection of sh.exe was occurring too soon. The 2nd check for the existence of sh.exe must come after the call to read_all_makefiles(). Fri Sep 26 01:14:18 1997 * makefile.com [VMS]: Fixed definition of sys. * readme.vms: Comments on what's changed lately. Fri Sep 26 01:14:18 1997 John W. Eaton * read.c (read_all_makefiles): Allow make to find files named "MAKEFILE" with no extension on VMS. * file.c (lookup_file): Lowercase filenames on VMS. 1997-09-29 Paul D. Smith * read.c (read_makefile): Reworked target detection again; the old version had an obscure quirk. Fri Sep 19 09:20:49 1997 Paul D. Smith * Version 3.76.1 released. * Makefile.am: Add loadavg files to clean rules. * configure.in (AC_OUTPUT): Remove stamp-config; no longer needed. * Makefile.ami (distclean): Ditto. * SMakefile (distclean): Ditto. * main.c (main): Arg count should be int, not char! Major braino. Tue Sep 16 10:18:22 1997 Paul D. Smith * Version 3.76 released. Tue Sep 2 10:07:39 1997 Paul D. Smith * function.c (expand_function): When processing $(shell...) translate a CRLF (\r\n) sequence as well as a newline (\n) to a space. Also remove an ending \r\n sequence. * make.texinfo (Shell Function): Document it. Fri Aug 29 12:59:06 1997 Rob Tulloh * w32/pathstuff.c (convert_Path_to_windows32): Fix problem where paths which contain single character entries like `.' are not handled correctly. * README.W32: Document path handling issues on Windows systems. Fri Aug 29 02:01:27 1997 Paul D. Smith * Version 3.75.93. Thu Aug 28 19:39:06 1997 Rob Tulloh * job.c (exec_command) [WINDOWS32]: If exec_command() is invoked from main() to re-exec make, the call to execvp() would incorrectly return control to parent shell before the exec'ed command could run to completion. I believe this is a feature of the way that execvp() is implemented on top of WINDOWS32 APIs. To alleviate the problem, use the supplied process launch function in the sub_proc library and suspend the parent process until the child process has run. When the child exits, exit the parent make with the exit code of the child make. Thu Aug 28 17:04:47 1997 Paul D. Smith * Makefile.DOS.template (distdir): Fix a line that got wrapped in email. * Makefile.am (loadavg): Give the necessary cmdline options when linking loadavg. * configure.in: Check for pstat_getdynamic for getloadvg on HP. * job.c (start_job_command) [VMS, _AMIGA]: Don't perform empty command optimization on these systems; it doesn't make sense. Wed Aug 27 17:09:32 1997 Paul D. Smith * Version 3.75.92 Tue Aug 26 11:59:15 1997 Paul D. Smith * main.c (print_version): Add '97 to copyright years. * read.c (do_define): Check the length of the array before looking at a particular offset. * job.c (construct_command_argv_internal): Examine the last byte of the previous arg, not the byte after that. Sat Aug 23 1997 Eli Zaretskii * Makefile.DOS.template: New file (converted to Makefile.DOS in the distribution). * configure.bat: Rewrite to use Makefile.DOS instead of editing Makefile.in. Add support for building from outside of the source directory. Fail if the environment block is too small. * configh.dos: Use . * README.DOS: Update instructions. Fri Aug 22 1997 Eli Zaretskii * job.c (start_job_command) [__MSDOS__]: Don't test for "/bin/sh" literally, use value of unixy_shell instead. * filedef.h (NEW_MTIME): Use 1 less than maximum possible value if time_t is unsigned. Sat Aug 16 00:56:15 1997 John W. Eaton * vmsify.c (vmsify, case 11): After translating `..' elements, set nstate to N_OPEN if there are still more elements to process. (vmsify, case 2): After translating `foo/bar' up to the slash, set nstate to N_OPEN, not N_DOT. Fri Aug 8 15:18:09 1997 John W. Eaton * dir.c (vmsstat_dir): Leave name unmodified on exit. * make.h (PATH_SEPARATOR_CHAR): Set to comma for VMS. * vpath.c: Fix comments to refer to path separator, not colon. (selective_vpath_search): Avoid Unixy slash handling for VMS. Thu Aug 7 22:24:03 1997 John W. Eaton * ar.c [VMS]: Don't declare ar_member_touch. Delete VMS version of ar_member_date. Enable non-VMS versions of ar_member_date and ar_member_date_1 for VMS too. * arscan.c (VMS_get_member_info): New function. (ar_scan): Provide version for VMS systems. (ar_name_equal): Simply compare name and mem on VMS systems. Don't define ar_member_pos or ar_member_touch on VMS systems. * config.h-vms (pid_t, uid_t): Don't define. * remake.c: Delete declaration of vms_stat. (name_mtime): Don't call vms_stat. (f_mtime) [VMS]: Funky time value manipulation no longer necessary. * file.c (print_file): [VMS] Use ctime, not cvt_time. * make.h [VMS]: Don't define POSIX. * makefile.com (filelist): Include ar and arscan. Also include them in the link commands. Don't define NO_ARCHIVES in cc command. * makefile.vms (ARCHIVES, ARCHIVES_SRC): Uncomment. (defines): Delete NO_ARCHIVES from list. * remake.c (f_mtime): Only check to see if intermediate file is out of date if it also exists (i.e., mtime != (time_t) -1). * vmsdir.h (u_long, u_short): Skip typedefs if using DEC C. Fri Jun 20 23:02:07 1997 Rob Tulloh * w32/subproc/sub_proc.c: Get W32 sub_proc to handle shebang (#!/bin/sh) in script files correctly. Fixed a couple of memory leaks. Fixed search order in find_file() (w32/subproc/sub_proc.c) so that files with extensions are preferred over files without extensions. Added search for files with .cmd extension too. * w32/subproc/misc.c (arr2envblk): Fixed memory leak. Mon Aug 18 09:41:08 1997 Paul D. Smith * Version 3.75.91 Fri Aug 15 13:50:54 1997 Paul D. Smith * read.c (do_define): Remember to count the newline after the endef. Thu Aug 14 23:14:37 1997 Paul D. Smith * many: Rewrote builds to use Automake 1.2. * AUTHORS: New file. * maintMakefile: Contains maintainer-only make snippets. * GNUmakefile: This now only runs the initial auto* tools. * COPYING,texinfo.tex,mkinstalldirs,install-sh: Removed (obtained automatically by automake). * compatMakefile: Removed (not needed anymore). * README,build.sh.in: Removed (built from templates). * config.h.in,Makefile.in: Removed (built by tools). Wed Aug 13 02:22:08 1997 Paul D. Smith * make.texinfo: Updates for DOS/Windows information (Eli Zaretskii) * README,README.DOS: Ditto. * remake.c (update_file_1,f_mtime): Fix GPATH handling. * vpath.c (gpath_search): Ditto. * file.c (rename_file): New function: rehash, but also rename to the hashname. * filedef.h: Declare it. * variable.c (merge_variable_set_lists): Remove free() of variable set; since various files can share variable sets we don't want to free them here. Tue Aug 12 10:51:54 1997 Paul D. Smith * configure.in: Require autoconf 2.12 * make.texinfo: Replace all "cd subdir; $(MAKE)" examples with a more stylistically correct "cd subdir && $(MAKE)". * main.c: Global variable `clock_skew_detected' defined. (main): Print final warning if it's set. * make.h: Declare it. * remake.c (f_mtime): Test and set it. * job.c (start_job_command): Add special optimizations for "do-nothing" rules, containing just the shell no-op ":". This is useful for timestamp files and can make a real difference if you have a lot of them (requested by Fergus Henderson ). * configure.in,Makefile.in: Rewrote to use the new autoconf program_transform_name macro. * function.c (function_strip): Strip newlines as well as spaces and TABs. Fri Jun 6 23:41:04 1997 Rob Tulloh * remake.c (f_mtime): Datestamps on FAT-based files are rounded to even seconds when stored, so if the date check fails on WINDOWS32 systems, see if this "off-by-one" error is the problem. * General: If your TZ environment variable is not set correctly then all your timestamps will be off by hours. So, set it! Mon Apr 7 02:06:22 1997 Paul D. Smith * Version 3.75.1 * compatMakefile (objs): Define & use the $(GLOB) variable so that it's removed correctly from build.sh.in when it's built. * configure.in: On Solaris we can use the kstat_*() functions to get load averages without needing special permissions. Add a check for -lkstat to see if we have it. * getloadavg.c (getloadavg): Use HAVE_LIBKSTAT instead of SUN5 as the test to enable kstat_open(), etc. processing. Fri Apr 4 20:21:18 1997 Eli Zaretskii * : Fixes to work in the DJGPP DOS environment. Mon Mar 31 02:42:52 1997 Paul D. Smith * function.c (expand_function): Added new function $(wordlist). * make.texinfo (Filename Functions): Document $(wordlist) function. * vpath.c (build_vpath_lists): Construct the GPATH variable information in the same manner we used to construct VPATH. (gpath_search): New function to search GPATH. * make.h: Declare the new function. * remake.c (update_file_1): Call it, and keep VPATH if it's found. * make.texinfo (Search Algorithm): Document GPATH variable. Sun Mar 30 20:57:16 1997 Paul D. Smith * main.c (handle_non_switch_argument): Defined the MAKECMDGOALS variable to contain the user options passed in on the cmd line. * make.texinfo (Goals): Document MAKECMDGOALS variable. * remake.c (f_mtime): Print a warning if we detect a clock skew error, rather than failing. * main.c (main): If we rebuild any makefiles and need to re-exec, add "-o" options for each makefile rebuilt to avoid infinite looping. Fri Mar 28 15:26:05 1997 Paul D. Smith * job.c (construct_command_argv_internal): Track whether the last arg in the cmd string was empty or not (Roland). (construct_command_argv_internal): If the shell line is empty, don't do anything (Roland). * glob/glob.h,glob/glob.c,glob/fnmatch.c,glob/fnmatch.h: Install the latest changes from the GLIBC version of glob (Ulrich Drepper). * getloadavg.c,make-stds.texi: New version (Roland). * (ALL): Changed WIN32 to W32 or WINDOWS32 (RMS). Mon Mar 24 15:33:34 1997 Rob Tulloh * README.W32: Describe preliminary FAT support. * build_w32.bat: Use a variable for the final exe name. * dir.c (find_directory): W32: Find the filesystem type. (dir_contents_file_exists_p): W32: for FAT filesystems, always rehash since FAT doesn't change directory mtime on change. * main.c (handle_runtime_exceptions): W32: Add an UnhandledExceptionFilter so that when make bombs due to ^C or a bug, it won't cause a GUI requestor to pop up unless debug is turned on. (main): Call it. Mon Mar 24 00:57:34 1997 Paul D. Smith * configure.in, config.h.in, config.ami, config.h-vms, config.h.w32: Check for memmove() function. * make.h (bcopy): If memmove() available, define bcopy() to use it. Otherwise just use bcopy(). Don't use memcpy(); it's not guaranteed to handle overlapping moves. * read.c (read_makefile): Fix some uninitialized memory reads (reported by Purify). * job.c (construct_command_argv_internal): Use bcopy() not strcpy(); strcpy() isn't guaranteed to handle overlapping moves. * Makefile.in: Change install-info option ``--infodir'' to ``--info-dir'' for use with new texinfo. * function.c (expand_function): $(basename) and $(suffix) should only search for suffixes as far back as the last directory (e.g., only the final filename in the path). Sun Mar 23 00:13:05 1997 Paul D. Smith * make.texinfo: Add @dircategory/@direntry information. (Top): Remove previous reference to (dir) (from RMS). (Static Usage): Add "all:" rule to example. (Automatic Dependencies): fix .d file creation example. * Install VPATH+ patch: * filedef.h (struct file): Add in hname field to store the hashed filename, and a flag to remember if we're using the vpath filename or not. Renamed a few functions for more clarity. * file.c (lookup_file,enter_file,file_hash_enter): Store filenames in the hash table based on their "hash name". We can change this while keeping the original target in "name". (rehash_file): Renamed from "rename_file" to be more accurate. Changes the hash name, but not the target name. * remake.c (update_file_1): Modify -d output for more detailed VPATH info. If we don't need to rebuild, use the VPATH name. (f_mtime): Don't search for vpath if we're ignoring it. Call renamed function rehash_file. Call name_mtime instead of file_mtime, to avoid infinite recursion since the file wasn't actually renamed. * implicit.c (pattern_search): if we find an implicit file in VPATH, save the original name not the VPATH name. * make.texinfo (Directory Search): Add a section on the new VPATH functionality. Sun Dec 1 18:36:04 1996 Andreas Schwab * dir.c (file_exists_p, file_impossible, file_impossible_p): If dirname is empty replace it by the name of the root directory. Note that this doesn't work (yet) for W32, Amiga, or VMS. Tue Oct 08 13:57:03 1996 Rob Tulloh * main.c (main): W32 bug fix for PATH vars. Tue Sep 17 1996 Paul Eggert * filedef.h (NEW_MTIME): Don't assume that time_t is a signed 32-bit quantity. * make.h: (CHAR_BIT, INTEGER_TYPE_SIGNED, INTEGER_TYPE_MAXIMUM, INTEGER_TYPE_MINIMUM): New macros. Tue Aug 27 01:06:34 1996 Roland McGrath * Version 3.75 released. * main.c (print_version): Print out bug-reporting address. Mon Aug 26 19:55:47 1996 Roland McGrath * main.c (print_data_base): Don't declare ctime; headers do it for us already. Sun Jul 28 15:37:09 1996 Rob Tulloh (tulloh@tivoli.com) * w32/pathstuff.c: Turned convert_vpath_to_w32() into a real function. This was done so that VPATH could contain white space separated pathnames. Please note that directory paths (in VPATH/vpath context) containing white space are not supported (just as they are not under Unix). See README.W32 for suggestions. * w32/include/pathstuff.h: Added prototype for the new function convert_vpath_to_w32. Deleted macro for same. * README.W32: Added some notes about why I chose not to try and support pathnames which contain white space and some workaround suggestions. Thu Jul 25 19:53:31 1996 Roland McGrath * GNUmakefile (mkdep-nolib): Use -MM option unconditionally. * Version 3.74.7. * main.c (define_makeflags): Back up P to point at null terminator when killing final space and dash before setting MFLAGS. From Robert Hoehne : * dir.c [__MSDOS__ && DJGPP > 1]: Include and defin `__opendir_flags' initialized to 0. (dosify) [__MSDOS__ && DJGPP > 1]: Return name unchanged if _USE_LFN. (find_directory) [__MSDOS__ && DJGPP > 1]: If _USE_LGN, set __opendir_flags to __OPENDIR_PRESERVE_CASE. * vmsfunctions.c (vms_stat): `sys$dassgn (DevChan);' added by kkaempf. * GNUmakefile (w32files): Add NMakefile. * NMakefile (LDFLAGS_debug): Value fixed by tulloh. Sat Jul 20 12:32:10 1996 Klaus Kämpf (kkaempf@progis.de) * remake.c (f_mtime) [VMS]: Add missing `if' conditional for future modtime check. * config.h-vms, makefile.vms, readme.vms, vmsify.c: Update address. Sat Jul 20 05:29:43 1996 Roland McGrath * configure.in: Require autoconf 2.10 or later. Fri Jul 19 16:57:27 1996 Roland McGrath * Version 3.74.6. * GNUmakefile (w32files): New variable. (distfiles): Add it. * w32: Updated by Rob Tulloh. * makefile.vms (LOADLIBES): Fix typo. Sun Jul 14 12:59:27 1996 Roland McGrath * job.c (construct_command_argv_internal): Fix up #else, #endifs. * configh.dos: Define HAVE_DIRENT_H instead of DIRENT. * remake.c (f_mtime): Don't compare MTIME to NOW if MTIME == -1. * Version 3.74.5. * main.c (main): Exit with status 2 when update_goal_chain returns 2. Sat Jun 22 14:56:05 1996 Roland McGrath * configure.in: Don't check for _sys_siglist. * make.h [HAVE__SYS_SIGLIST]: Don't test this; just punt if there is no strsignal or sys_siglist. * read.c (conditional_line): Strip ws in `ifeq (a , b)' so it is the same as `ifeq (a, b)'. * job.c (reap_children): Don't call die if handling_fatal_signal. * file.c (file_hash_enter): Allow renaming :: to : when latter is non-target, or : to :: when former is non-target. * job.c (start_job_command): Call block_sigs. (block_sigs): New function, broken out of start_job_command. (reap_children): Block fatal signals around removing dead child from chain and adjusting job_slots_used. * job.h: Declare block_sigs. * remote-stub.c (remote_setup, remote_cleanup): New (empty) functions. * main.c (main): Call remote_setup. (die): Call remote_cleanup. * job.c (reap_children): Quiescent value of shell_function_pid is zero, not -1. * main.c (print_version): Add 96 to copyright years. Sat Jun 15 20:30:01 1996 Andreas Schwab * read.c (find_char_unquote): Avoid calling strlen on every call just to throw away the value most of the time. Sun Jun 2 12:24:01 1996 Roland McGrath * main.c (decode_env_switches): Prepend '-' to ARGV[1] if it contains no '=', regardless of ARGC. (define_makeflags): Elide leading '-' from MAKEFLAGS value if first word is short option, regardless of WORDS. Wed May 22 17:24:51 1996 Roland McGrath * makefile.vms: Set LOADLIBES. * makefile.com (link_using_library): Fix typo. Wed May 15 17:37:26 1996 Roland McGrath * dir.c (print_dir_data_base): Use %ld dev and ino and cast them to long. Wed May 15 10:14:14 CDT 1996 Rob Tulloh * dir.c: W32 does not support inode. For now, fully qualified pathname along with st_mtime will be keys for files. Fixed problem where vpath can be confused when files are added to a directory after the directory has already been read in. The code now attempts to reread the directory if it discovers that the datestamp on the directory has changed since it was cached by make. This problem only seems to occur on W32 right now so it is lumped under port #ifdef WINDOWS32. * function.c: W32: call subproc library (CreateProcess()) instead of fork/exec. * job.c: W32: Added the code to do fork/exec/waitpid style processing on W32 systems via calls to subproc library. * main.c: W32: Several things added here. First, there is code for dealing with PATH and SHELL defaults. Make tries to figure out if the user has %PATH% set in the environment and sets it to %Path% if it is not set already. Make also looks to see if sh.exe is anywhere to be found. Code path through job.c will change based on existence of a working Bourne shell. The checking for default shell is done twice: once before makefiles are read in and again after. Fall back to MSDOS style execution mode if no sh.exe is found. Also added some debug support that allows user to pause make with -D switch and attach a debugger. This is especially useful for debugging recursive calls to make where problems appear only in the sub-make. * make.h: W32: A few macros and header files for W32 support. * misc.c: W32: Added a function end_of_token_w32() to assist in parsing code in read.c. * read.c: W32: Fixes similar to MSDOS which allow colon to appear in filenames. Use of colon in filenames would otherwise confuse make. * remake.c: W32: Added include of io.h to eliminate compiler warnings. Added some code to default LIBDIR if it is not set on W32. * variable.c: W32: Added support for detecting Path/PATH and converting them to semicolon separated lists for make's internal use. New function sync_Path_environment() which is called in job.c and function.c before creating a new process. Caller must set Path in environment since we don't have fork() to do this for us. * vpath.c: W32: Added detection for filenames containing forward or backward slashes. * NMakefile: W32: Visual C compatible makefile for use with nmake. Use this to build GNU make the first time on Windows NT or Windows 95. * README.W32: W32: Contains some helpful notes. * build_w32.bat: W32: If you don't like nmake, use this the first time you build GNU make on Windows NT or Windows 95. * config.h.W32: W32 version of config.h * subproc.bat: W32: A bat file used to build the subproc library from the top-level NMakefile. Needed because WIndows 95 (nmake) doesn't allow you to cd in a make rule. * w32/include/dirent.h * w32/compat/dirent.c: W32: opendir, readdir, closedir, etc. * w32/include/pathstuff.h: W32: used by files needed functions defined in pathstuff.c (prototypes). * w32/include/sub_proc.h: W32: prototypes for subproc.lib functions. * w32/include/w32err.h: W32: prototypes for w32err.c. * w32/pathstuff.c: W32: File and Path/Path conversion functions. * w32/subproc/build.bat: W32: build script for subproc library if you don't wish to use nmake. * w32/subproc/NMakefile: W32: Visual C compatible makefile for use with nmake. Used to build subproc library. * w32/subproc/misc.c: W32: subproc library support code * w32/subproc/proc.h: W32: subproc library support code * w32/subproc/sub_proc.c: W32: subproc library source code * w32/subproc/w32err.c: W32: subproc library support code Mon May 13 14:37:42 1996 Roland McGrath * Version 3.74.4. * GNUmakefile (vmsfiles): Fix typo. * GNUmakefile (amigafiles): Add amiga.h. Sun May 12 19:19:43 1996 Aaron Digulla * dir.c: New function: amigafy() to fold filenames Changes HASH() to HASHI() to fold filenames on Amiga. Stringcompares use strieq() instead of streq() The current directory on Amiga is "" instead of "." * file.c: Likewise. * amiga.c: New function wildcard_expansion(). Allows to use Amiga wildcards with $(wildcard ) * amiga.h: New file. Prototypes for amiga.c * function.c: Use special function wildcard_expansion() for $(wildcard ) to allow Amiga wildcards The current directory on Amiga is "" instead of "." * job.c: No Pipes on Amiga, too (load_too_high) Neither on Amiga ENV variable on Amiga are in a special directory and are not passed as third argument to main(). * job.h: No envp on Amiga * make.h: Added HASHI(). This is the same as HASH() but converts it's second parameter to lowercase on Amiga to fold filenames. * main.c: (main), variable.c Changed handling of ENV-vars. Make stores now the names of the variables only and reads their contents when they are accessed to reflect that these variables are really global (ie. they CAN change WHILE make runs !) This handling is made in lookup_variable() * Makefile.ami: renamed file.h to filedep.h Updated dependencies * read.c: "find_semicolon" is declared as static but never defined. No difference between Makefile and makefile on Amiga; added SMakefile to *default_makefiles[]. (read_makefile) SAS/C want's two_colon and pattern_percent be set before use. The current directory on Amiga is "" instead of "." Strange #endif moved. * README.Amiga: updated feature list * SMakefile: Updated dependencies * variable.c: Handling of ENV variable happens inside lookup_variable() Sat May 11 17:58:32 1996 Roland McGrath * variable.c (try_variable_definition): Count parens in lhs variable refs to avoid seeing =/:=/+= inside a ref. Thu May 9 13:54:49 1996 Roland McGrath * commands.c (fatal_error_signal) [SIGQUIT]: Make SIGQUIT check conditional. * main.c (main): Use unsigned for fread return. * read.c (parse_file_seq): Use `int' for char arg to avoid widening conflict issues. * dep.h: Fix prototype. * function.c (expand_function) [_AMIGA]: Fix some typos. (patsubst_expand): Make len vars unsigned. * GNUmakefile (globfiles): Add AmigaDOS support files. (distfiles): Add $(amigafiles). (amigafiles): New variable. Thu Nov 7 10:18:16 1995 Aaron Digulla * Added Amiga support in commands.c, dir.c, function.c, job.c, main.c, make.h, read.c, remake.c * commands.c: Amiga has neither SIGHUP nor SIGQUIT * dir.c: Amiga has filenames with Upper- and Lowercase, but "FileName" is the same as "filename". Added strieq() which is use to compare filenames. This is like streq() on all other systems. Also there is no such thing as "." under AmigaDOS. * function.c: On Amiga, the environment is not passed as envp, there are no pipes and Amiga can't fork. Use my own function to create a new child. * job.c: default_shell is "" (The system automatically chooses a shell for me). Have to use the same workaround as MSDOS for running batch commands. Added HAVE_SYS_PARAM_H. NOFILE isn't known on Amiga. Cloned code to run children from MSDOS. Own version of sh_chars[] and sh_cmds[]. No dup2() or dup() on Amiga. * main.c: Force stack to 20000 bytes. Read environment from ENV: device. On Amiga, exec_command() does return, so I exit() afterwards. * make.h: Added strieq() to compare filenames. * read.c: Amiga needs special extension to have passwd. Only one include-dir. "Makefile" and "makefile" are the same. Added "SMakefile". Added special code to handle device names (xxx:) and "./" in rules. * remake.c: Only one lib-dir. Amiga link-libs are named "%s.lib" instead of "lib%s.a". * main.c, rule.c, variable.c: Avoid floats at all costs. * vpath.c: Get rid of as many alloca()s as possible. Thu May 9 13:20:43 1996 Roland McGrath * read.c (read_makefile): Grok `sinclude' as alias for `-include'. Wed Mar 20 09:52:27 1996 Roland McGrath * GNUmakefile (vmsfiles): New variable. (distfiles): Include $(vmsfiles). Tue Mar 19 20:21:34 1996 Roland McGrath Merged VMS port from Klaus Kaempf . * make.h (PARAMS): New macro. * config.h-vms: New file. * makefile.com: New file. * makefile.vms: New file. * readme.vms: New file. * vmsdir.h: New file. * vmsfunctions.c: New file. * vmsify.c: New file. * file.h: Renamed to filedef.h to avoid conflict with VMS system hdr. * ar.c: Added prototypes and changes for VMS. * commands.c: Likewise. * commands.h: Likewise. * default.c: Likewise. * dep.h: Likewise. * dir.c: Likewise. * expand.c: Likewise. * file.c: Likewise. * function.c: Likewise. * implicit.c: Likewise. * job.c: Likewise. * job.h: Likewise. * main.c: Likewise. * make.h: Likewise. * misc.c: Likewise. * read.c: Likewise. * remake.c: Likewise. * remote-stub.c: Likewise. * rule.c: Likewise. * rule.h: Likewise. * variable.c: Likewise. * variable.h: Likewise. * vpath.c: Likewise. * compatMakefile (srcs): Rename file.h to filedef.h. Sat Aug 19 23:11:00 1995 Richard Stallman * remake.c (check_dep): For a secondary file, try implicit and default rules if appropriate. Wed Aug 2 04:29:42 1995 Richard Stallman * remake.c (check_dep): If an intermediate file exists, do consider its actual date. Sun Jul 30 00:49:53 1995 Richard Stallman * file.h (struct file): New field `secondary'. * file.c (snap_deps): Check for .INTERMEDIATE and .SECONDARY. (remove_intermediates): Don't delete .SECONDARY files. Sat Mar 2 16:26:52 1996 Roland McGrath * compatMakefile (srcs): Add getopt.h; prepend $(srcdir)/ to getopt*. Fri Mar 1 12:04:47 1996 Roland McGrath * Version 3.74.3. * remake.c (f_mtime): Move future modtime check before FILE is clobbered by :: loop. * dir.c: Use canonical code from autoconf manual for dirent include. [_D_NAMLEN]: Redefine NAMLEN using this. (dir_contents_file_exists_p): Use NAMLEN macro. (read_dirstream) [_DIRENT_HAVE_D_NAMLEN]: Only set d_namlen #if this. * compatMakefile (objs): Add missing backslash. Wed Feb 28 03:56:20 1996 Roland McGrath * default.c (default_terminal_rules): Remove + prefix from RCS cmds. (default_variables): Put + prefix in $(CHECKOUT,v) value instead. * remake.c (f_mtime): Check for future timestamps; give error and mark file as "failed to update". Fri Jan 12 18:09:36 1996 Roland McGrath * job.c: Don't declare unblock_sigs; job.h already does. Sat Jan 6 16:24:44 1996 Roland McGrath * acconfig.h (HAVE_SYSCONF_OPEN_MAX): #undef removed. * job.c (NGROUPS_MAX): Don't try to define this macro. Fri Dec 22 18:44:44 1995 Roland McGrath * compatMakefile (GETOPT, GETOPT_SRC, GLOB): Variables removed. (objs, srcs): Include their values here instead of references. Thu Dec 14 06:21:29 1995 Roland McGrath * Version 3.74.2. * job.c (reap_children): Call unblock_sigs after start_job_command. Thu Dec 14 07:22:03 1995 Roland McGrath * dir.c (dir_setup_glob): Don't use lstat; glob never calls it anyway. Avoid & before function names to silence bogus sunos4 compiler. * configure.in: Remove check for `sysconf (_SC_OPEN_MAX)'. Tue Dec 12 00:48:42 1995 Roland McGrath * Version 3.74.1. * dir.c (read_dirstream): Fix braino: fill in the buffer when not reallocating it! Mon Dec 11 22:26:15 1995 Roland McGrath * misc.c (collapse_continuations): Fix skipping of trailing \s so it can never dereference before the beginning of the array. * read.c (find_semicolon): Function removed. (read_makefile): Don't use find_semicolon or remove_comments for rule lines. Use find_char_unquote directly and handle quoted comments properly. * default.c: Remove all [M_XENIX] code. * dir.c [HAVE_D_NAMLEN]: Define this for __GNU_LIBRARY__ > 1. (D_NAMLEN): Macro removed. (FAKE_DIR_ENTRY): New macro. (dir_contents_file_exists_p): Test HAVE_D_NAMLEN instead of using D_NAMLEN. (read_dirstream): Return a struct dirent * for new glob interface. (init_dir): Function removed. (dir_setup_glob): New function. * main.c (main): Don't call init_dir. * read.c (multi_glob): Call dir_setup_glob on our glob_t and use GLOB_ALTDIRFUNC flag. * misc.c (safe_stat): Function removed. * read.c, commands.c, remake.c, vpath.c: Use plain stat instead of safe_stat. Sat Nov 25 20:35:18 1995 Roland McGrath * job.c [HAVE_UNION_WAIT]: Include sys/wait.h. * main.c (log_working_directory): Made global. Print entering msg only once. * make.h (log_working_directory): Declare it. * misc.c (message): Take new arg PREFIX. Print "make: " only if nonzero. Call log_working_directory. * remake.c: Pass new arg in `message' calls. * job.c (start_job_command): Pass new arg to `message'; fix inverted test in that call. Tue Nov 21 19:01:12 1995 Roland McGrath * job.c (start_job_command): Use `message' to print the command, and call it with null if the command is silent. * remake.c (touch_file): Use message instead of printf. Tue Oct 10 14:59:30 1995 Roland McGrath * main.c (enter_command_line_file): Barf if NAME is "". Sat Sep 9 06:33:20 1995 Roland McGrath * commands.c (delete_target): Ignore unlink failure if it is ENOENT. Thu Aug 17 15:08:57 1995 Roland McGrath * configure.in: Don't check for getdtablesize. * job.c (getdtablesize): Remove decls and macros. Thu Aug 10 19:10:03 1995 Roland McGrath * main.c (define_makeflags): Omit command line variable definitions from MFLAGS value. * arscan.c (ar_scan) [AIAMAG]: Check for zero MEMBER_OFFSET, indicating a valid, but empty, archive. Mon Aug 7 15:40:03 1995 Roland McGrath * dir.c (file_impossible_p): Correctly reset FILENAME to name within directory before hash search. * job.c (child_error): Do nothing if IGNORED under -s. * job.c (exec_command): Correctly use ARGV[0] for script name when running shell directly. Tue Aug 1 14:39:14 1995 Roland McGrath * job.c (child_execute_job): Close STDIN_FD and STDOUT_FD after dup'ing from them. Don't try to close all excess descriptors; getdtablesize might return a huge value. Any open descriptors in the parent should have FD_CLOEXEC set. (start_job_command): Set FD_CLOEXEC flag on BAD_STDIN descriptor. Tue Jun 20 03:47:15 1995 Roland McGrath * read.c (read_all_makefiles): Properly append default makefiles to the end of the `read_makefiles' chain. Fri May 19 16:36:32 1995 Roland McGrath * Version 3.74 released. Wed May 10 17:43:34 1995 Roland McGrath * Version 3.73.3. Tue May 9 17:15:23 1995 Roland McGrath * compatMakefile ($(infodir)/make.info): Make sure $$dir is set in install-info cmd. Wed May 3 15:56:06 1995 Roland McGrath * file.c (print_file): Grok update_status of 1 for -q. Thu Apr 27 12:39:35 1995 Roland McGrath * Version 3.73.2. Wed Apr 26 17:15:57 1995 Roland McGrath * file.c (remove_intermediates): Fix inverted test to bail under -n for signal case. Bail under -q or -t. Skip files with update_status==-1. * job.c (job_next_command): Skip empty lines. (new_job): Don't test the return of job_next_command. Just let start_waiting_job handle the case of empty commands. Wed Apr 19 03:25:54 1995 Roland McGrath * function.c [__MSDOS__]: Include . From DJ Delorie. * Version 3.73.1. Sat Apr 8 14:53:24 1995 Roland McGrath * remake.c (notice_finished_file): Set FILE->update_status to zero if it's -1. Wed Apr 5 00:20:24 1995 Roland McGrath * Version 3.73 released. Tue Mar 28 13:25:46 1995 Roland McGrath * main.c (main): Fixed braino in assert. * Version 3.72.13. Mon Mar 27 05:29:12 1995 Roland McGrath * main.c: Avoid string in assert expression. Some systems are broken. Fri Mar 24 00:32:32 1995 Roland McGrath * main.c (main): Handle 1 and 2 returns from update_goal_chain makefile run properly. * Version 3.72.12. * main.c (handle_non_switch_argument): New function, broken out of decode_switches. (decode_switches): Set optind to 0 to reinitialize getopt, not to 1. When getopt_long returns EOF, break the loop and handle remaining args with a simple second loop. * remake.c (remake_file): Set update_status to 2 instead of 1 for no rule to make. Mention parent (dependent) in error message. (update_file_1): Handle FILE->update_status == 2 in -d printout. * job.c (start_job_command, reap_children): Set update_status to 2 instead of 1 for failed commands. Tue Mar 21 16:23:38 1995 Roland McGrath * job.c (search_path): Function removed (was already #if 0'd out). * configure.in: Remove AC_TYPE_GETGROUPS; nothing needs it any more. Fri Mar 17 15:57:40 1995 Roland McGrath * configure.bat: Write @CPPFLAGS@ translation. Mon Mar 13 00:45:59 1995 Roland McGrath * read.c (parse_file_seq): Rearranged `l(a b)' -> `l(a) l(b)' loop to not skip the elt immediately preceding `l(...'. Fri Mar 10 13:56:49 1995 Roland McGrath * Version 3.72.11. * read.c (find_char_unquote): Make second arg a string of stop chars instead of a single stop char. Stop when any char in the string is hit. All callers changed. (find_semicolon): Pass stop chars "#;" to one find_char_unquote call, instead of using two calls. If the match is not a ; but a #, return zero. * misc.c: Changed find_char_unquote callers here too. * Version 3.72.10. * read.c (read_makefile, parse_file_seq): Fix typo __MS_DOS__ -> __MSDOS__. * GNUmakefile (globfiles): Add glob/configure.bat. (distfiles): Add configh.dos, configure.bat. Wed Mar 8 13:10:57 1995 Roland McGrath Fixes for MS-DOS from DJ Delorie. * read.c (read_makefile, parse_file_seq) [__MS_DOS__]: Don't see : as separator in "C:\...". * configh.dos (STDC_HEADERS): Define only if undefined. (HAVE_SYS_PARAM_H): Don't define this. (HAVE_STRERROR): Define this. * job.c (construct_command_argv_internal) [__MSDOS__]: Fix typos. * Version 3.72.9. * main.c (decode_switches): Reset optind to 1 instead of 0. Tue Mar 7 17:31:06 1995 Roland McGrath * main.c (decode_switches): If non-option arg is "-", ignore it. Mon Mar 6 23:57:38 1995 Roland McGrath * Version 3.72.8. Wed Feb 22 21:26:36 1995 Roland McGrath * Version 3.72.7. Tue Feb 21 22:10:43 1995 Roland McGrath * main.c (main): Pass missing arg to tmpnam. * configure.in: Check for strsignal. * job.c (child_error): Use strsignal. * main.c (main): Don't call signame_init #ifdef HAVE_STRSIGNAL. * misc.c (strerror): Fix swapped args in sprintf. Mon Feb 13 11:50:08 1995 Roland McGrath * configure.in (CFLAGS, LDFLAGS): Don't set these variables. Fri Feb 10 18:44:12 1995 Roland McGrath * main.c (print_version): Add 95 to copyright years. * Version 3.72.6. * job.c (start_job_command): Remember to call notice_finished_file under -n when not recursing. To do this, consolidate that code under the empty command case and goto there for the -n case. Tue Feb 7 13:36:03 1995 Roland McGrath * make.h [! STDC_HEADERS]: Don't declare qsort. Sun headers declare it int. Mon Feb 6 17:37:01 1995 Roland McGrath * read.c (read_makefile): For bogus line starting with tab, ignore it if blank after removing comments. * main.c: Cast results of `alloca' to `char *'. * expand.c: Likewise. Sun Feb 5 18:35:46 1995 Roland McGrath * Version 3.72.5. * configure.in: Check for mktemp. * main.c (main) [! HAVE_MKTEMP]: Use tmpnam instead of mktemp. * configure.in (make_cv_sysconf_open_max): New check for `sysconf (_SC_OPEN_MAX)'. * acconfig.h: Added #undef HAVE_SYSCONF_OPEN_MAX. * job.c [HAVE_SYSCONF_OPEN_MAX] (getdtablesize): Define as macro using sysconf. Fri Jan 27 04:42:09 1995 Roland McGrath * remake.c (update_file_1): When !MUST_MAKE, don't set FILE->update_status to zero before calling notice_finished_file. (notice_finished_file): Touch only when FILE->update_status is zero. (remake_file): Set FILE->update_status to zero after not calling execute_file_command and deciding to touch instead. Thu Jan 26 01:29:32 1995 Roland McGrath * main.c (debug_signal_handler): New function; toggles debug_flag. (main): Handle SIGUSR1 with that. Mon Jan 16 15:46:56 1995 Roland McGrath * compatMakefile (realclean): Remove Info files. Sun Jan 15 08:23:09 1995 Roland McGrath * Version 3.72.4. * job.c (start_job_command): Save and restore environ around vfork call. (search_path): Function #if 0'd out. (exec_command): Use execvp instead of search_path. * expand.c (variable_expand): Rewrote computed variable name and substitution reference handling to be simpler. First expand the entire text between the parens if it contains any $s, then examine the result of that for subtitution references and do no further expansion while parsing them. * job.c (construct_command_argv_internal): Handle " quoting too, when no backslash, $ or ` characters appear inside the quotes. * configure.in (union wait check): If WEXITSTATUS and WTERMSIG are defined, just use int. Tue Jan 10 06:27:27 1995 Roland McGrath * default.c (default_variables) [__hpux]: Remove special definition of ARFLAGS. Existence of the `f' flag is not consistent across HPUX versions; and one might be using GNU ar anyway. * compatMakefile (clean): Don't remove Info files. * compatMakefile (check): Remove gratuitous target declaration. Sat Jan 7 11:38:23 1995 Roland McGrath * compatMakefile (ETAGS, CTAGS): Don't use -t. * arscan.c (ar_name_equal) [cray]: Subtract 1 like [__hpux]. * main.c (decode_switches): For --help, print usage to stdout. Mon Dec 5 12:42:18 1994 Roland McGrath * Version 3.72.3. * remake.c (update_file_1): Do set_command_state (FILE, cs_not_started) only if old state was deps_running. Mon Nov 28 14:24:03 1994 Roland McGrath * job.c (start_waiting_job): Use set_command_state. * build.template (CPPFLAGS): New variable. (prefix, exec_prefix): Set from @...@. (compilation loop): Pass $CPPFLAGS to compiler. * GNUmakefile (build.sh.in): Make it executable. * GNUmakefile (globfiles): Add configure.in, configure. * Version 3.72.2. * configure.in (AC_OUTPUT): Don't write glob/Makefile. * configure.in (AC_CHECK_SYMBOL): Use AC_DEFINE_UNQUOTED. * configure.in: Don't check for ranlib. Tue Nov 22 22:42:40 1994 Roland McGrath * remake.c (notice_finished_file): Only mark also_make's as updated if really ran cmds. Tue Nov 15 06:32:46 1994 Roland McGrath * configure.in: Put dnls before random whitespace. Sun Nov 13 05:02:25 1994 Roland McGrath * compatMakefile (CPPFLAGS): New variable, set from @CPPFLAGS@. (RANLIB): Variable removed. (prefix, exec_prefix): Set these from @...@. (.c.o): Use $(CPPFLAGS). (glob/libglob.a): Don't pass down variables to sub-make. glob/Makefile should be configured properly by configure. (distclean): Remove config.log and config.cache (autoconf stuff). Mon Nov 7 13:58:06 1994 Roland McGrath * acconfig.h: Add #undef HAVE_UNION_WAIT. * configure.in: Converted to Autoconf v2. * dir.c: Test HAVE_DIRENT_H, HAVE_SYS_DIR_H, HAVE_NDIR_H instead of DIRENT, SYSDIR, NDIR. * build.sh.in (prefix, exec_prefix): Set these from @...@. (CPPFLAGS): New variable, set from @CPPFLAGS@. (compiling loop): Pass $CPPFLAGS before $CFLAGS. * install.sh: File renamed to install-sh. * main.c (define_makeflags): When no flags, set WORDS to zero. Sun Nov 6 18:34:01 1994 Roland McGrath * Version 3.72.1. * main.c (define_makeflags): Terminate properly when FLAGSTRING is empty. Fri Nov 4 16:02:51 1994 Roland McGrath * Version 3.72. Tue Nov 1 01:18:10 1994 Roland McGrath * Version 3.71.5. * job.c (start_job_command): When ARGV is nil, only set update_state and call notice_finished_file if job_next_command returns zero. * job.c (start_job_command): Call notice_finished_file for empty command line. Thu Oct 27 02:02:45 1994 Roland McGrath * file.c (snap_deps): Set COMMANDS_SILENT for .SILENT, not COMMANDS_NOERROR. Wed Oct 26 02:14:10 1994 Roland McGrath * Version 3.71.4. Tue Oct 25 22:49:24 1994 Roland McGrath * file.c (snap_deps): Set command_flags bits in all :: entries. Mon Oct 24 18:47:50 1994 Roland McGrath * make.h (posix_pedantic): Declare it. * main.c (main): Move checks .IGNORE, .SILENT, .POSIX to snap_deps. * file.c (snap_deps): Check .IGNORE, .SILENT, .POSIX here instead of in main. If .IGNORE has deps, OR COMMANDS_NOERROR into their command_flags and don't set -i. Likewise .SILENT. * job.c (start_job_command): In FLAGS initialization, OR in CHILD->file->command_flags. * file.h (struct file): New member `command_flags'. Sun Oct 16 01:01:51 1994 Roland McGrath * main.c (switches): Bump flag values for --no-print-directory and --warn-undefined-variables, so neither is 1 (which indicates a nonoption argument). Sat Oct 15 23:39:48 1994 Roland McGrath * main.c (main): Add missing code in .IGNORE test. Mon Oct 10 04:09:03 1994 Roland McGrath * variable.c (define_automatic_variables): Define +D and +F. Sat Oct 1 04:07:48 1994 Roland McGrath * main.c (main): Define hidden automatic variable with command vars, and MAKEOVERRIDES to a reference to that. (define_makeflags): If posix_pedantic, write a reference to that instead. Thu Sep 29 00:14:26 1994 Roland McGrath * main.c (posix_pedantic): New variable. (main): Set posix_pedantic if .POSIX is a target. Fix .IGNORE and .SILENT checks to require is_target. * commands.c (set_file_variables): Define new automatic variable $+, like $^ but before calling uniquize_deps. * job.c (reap_children): Call delete_child_targets for non-signal error if .DELETE_ON_ERROR is a target. Tue Sep 27 01:57:14 1994 Roland McGrath * Version 3.71.3. Mon Sep 26 18:16:55 1994 Roland McGrath * job.c (reap_children): Don't change C->file->command_state when dying. Test it only after calling start_job_command for a new command line. When no more cmds, just set C->file->update_status. (start_job_command): When the last line is empty or under -n, set C->file->update_status. (start_waiting_job): Grok cs_not_started after start_job_command as success. (new_job): Set C->file->update_status when there are no cmds. (job_next_command): When out of lines, don't set CHILD->file->update_status or CHILD->file->command_state. * main.c (quote_as_word): Renamed from shell_quote. Take new arg; if nonzero, also double $s. (main): Define MAKEOVERRIDES from command_variables here. (define_makeflags): Don't use command_variables here; instead write a reference $(MAKEOVERRIDES) in MAKEFLAGS. Make vars recursive. * dir.c [__MSDOS__]: Fixed typo. * vpath.c (selective_vpath_search): Reset EXISTS when stat fails. Sat Sep 10 03:01:35 1994 Roland McGrath * remake.c: Include and use assert instead of printfs and abort. * main.c (decode_switches): Loop until optind hits ARGC, not just until getopt_long returns EOF. Initialize C to zero before loop; in loop if C is EOF, set optarg from ARGV[optind++], else call getopt_long. (decode_env_switches): Use variable_expand instead of allocated_variable_expand. Allocate a fresh buffer to copy split words into; scan characters by hand to break words and debackslashify. (shell_quote): New function. (define_makeflags): Allocate doubled space for switch args, and command variable names and values; use shell_quote to quote those things. Fri Sep 9 01:37:47 1994 Roland McGrath * Version 3.71.2. * acconfig.h: Add HAVE_SYS_SIGLIST and HAVE__SYS_SIGLIST. * main.c (decode_switches): The non-option return from getopt is 1, not 0. (command_variables): New type and variable. (decode_switches, decode_env_switches): After making a variable definition, record the struct variable pointer in the command_variables chain. (define_makeflags): If ALL, write variable definitions for command_variables. * main.c (other_args): Variable removed. (goals, lastgoal): New static variables (moved from auto in main). (main): Don't process OTHER_ARGS at all. Don't set variable MAKEOVERRIDES at all; define MAKE to just $(MAKE_COMMAND). (init_switches): Prepend a - {return in order} instead of a + {require order}. (decode_switches): Don't set OTHER_ARGS at all. Grok '\0' return from getopt_long as non-option argument; try variable definition and (if !ENV) enter goal targets here. (decode_env_switches): Use allocated_variable_expand to store value. Use find_next_token to simplify word-splitting loop. Don't prepend a dash to uninterpreted value. Instead, if split into only one word, try variable definition and failing that prepend a dash to the word and pass it to decode_switches as a single arg. Wed Sep 7 03:02:46 1994 Roland McGrath * remake.c (notice_finished_file): Only recheck modtimes if FILE->command_state was cs_running on entry (meaning the commands actually just ran). (update_file_1): Whenever we set FILE->update_status, call notice_finished_file instead of just set_command_state. * job.c (start_job_command): Whenever we set CHILD->file->update_status, call notice_finished_file instead of just set_command_state. Tue Sep 6 19:13:54 1994 Roland McGrath * default.c: Add missing ". * job.c: Changed all assignments of command_state members to calls to set_command_state. * remake.c: Likewise. * file.c (set_command_state): New function. * file.h: Declare set_command_state. * main.c (init_switches): Put a + first in options. Mon Jul 25 18:07:46 1994 Roland McGrath Merge MSDOS/GO32 port from DJ Delorie . * vpath.c: Changed all uses of ':' to PATH_SEPARATOR_CHAR. * main.c (directory_before_chdir): New variable, moved out of main (was local). (main) [__MSDOS__]: Look for \ or : to delimit last component of PROGRAM. Don't frob ARGV[0] before setting MAKE_COMMAND variable. (die): Change back to `directory_before_chdir' before dying. * make.h (PATH_SEPARATOR_CHAR): New macro; differing defns for [__MSDOS__] and not. * job.c [__MSDOS__]: Include . [__MSDOS__] (dos_pid, dos_status, dos_bname, dos_bename, dos_batch_file): New variables. (reap_children) [__MSDOS__]: Don't call wait; just examine those vars. (unblock_sigs) [__MSDOS__]: Do nothing. (start_job_command) [__MSDOS__]: Use spawnvpe instead of vfork & exec. (load_too_high) [__MSDOS__]: Always return true. (search_path) [__MSDOS__]: Check for : or / in FILE to punt. Use PATH_SEPARATOR_CHAR instead of ':'. (construct_command_argv_internal) [__MSDOS__]: Wholly different values for sh_chars and sh_cmds. Wholly new code to handle shell scripts. * function.c (expand_function: `shell') [__MSDOS__]: Wholly new implementation. * dir.c [__MSDOS__] (dosify): New function. (dir_contents_file_exists_p) [__MSDOS__]: Call it on FILENAME and process the result instead of FILENAME itself. (file_impossible_p) [__MSDOS__]: Likewise. * default.c [__MSDOS__]: Define GCC_IS_NATIVE. (default_suffix_rules) [__MSDOS__]: Use `y_tab.c' instead of `y.tab.c'. (default_variables) [GCC_IS_NATIVE]: Set CC and CXX to `gcc', YACC to `bison -y', and LEX to `flex'. * configure.bat, configh.dos: New files. * commands.c (fatal_error_signal) [__MSDOS__]: Just remove intermediates and exit. * commands.c (set_file_variables): Add parens in length computation in .SUFFIXES dep loop to quiet compiler warning. From Jim Meyering. * read.c (read_makefile): Free FILENAME if we allocated it. From Jim Meyering. Mon Jul 4 17:47:08 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * misc.c (safe_stat): New function, EINTR-safe wrapper around stat. * vpath.c (selective_vpath_search): Use safe_stat in place of stat. * read.c (construct_include_path): Use safe_stat in place of stat. * job.c (search_path): Use safe_stat in place of stat. * dir.c (find_directory): Use safe_stat in place of stat. * commands.c (delete_target): Use safe_stat in place of stat. * arscan.c (ar_member_touch) [EINTR]: Do EINTR looping around fstat. * remake.c (name_mtime): Use safe_stat in place of stat. (touch_file) [EINTR]: Do EINTR looping around fstat. Fri Jun 24 05:40:24 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Check for a shell command first, and then strip leading tabs before further checking if it's not a shell command line. * make.h [__arm]: Undefine POSIX. [!__GNU_LIBRARY__ && !POSIX && !_POSIX_VERSION]: Don't declare system functions that return int. * job.c (construct_command_argv_internal): After swallowing a backslash-newline combination, if INSTRING is set goto string_char (new label) for normal INSTRING handling code. Sat Jun 4 01:11:20 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) * configure.in: Don't check for sys_siglist and _sys_siglist with AC_HAVE_FUNCS. Instead use two AC_COMPILE_CHECKs. Mon May 23 18:20:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.71.1 released. * make.h [!__GNU_LIBRARY__ && !POSIX]: Also test #ifndef _POSIX_VERSION for these declarations. * misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Remove bogus #ifndefs around #undefs of HAVE_SETREUID and HAVE_SETREGID. Sat May 21 16:26:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.71 released. * misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Don't test [HAVE_SETUID] and [HAVE_SETGID]. Every system has those, and configure doesn't check for them. * make.h [_POSIX_VERSION]: Don't #define POSIX #ifdef ultrix. * compatMakefile (loadavg): Depend on and use loadavg.c instead of getloadavg.c. (loadavg.c): Link or copy it from getloadavg.c. (distclean): Remove loadavg.c. Mon May 16 22:59:04 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.70.4. * misc.c [GETLOADAVG_PRIVILEGED] [! POSIX]: Undefine HAVE_SETEUID and HAVE_SETEGID. * default.c (default_terminal_rules): In SCCS rules, put $(SCCS_OUTPUT_OPTION) before $<. On some systems -G is grokked only before the file name. * configure.in (SCCS_GET_MINUS_G check): Put -G flag before file name. Tue May 10 16:27:38 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Swallow backslash-newline combinations inside '' strings too. Thu May 5 04:15:10 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (do_define): Call collapse_continuations on each line before all else. Mon Apr 25 19:32:02 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Notice newline inside '' string when RESTP is non-null. Fri Apr 22 17:33:30 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.70.3. * remake.c (update_goal_chain): Reset FILE to G->file after the double-colon loop so it is never null for following code. * read.c (read_makefile): Fix `override define' parsing to skip whitespace after `define' properly. * compatMakefile (srcdir): Define as @srcdir@; don't reference $(VPATH). (glob/Makefile): New target. Thu Apr 21 16:16:55 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.70.2. * misc.c (remove_comments): Use find_char_unquote. * make.h (find_char_unquote): Declare it. * read.c (find_char_unquote): New function, generalized from find_percent. (find_percent, find_semicolon, parse_file_seq): Use that. Wed Apr 20 18:42:39 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * implicit.c (pattern_search): Always allocate new storage for FILE->stem. It is not safe to store STEM's address because it might be auto storage. * configure.in: Check for seteuid and setegid. * misc.c [HAVE_SETEUID]: Declare seteuid. [HAVE_SETEGID]: Declare setegid. (make_access, user_access) [HAVE_SETEUID]: Use seteuid. [HAVE_SETEGID]: Use setegid. * remake.c (update_goal_chain): Set STATUS to FILE->update_status, to preserve whether it's 2 for error or 1 for -q trigger. When STATUS gets nonzero and -q is set, always stop immediately. * main.c (main, decode_switches): Die with 2 for errors. (main): Accept 2 return from update_goal_chain and die with that. * misc.c (fatal, makefile_fatal): Die with 2; 1 is reserved for -q answer. * job.c (reap_children): Die with 2 for error. (start_job_command): Set update_status to 2 for error. Set it to 1 when we would run a command and question_flag is set. * read.c (read_makefile): Don't mark makefiles as precious. Just like other targets, they can be left inconsistent and in need of remaking by aborted commands. * read.c (read_makefile): Write no error msg for -include file. Tue Apr 5 05:22:19 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * commands.c (fatal_error_signal): Don't unblock signals. * file.h (struct file): Change member `double_colon' from flag to `struct file *'. * read.c (record_files): Set double_colon pointer instead of flag. * main.c (main): When disqualifying makefiles for updating, use double_colon pointer to find all entries for a file. * file.c (enter_file): If there is already a double-colon entry for the file, set NEW->double_colon to that pointer. (file_hash_enter): Use FILE->double_colon to find all entries to set name. * remake.c (update_goal_chain): Do inner loop on double-colon entries. (update_file): Use FILE->double_colon pointer to find all entries. (f_mtime): Likewise. (notice_finished_file): Propagate mtime change to all entries. * variable.c (try_variable_definition): Return after abort. Fri Apr 1 18:44:15 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Remove unused variable. (parse_file_seq): When removing an elt that is just `)', properly fix up the previous elt's next pointer. Mon Mar 28 18:31:49 1994 Roland McGrath (roland@mole.gnu.ai.mit.edu) * configure.in: Do AC_SET_MAKE. * GNUmakefile (Makefile.in): Edit MAKE assignment into @SET_MAKE@. Fri Mar 4 00:02:32 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * function.c (subst_expand): If BY_WORD or SUFFIX_ONLY is set and the search string is the empty string, find a match at the end of each word (using end_of_token in place of sindex). * misc.c (end_of_token): Don't treat backslashes specially; you can no longer escape blanks with backslashes in export, unexport, and vpath. This was never documented anyway. Thu Mar 3 23:53:46 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Variable name for `define' is not just first token; use whole rest of line and strip trailing blanks. Wed Feb 16 16:03:45 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.70.1. * read.c (read_makefile): Add -d msg stating args. * read.c (read_makefile): Use isspace to skip over leading whitespace, and explicitly avoid skipping over tabs. Don't want to skip just spaces though; formfeeds et al should be skipped. * default.c (default_variables) [__hpux]: Add f in ARFLAGS. * arscan.c (ar_name_equal) [__hpux]: Subtract 2 instead of 1 from sizeof ar_name for max length to compare. * misc.c [GETLOADAVG_PRIVILEGED] [POSIX]: Undefine HAVE_SETREUID #ifdef HAVE_SETUID; likewise HAVE_SETREGID and HAVE_SETGID. * main.c (main): Call user_access after setting `program', in case it needs to use it in an error message. * read.c (read_makefile): Ignore an empty line starting with a tab. Thu Feb 10 21:45:31 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in (AC_SYS_SIGLIST_DECLARED): Use this instead of AC_COMPILE_CHECK that is now its contents. Fri Feb 4 16:28:54 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h: #undef strerror after #include . [! ANSI_STRING]: Declare strerror. Thu Feb 3 02:21:22 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * misc.c (strerror): #undef any macro before function definition. Mon Jan 31 19:07:23 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (try_variable_definition): Calculate BEG before loop to strip blanks by decrementing END. Don't decr END to before BEG. * read.c (read_makefile): Skip over leading space characters, but not tabs, after removing continuations and comments (it used to use isspace). Tue Jan 25 16:45:05 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (define_automatic_variables): In $(@D) et al, use patsubst to remove trailing slash. * commands.c (delete_target): New function, broken out of delete_child_targets. Check for archive members and give special msg. (delete_child_targets): Use delete_target. Mon Jan 17 17:03:22 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (default_suffix_rules): Use $(TEXI2DVI_FLAGS) in texi2dvi rules. Use $(MAKEINFO_FLAGS) in makeinfo rules. Tue Jan 11 19:29:55 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * GNUmakefile (tarfiles): Omit make-doc. (make-$(version).tar): Include make.info*. Fri Jan 7 16:27:00 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (configure, config.h.in): Comment out rules. Thu Jan 6 18:08:08 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (binprefix, manprefix): New variables. (instname): Variable removed. (install): Use $({bin,man}prefix)make in place of $(instname). File targets likewised renamed. Mon Jan 3 17:50:25 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.70 released. Thu Dec 23 14:46:54 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.69.3. * read.c (parse_file_seq): Inside multi-word archive ref translation loop, check NEW1==0 at end and break out of the loop. * GNUmakefile (make-$(version).tar): Distribute install.sh. * install.sh: New file. * configure.in (SCCS_GET_MINUS_G check): Put redirection for admin cmds outside subshell parens, to avoid "command not found" msgs from the shell. Wed Dec 22 17:00:43 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in (SCCS_GET_MINUS_G check): Put -G flag last in get cmd. Redirect output & error from get to /dev/null. Fix reversed sense of test. Fri Dec 17 15:31:36 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in (SCCS_GET_MINUS_G check): Use parens instead of braces inside if condition command; some shells lose. Thu Dec 16 15:10:23 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.69.2. * arscan.c [M_UNIX]: Move #undef M_XENIX for PORTAR stuff. (PORTAR) [M_XENIX]: Define to 0 instead of 1. * main.c (define_makeflags): Only export MAKEFLAGS if !ALL. Wed Dec 15 17:47:48 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (main): Cast result of pointer arith to unsigned int before passing to define_variable for envars. Matters when sizeof(unsigned)!=sizeof(ptrdiff_t). Tue Dec 14 14:21:16 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in: Add new check for SCCS_GET_MINUS_G. * config.h.in: Add #undef SCCS_GET_MINUS_G. * default.c (default_terminal_rules): Use `$(SCCS_OUTPUT_OPTION)' in place of `-G $@' in SCCS commands. (default_variables) [SCCS_GET_MINUS_G]: Define SCCS_OUTPUT_OPTION to "-G$@". * configure.in (AC_OUTPUT): Put touch stamp-config in second arg (so it goes in config.status), rather than afterward. * ar.c (ar_member_date): Don't call enter_file on the archive file if it doesn't exist (by file_exists_p). * compatMakefile ($(infodir)/make.info): Replace `$$d/foo.info' with `$$dir/make.info' in install-info invocation (oops). * vpath.c (construct_vpath_list): Only set LASTPATH set PATH when we do not unlink and free PATH. * file.c (print_file_data_base): Fix inverted calculation for average files per hash bucket. * read.c (readline): When we see a NUL, give only a warning and synthesize a newline to terminate the building line (used to fatal). Move fgets call into the loop condition, and after the loop test ferror (used to test !feof in the loop). Fri Dec 3 16:40:31 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in: Check for strerror in AC_HAVE_FUNCS. Thu Dec 2 15:37:50 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) Differentiate different flavors of missing makefile error msgs, removing gratuitous `fopen: ' and giving caller for included makefiles. * misc.c [! HAVE_STRERROR]: Define our own strerror here. (perror_with_name, pfatal_with_name): Use strerror instead of replicating its functionality. * read.c (read_makefile): Return int instead of void. (read_all_makefiles, read_makefile): Change callers to notice zero return and give error msg. Thu Nov 11 11:47:36 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.69.1. * default.c: Put `-G $@' before $< in SCCS cmds. Wed Nov 10 06:06:14 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): After trying a variable defn, notice if the line begins with a tab, and diagnose an error. Sun Nov 7 08:07:37 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.69. Wed Nov 3 06:54:33 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.10. * implicit.c (try_implicit_rule): Look for a normal rule before an archive rule. Fri Oct 29 16:45:28 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * function.c (expand_function: `sort'): Double NWORDS when it overflows, instead of adding five. * compatMakefile (clean): Remove loadavg. Wed Oct 27 17:58:33 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.9. * file.h (NEW_MTIME): Define new macro. * main.c (main): Set time of NEW_FILES to NEW_MTIME, not to current time returned from system. Removed variable NOW. * remake.c (notice_finished_file): Use NEW_MTIME in place of current time here too. Tue Oct 26 19:45:35 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.8. * remake.c (update_file_1): Don't clear MUST_MAKE when FILE has no cmds and !DEPS_CHANGED unless also !NOEXIST. Mon Oct 25 15:25:21 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (parse_file_seq): When converting multi-word archive refs, ignore a word beginning with a '('. Fri Oct 22 02:53:38 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in: Check for sys/timeb.h. * make.h [HAVE_SYS_TIMEB_H]: Test this before including it. Thu Oct 21 16:48:17 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.7. * rule.c (convert_suffix_rule): New local TARGPERCENT. Set it to TARGNAME+1 for "(%.o)", to TARGNAME for "%.?". Use it in place of TARGNAME to initialize PERCENTS[0]. Mon Oct 18 06:49:35 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in: Use AC_HAVE_HEADERS(unistd.h) instead of AC_UNISTD_H. Remove AC_USG; it is no longer used. * file.c (print_file): New function, broken out of print_file_data_base. (print_file_data_base): Call it. * rule.c (print_rule): New function, broken out of print_rule_data_base. (print_rule_data_base): Call it. Thu Oct 14 14:54:03 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (install_default_suffix_rules): New function, broken out of install_default_implicit_rules. (install_default_implicit_rules): Move suffix rule code there. * make.h: Declare install_default_suffix_rules. * main.c (main): Call install_default_suffix_rules before reading makefiles. Move convert_to_pattern call before install_default_implicit_rules. * job.h (struct child): Make `pid' member type `pid_t' instead of `int'. * compatMakefile (RANLIB): New variable, set by configure. (glob/libglob.a): Pass RANLIB value down to submake. Fixes for SCO 3.2 "devsys 4.2" from pss@tfn.com (Peter Salvitti). * make.h: Include before for SCO lossage. * job.c [! getdtablesize] [! HAVE_GETDTABLESIZE]: If NOFILE is not defined but NOFILES_MAX is, define it to be that. Mon Oct 11 19:47:33 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * GNUmakefile (make-$(version).tar): Depend on acconfig.h, so it is distributed. Sun Oct 3 15:15:33 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (default_terminal_rules): Add `-G $@' to SCCS get cmds. Tue Sep 28 14:18:20 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Add ^ to SH_CHARS; it is another symbol for | in some shells. * main.c (main): Add it to CMD_DEFS quoting list as well. Mon Sep 20 18:05:24 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Remove '=' from SH_CHARS. Only punt on '=' if it is unquoted in a word before the first word without an unquoted '='. * main.c (define_makeflags): Set v_export for MAKEFLAGS. Fri Sep 17 00:37:18 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (update_file_1): Use .DEFAULT cmds for phony targets. * make.h [_AIX && _POSIX_SOURCE]: Define POSIX. * commands.c (delete_child_targets): Don't delete phony files. * job.c (start_job_command): Set COMMANDS_RECURSE in FLAGS if we see a `+' at the beginning of the command line. Thu Sep 9 17:57:14 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.6. Wed Sep 8 20:14:21 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (define_makeflags): Define MAKEFLAGS with o_file, not o_env. Mon Aug 30 12:31:58 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * expand.c (variable_expand): Fatal on an unterminated reference. Thu Aug 19 16:27:53 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.5. * variable.c (define_automatic_variables): Define new o_default variable `MAKE_VERSION' from version_string and remote_description. * make.h (version_string, remote_description): Declare these here. * main.c: Don't declare version_string. (print_version): Don't declare remote_description. Wed Aug 18 15:01:24 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Free space pointed to by CONDITIONALS before restoring the old pointer. Mon Aug 16 17:33:36 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile ($(objs)): Depend on config.h. * GNUmakefile (build.sh.in): Depend on compatMakefile. * configure.in: Touch stamp-config after AC_OUTPUT. Fri Aug 13 16:04:22 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.4. Thu Aug 12 17:18:57 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h: Include instead of "config.h". Wed Aug 11 02:35:25 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (main): Make all variables interned from ENVP be v_export. * variable.c (try_variable_definition): In v_default case, don't check for an o_file variable that `getenv' finds. * job.c (reap_children): New local variable ANY_LOCAL; set it while setting ANY_REMOTE. If !ANY_LOCAL, don't wait for local kids. * main.c (main): Don't call decode_env_switches on MFLAGS. DOC THIS. * function.c (expand_function): #if 0 out freeing of ENVP since it is environ. Mon Aug 9 17:37:20 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.3. * remote-stub.c (remote_status): Set errno to ECHILD before return. * job.c (reap_children): Scan the chain for remote children and never call remote_status if there are none. * function.c (expand_function: `shell'): #if 0 out calling target_environment; just set ENVP to environ instead. * job.c (reap_children): Check for negative return from remote_status and fatal for it. When blocking local child wait returns 0, then try a blocking call to remote_status. Tue Aug 3 00:19:00 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (clean): Delete make.info* and make.dvi here. (distclean): Not here. * dep.h (RM_*): Use #defines instead of enum to avoid lossage from compilers that don't like enum values used as ints. Mon Aug 2 16:46:34 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (loadavg): Add $(LOADLIBES). Sun Aug 1 16:01:15 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.2. * compatMakefile (loadavg, check-loadavg): New targets. (check): Depend on check-loadavg. * compatMakefile (glob/libglob.a): Depend on config.h. * misc.c (log_access): Write to stderr instead of stdout. Fri Jul 30 00:07:02 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68.1. Thu Jul 29 23:26:40 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in (SYS_SIGLIST_DECLARED): In test program include #ifdef HAVE_UNISTD_H. * compatMakefile (.PHONY): Put after `all' et al. * configure.in: Add AC_IRIX_SUN. Wed Jul 28 17:41:12 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.68. Mon Jul 26 14:36:49 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.8. Sun Jul 25 22:09:08 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.7. * compatMakefile ($(infodir)/make.info): Don't use $(instname). Run install-info script if present. Fri Jul 23 16:03:50 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h [STAT_MACROS_BROKEN]: Test this instead of [uts]. * configure.in: Add AC_STAT_MACROS_BROKEN. Wed Jul 14 18:48:11 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.6. * read.c (read_makefile): Recognize directive `-include', like `include' but sets RM_DONTCARE flag. * variable.c (target_environment): If FILE is nil, use current_variable_set_list in place of FILE->variables. * function.c (expand_function: `shell'): Get an environment for the child from target_environment instead of using environ. * dep.h: Declare read_all_makefiles here. (RM_*): Define new enum constants. * read.c (read_makefile): Second arg is FLAGS instead of TYPE. Treat it as a bit mask containing RM_*. (read_all_makefiles): For default makefiles, set D->changed to RM_DONTCARE instead of 1. * main.c: Don't declare read_all_makefiles here. (main): Check `changed' member of read_makefiles elts for RM_* flags instead of specific integer values. Mon Jul 12 22:42:17 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h [sequent && i386]: #undef POSIX. From trost@cse.ogi.edu. Thu Jul 8 19:51:23 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * vpath.c (construct_vpath_list): If ELEM is zero 0, free PATTERN as well as VPATH. (build_vpath_lists): Empty `vpaths' around construct_vpath_list call for $(VPATH). Expand $(strip $(VPATH)), not just $(VPATH). * rule.c (convert_suffix_rule): Use alloca instead of xmalloc for PERCENTS, whose storage is not consumed by create_pattern_rule. * make.h [__mips && _SYSTYPE_SVR3]: #undef POSIX. Wed Jun 30 18:11:40 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.5. * rule.c (max_pattern_targets): New variable. (count_implicit_rule_limits): Compute its value. * rule.h: Declare it. * implicit.c (pattern_search): Make TRYRULES max_target_patterns times bigger. Move adding new TRYRULES elt inside the inner targets loop, so each matching target gets its own elt in MATCHES and CHECKED_LASTSLASH. * file.c (remove_intermediates): If SIG!=0 say `intermediate file' instead of just `file' in error msg. Fri Jun 25 14:55:15 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv): Turn off --warn-undefined-variables around expansion of SHELL and IFS. * read.c (tilde_expand): Likewise for HOME. (read_all_makefiles): Likewise for MAKEFILES. * vpath.c (build_vpath_lists): Likewise for VPATH. * main.c (warn_undefined_variables_flag): New flag variable. (switches): Add --warn-undefined-variables. * make.h (warn_undefined_variables_flag): Declare it. * expand.c (warn_undefined): New function. (reference_variable): Call it if the variable is undefined. (variable_expand): In substitution ref, call warn_undefined if the variable is undefined. * default.c (default_pattern_rules): Add `%.c: %.w %.ch' and `%.tex: %.w %.ch' rules. (default_suffix_rules: .w.c, .w.tex): Pass three args: $< - $@. (default_suffixes): Add `.ch'. Mon Jun 21 17:55:39 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (default_suffixes): Replace `.cweb' with `.w'. (default_suffix_rules): Rename `.cweb.c' and `.cweb.tex' to `.w.c' and `.w.tex'. Fri Jun 11 14:42:09 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile ($(bindir)/$(instname)): Add missing backslash. Thu Jun 10 18:14:08 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.4. * read.c (multi_glob): Don't free OLD and OLD->name in the FOUND!=0 fork. Use new block-local variable F instead of clobbering OLD. * ar.c (glob_pattern_p): New function, snarfed from glob/glob.c. (ar_glob): Call it; return nil immediately if MEMBER_PATTERN contains no metacharacters. Wed Jun 9 16:25:35 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * ar.c (ar_glob{_match,_alphacompare}): New function. * dep.h [! NO_ARCHIVES]: Declare it. * read.c (multi_glob) [! NO_ARCHIVES]: Use it on archive member elts. * read.c (read_makefile): Pass flag (1) to parse_file_seq, not to multi_glob (which doesn't take a 3rd arg). * rule.c (install_pattern_rule): Likewise. * default.c (set_default_suffixes): Here too. * function.c (string_glob): Don't pass gratuitous arg to multi_glob. * read.c (parse_file_seq) [! NO_ARCHIVES]: Add post-processing loop to translate archive refs "lib(a b)" into "lib(a) lib(b)". Mon Jun 7 19:26:51 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (installdirs): Actually pass directory names. ($(bindir)/$(instname)): Test chgrp&&chmod exit status with `if'; if it fails, echo a warning msg, but don't make the rule fail. * read.c (tilde_expand): New function, broken out of tilde_expand. (multi_glob): Call it. (construct_include_path): Expand ~ in directory names. * dep.h: Declare tilde_expand. * main.c (enter_command_line_file): Expand ~ at the start of NAME. (main): Expand ~ in -C args. * read.c (read_makefile): Expand ~ in FILENAME unless TYPE==2. Fri Jun 4 13:34:47 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (decode_env_switches): Use xmalloc instead of alloca for ARGS. * main.c (main): Put result of alloca in temporary variable with simple assignment, to make SGI compiler happy. Thu Jun 3 20:15:46 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.3. * main.c (main): Before re-execing, remove intermediate files, and print the data base under -p. Sexier debugging message. * implicit.c (pattern_search): Allocate an extra copy of the name of a winning intermediate file when putting it in FOUND_FILES. Wed Jun 2 16:38:08 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Pass flag (1) to parse_file_seq, not to multi_glob (which doesn't take a 3rd arg). * dir.c (dir_contents_file_exists_p): When reading dirents, ignore chars within D_NAMLEN that are NULs. * main.c (decode_switches): Don't savestring ARGV[0] to put it into `other_args'. For string switch, don't savestring `optarg'. (main): Don't free elts of makefiles->list that are "-". Use alloca'd rather than savestring'd storage for elts of makefiles->list that are temporary file names. * read.c (read_all_makefiles): Don't free *MAKEFILES. * file.c (enter_file): Don't strip `./'s. * main.c (enter_command_line_file): New function. (main): Use it in place of enter_file for command-line goals from other_files, and for old_files and new_files. Mon May 31 18:41:40 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.2. * compatMakefile (.SUFFIXES): Add .info. ($(infodir)/$(instname).info): Find make.info* in cwd if there, else in $srcdir. Use basename to remove dir name from installed name. Thu May 27 17:35:02 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * implicit.c (pattern_search): When interning FOUND_FILES, try lookup_file first; if found, free the storage for our copy of the name. Wed May 26 14:31:20 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67.1. * main.c (decode_switches): In usage msg, write `--switch=ARG' or `--switch[=OPTARG]' rather than `--switch ARG' or `--switch [ARG]'. Mon May 24 16:17:31 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * rule.c (convert_suffix_rule): New function. (convert_to_pattern): Use it instead of doing all the work here several times. For target suffix `.a', generate both the archive magic rule and the normal rule. * compatMakefile (distclean): Remove stamp-config. Sat May 22 16:15:18 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.67. * file.c (remove_intermediates): Don't write extra space after `rm'. * main.c (struct command_switch.type): Remove `usage_and_exit'. (print_usage_flag): New variable. (switches: --help): Make type `flag', to set print_usage_flag. (init_switches): Remove `usage_and_exit' case. (decode_switches): Likewise. (decode_switches): Print usage if print_usage_flag is set. When printing usage, die with status of BAD. (main): Die with 0 if print_version_flag. Fri May 21 16:09:28 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.66. Wed May 19 21:30:44 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (installdirs): New target. (install): Depend on it. Sun May 16 20:15:07 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.65.2. Fri May 14 16:40:09 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * vpath.c (construct_vpath_list): In removal loop for DIRPATH==0, set LASTPATH to PATH, not NEXT. * dir.c (read_dirstream): Break out of loop after incrementing DS->buckets such that it reaches DIRFILE_BUCKETS; avoid trying to dereference DS->contents->files[DIRFILE_BUCKETS]. * read.c (read_makefile): Clear no_targets after reading a targetful rule line. * main.c (main): If print_version_flag is set, exit after printing the version. (switches): Change --version docstring to say it exits. * make.h [butterfly]: #undef POSIX. Wed May 12 15:20:21 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.65.1. * arscan.c (ar_scan) [! AIAMAG]: Don't declare LONG_NAME. [AIAMAG]: Pass TRUNCATE flag arg to (*FUNCTION), always zero. * function.c (handle_function): Use fatal instead of makefile_fatal when reading_filename is nil. * configure.in: Add AC_GETGROUPS_T. * job.c (search_path): Use GETGROUPS_T in place of gid_t. Sun May 9 15:41:25 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.65. Fri May 7 18:34:56 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * function.c (handle_function): Fatal for unmatched paren. Thu May 6 16:13:41 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.64.3. * commands.c (handling_fatal_signal): New variable. (fatal_error_signal): Set it. * job.c (reap_children): Avoid nonreentrant operations if that is set. * make.h: Declare handling_fatal_signal. * expand.c (reference_variable): New function, snippet of code broken out of simple-reference case of variable_expand. (variable_expand): Use it for simple refs. (variable_expand): When checking for a computed variable name, notice a colon that comes before the final CLOSEPAREN. Expand only up to the colon, and then replace the pending text with a copy containing the expanded name and fall through to subst ref handling. (variable_expand): Don't bother expanding the name if a colon appears before the first $. (expand_argument): Use alloca instead of savestring. (variable_expand): For subst ref, expand both sides of = before passing to [pat]subst_expand. Use find_percent instead of lindex to check the lhs for a %. Wed May 5 14:45:52 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.64.2. Mon May 3 17:00:32 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * arscan.c (ar_name_equal) [AIAMAG]: Abort if TRUNCATED is nonzero. * read.c (read_makefile): Pass extra arg of 1 to parse_file_seq, not to multi_glob. Thu Apr 29 19:47:33 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.64.1. * arscan.c (ar_scan): New local flag var LONG_NAME. Set it when we read the member name in any of the fashions that allow it to be arbitrarily long. Pass its negation to FUNCTION. (describe_member): Take TRUNCATED from ar_scan and print it. (ar_name_equal): Take new arg TRUNCATED; if nonzero, compare only the first sizeof (struct ar_hdr.ar_name) chars. (ar_member_pos): Take TRUNCATED from ar_scan, pass to ar_name_equal. * ar.c (ar_member_date_1): Likewise. Wed Apr 28 21:18:22 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (reap_children): Before calling start_job_command to start the next command line, reset C->remote by calling start_remote_job_p. Mon Apr 26 15:56:15 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * arscan.c (ar_scan): New local var NAMEMAP. In loop, rename NAME to NAMEBUF; new var NAME is a pointer; new flag IS_NAMEMAP. When extracting the member name, always put a null at its end first. If the name is "//" or "/ARFILENAMES", set IS_NAMEMAP. If we have already read in NAMEMAP, and NAME looks like " /N", get full name from NAMEMAP+N. Else if NAME looks like "#1/N", read N chars from the elt data to be the full name. At end of loop, if IS_NAMEMAP, read the elt's data into alloca'd NAMEMAP. (ar_name_equal): #if 0 truncating code. * make.h: Don't declare vfork at all. It returns int anyway, unless declared it; and we conflicted with some systems. * main.c (define_makeflags): If FLAGSTRING[1] is '-', define MAKEFLAGS to all of FLAGSTRING, not &FLAGSTRING[1]. Don't want to define it to something like "-no-print-directory". Use %g format instead of %f for floating-valued things. Thu Apr 22 18:40:58 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * GNUmakefile (Makefile.in): Use a substitution ref on nolib-deps to change remote-%.dep to remote-stub.dep. Wed Apr 21 15:17:54 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.64. Fri Apr 16 14:22:22 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (install): Remove - prefix from chgrp+chmod. * Version 3.63.8. Thu Apr 15 18:24:07 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * acconfig.h: New file; contains "#undef SCCS_GET" for autoheader. * configure.in: If /usr/sccs/get exists, define SCCS_GET to that, else to "get". * default.c (default_variables): Set GET to macro SCCS_GET. * read.c (parse_file_seq): Take extra arg STRIP; strip `./' only if nonzero. I hope this is the last time this argument is added or removed. (read_makefile): Pass it 1 when parsing include file names. Pass it 1 when parsing target file names. Pass it 1 when parsing static pattern target pattern names. * rule.c (install_pattern_rule): Pass it 1 when parsing rule deps. * default.c (set_default_suffixes): Pass it 1 when parsing default_suffixes. * function.c (string_glob): Pass it 0 here. Wed Apr 14 11:32:05 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * misc.c (log_access): New function. ({init,user,make,child}_access): Call it. (child_access): Abort if !access_inited. * main.c (switches: --no-print-directory): Use 1 instead of -1 for single-letter option. (init_switches, decode_switches, define_makeflags): An option with no single-letter version is no longer indicated by a value of -1; instead a value that is !isalnum. (init_switches): Don't put such switches into the string, only into the long_option table. * make.h [!NSIG] [!_NSIG]: #define NSIG 32. * job.c [HAVE_WAITPID]: Remove #undef HAVE_UNION_WAIT. AIX's bsdcc defined WIF* to use union wait. * main.c (struct command_switch): Change member `c' to type int. (switches): Make const. (decode_switches): Use `const struct command_switch *'. (define_makeflags): Likewise. * default.c (default_suffix_rules): Add `-o $@' to makeinfo rules. Mon Apr 12 12:30:04 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.63.7. * configure.in (AC_HAVE_HEADERS): Check for string.h and memory.h. Removed AC_MEMORY_H. * make.h [USG, NeXT]: Don't test these. [HAVE_STRING_H]: Test this to include string.h and define ANSI_STRING. [HAVE_MEMORY_H]: Test this instead of NEED_MEMORY_H. [! ANSI_STRING]: Put decls of bcopy et al here. [sparc]: Don't test this for alloca.h; HAVE_ALLOCA_H is sufficient. [HAVE_SIGSETMASK]: Test this rather than USG. [__GNU_LIBRARY__ || POSIX]: Don't #include again. * main.c (main): Handle SIGCHLD if defined, and SIGCLD if defined. It doesn't hurt to do both if they are both defined, and testing USG is useless. * dir.c: Rationalize directory header conditionals. * arscan.c [HAVE_FCNTL_H]: Test this rather than USG || POSIX. * default.c (default_suffixes): Add `.txinfo'. (default_suffix_rules): Add `.txinfo.info' and `.txinfo.dvi' rules. * variable.c (try_variable_definition): Replace RECURSIVE flag with enum FLAVOR, which can be simple, recursive, or append. Recognize += as append flavor. Set new variable VALUE in a switch on FLAVOR. For append flavor, prepend the variable's old value. If the variable was previously defined recursive, set FLAVOR to recursive; if it was defined simple, expand the new value before appending it to the old value. Pass RECURSIVE flag to define_variable iff FLAVOR == recursive. * variable.c (try_variable_definition): Use alloca and bcopy for NAME, instead of savestring. Might as well use stack storage since we free it immediately anyway. Thu Apr 8 18:04:43 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (start_waiting_jobs): Move decl of JOB outside of loop. * main.c (define_makeflags): Rename `struct flag' member `switch' to `cs', which is not a reserved word. Wed Apr 7 15:30:51 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (new_job): Call start_waiting_jobs first thing. (start_waiting_job): Changed return type from void to int. Return 0 when putting the child on the waiting_jobs chain. (start_waiting_jobs): Don't check load and job_slots here. Always take a job off the chain and call start_waiting_job on it; give up and return when start_waiting_job returns zero. * main.c (define_makeflags: struct flag): Change member `char c' to `struct command_switch *switch'. (ADD_FLAG): Set that to CS instead of CS->c. If CS->c is -1, increment FLAGSLEN for the long name. When writing out FLAGS, handle FLAGS->switch->c == -1 and write the long name instead. * compatMakefile (stamp-config): New target of old config.h rule. Touch stamp-config after running config.status. (config.h): Just depend on stamp-config, and have empty commands. Mon Apr 5 20:14:02 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c [HAVE_WAITPID]: #undef HAVE_UNION_WAIT. * configure.in (AC_HAVE_FUNCS): Check for psignal. Fri Apr 2 17:15:46 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (long_option_aliases): Remove "new"; it is already an unambiguous prefix of "new-file". Sun Mar 28 16:57:17 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.63.6. Wed Mar 24 14:26:19 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * vpath.c (selective_vpath_search): When adding the name-within-directory at the end of NAME, and we don't add a slash, don't copy FILENAME in one char too far into NAME. * variable.c (define_automatic_variables): Find default_shell's length with strlen, not numerology. Wed Mar 17 20:02:27 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (define_makeflags): Add the elts of a string option in reverse order, so they come out right when reversed again. Fri Mar 12 15:38:45 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (make.info): Use `-o make.info'. Thu Mar 11 14:13:00 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (REMOTE): Set to @REMOTE@; change comments to reflect new use. (objs): Replace remote.o with remote-$(REMOTE).o. (srcs): Replace remote.c with remote-$(REMOTE).c. (remote.o): Rule removed. * configure.in (REMOTE): Subst this in Makefile et al; default "stub". Use AC_WITH to grok --with-customs arg to set REMOTE=cstms. * GNUmakefile (build.sh.in): Filter out remote-% from objs list. * build.template (REMOTE): New var; set to @REMOTE@. (objs): Add remote-${REMOTE}.o. Wed Mar 10 15:12:24 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.63.5. * implicit.c (pattern_search): Fix "dependent"->"dependency" in "Rejecting impossible" -d msg. * file.c (file_hash_enter): New local vars {OLD,NEW}BUCKET. Store mod'd values there; never mod {OLD,NEW}HASH. Mon Mar 8 13:32:48 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * remake.c [eta10]: Include instead of . * compatMakefile (VPATH): Set this to @srcdir@. (srcdir): Set this to $(VPATH). * main.c (main): New local var DIRECTORY_BEFORE_CHDIR. Save in it a copy of CURRENT_DIRECTORY after the first getcwd. Use it instead of CURRENT_DIRECTORY when chdir'ing back before re-execing. * remake.c (notice_finished_file): Pass missing SEARCH arg to f_mtime. * read.c (read_makefile): Remove extraneous arg to parse_file_seq. Mon Feb 22 14:19:38 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile ($(infodir)/$(instname).info): Use , instead of / as the sed delimiter char. Sun Feb 21 14:11:04 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.63.4. * rule.h (struct rule): Removed `subdir' member. * rule.c (new_pattern_rule): No need to clear it. (count_implicit_rule_limits): Set the `changed' flag in each dep that refers to a nonexistent directory. No longer set rule-global `subdir' flag with that information. (print_rule_data_base): Don't record info on `subdir' flags. * implicit.c (pattern_search): Check the DEP->changed flag rather than the (now gone) RULE->subdir flag. Also test CHECK_LASTSLASH; if it is set, the file might exist even though the DEP->changed flag is set. * rule.c (count_implicit_rule_limits): Pass "", not ".", as file name arg to dir_file_exists_p to check for existence of directory. * implicit.c (pattern_search): Inside dep-finding loop, set CHECK_LASTSLASH from the value recorded in CHECKED_LASTSLASH[I], rather than computing it anew. * commands.c (set_file_variables): Must alloca space for PERCENT and copy it, to avoid leaving the trailing `)' in the value. * misc.c (remove_comments): Fixed backslash-checking loop condition to allow it to look at the first char on the line. P2 >= LINE, not P2 > LINE. * compatMakefile ($(bindir)/$(instname)): Before moving $@.new to $@, rm $@.old and mv $@ to $@.old. * variable.c (try_variable_definition): Take new args FILENAME and LINENO. Fatal if the variable name is empty. * read.c (read_makefile): Change callers. * main.c (main): Likewise. * compatMakefile (group): Define to @KMEM_GROUP@, autoconf magic that configure will replace with the group owning /dev/kmem. Mon Feb 8 14:26:43 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * vpath.c (vpath_search): Take second arg MTIME_PTR, pass thru to selective_vpath_search. (selective_vpath_search): Take second arg MTIME_PTR. If the dir cache thinks a file exists, stat it to make sure, and put the modtime in *MTIME_PTR. * remake.c (library_search): Take second arg MTIME_PTR. When we find a match, record its mtime there. Pass MTIME_PTR through to vpath_search to do same. (f_mtime): Pass &MTIME as new 2nd arg to {vpath,library}_search; store it in FILE->last_mtime if set nonzero. * implicit.c (pattern_search): Pass nil 2nd arg to vpath_search. * compatMakefile (remote.o): Prepend `$(srcdir)/' to `remote-*.c', so globbing looks somewhere it will find things. * compatMakefile ($(infodir)/$(instname).info): Install `make.info*' not `$(srcdir)/make.info*'; no need to use basename. Fri Feb 5 12:52:43 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.63.3. * compatMakefile (install): Add missing ;\s. Make -, @, and + prefixes on a pre-expanded command line affect all lines in the expansion, not just the first. * commands.h (struct commands): Replace `lines_recurse' member with `lines_flags'. (COMMANDS_{RECURSE,SILENT,NOERROR}): New macros, bits to set in that flag byte. * commands.c (chop_commands): Set `lines_flags' instead of `lines_recurse'. Record not only + but also @ and - prefixes. * remake.c (notice_finished_file): Check the COMMANDS_RECURSE bit in FILE->cmds->lines_flags, rather than FILE->cmds->lines_recurse. * job.c (start_job_command): Replaced RECURSIVE and NOPRINT local var with FLAGS; initialize it to the appropriate `lines_flags' byte. Set CHILD->noerror if the COMMANDS_NOERROR bit is set in FLAGS. Set the COMMANDS_SILENT bit in FLAGS for a @ prefix. * remake.c (update_goal_chain): Set G->file to its prev after checking for G being finished, since that check needs to examine G->file. * configure.in (union wait check) [HAVE_WAITPID]: Try using waitpid with a `union wait' STATUS arg. If waitpid and union wait don't work together, we should not use union wait. * Version 3.63.2. * remake.c (update_goal_chain): When G->file->updated, move G->file to its prev. We aren't finished until G->file is nil. Thu Feb 4 12:53:04 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (starting_directory): New global variable. (main): Set it to cwd after doing -Cs. (log_working_directory): Use it, rather than computing each time. * make.h: Declare it. * compatMakefile (SHELL): Define to /bin/sh for losing Unix makes. * main.c (decode_env_switches): Allocate (1 + LEN + 1) words for ARGV, rather than LEN words plus one byte. Wed Feb 3 18:13:52 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile ($(bindir)/$(instname)): Put - before install_setgid command line, so its failure won't be an error. (infodir): New variable. (install): Depend on $(infodir)/$(instname).info. ($(infodir)/$(instname).info): New target. * read.c (read_makefile): If FILENAMES is nil when we see a line starting with a tab, don't treat it as a command. Just fall through, rather than giving an error. * read.c (read_makefile): If the NO_TARGETS flag is set when we see a command line, don't clear it before continuing. We want subsequent command lines to be ignored as well. * job.c (new_job): Before expanding each command line, collapse backslash-newline combinations that are inside var or fn references. Mon Feb 1 16:00:13 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (exec_prefix): Default to $(prefix), not /usr/local. * compatMakefile (make.info): Pass -I$(srcdir) to makeinfo. * job.c [POSIX] (unblock_sigs): Made global. [!POSIX] (unblock_sigs): Move defns to job.h. * job.h [POSIX] (unblock_sigs): Declare. Sun Jan 31 19:11:05 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * read.c (read_makefile): In vpath parsing, after finding the pattern token, take entire rest of line as the search path, not just the next token. * compatMakefile (remote.o): Depend on remote-*.c. Thu Jan 28 16:40:29 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * commands.c (set_file_variables): Don't define any F or D versions. * variable.c (define_automatic_variables): Define them here as recursively-expanded variables that use the dir and notdir funcs. * variable.c (target_environment): In v_default case, don't export o_default or o_automatic variables. * configure.in (union wait check): Remove ` and ' inside C code; they confuse the shell script. Mon Jan 25 13:10:42 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.63.1. * vpath.c (construct_vpath_list): When skipping further processing of an elt that is ".", don't also skip the code that pushes P past the next separator. * compatMakefile (distclean): Don't remove make-*. * configure.in (HAVE_UNION_WAIT): Try to use WEXITSTATUS if it's defined. If one cannot use WEXITSTATUS with a `union wait' argument, we don't want to believe the system has `union wait' at all. * remake.c (update_file): Do nothing to print "up to date" msgs. (update_goal_chain): Do it here instead. Use the `changed' flag of each goal's `struct dep' to keep track of whether files_remade (now commands_started) changed around a call to update_file for that goal. When a goal is finished, and its file's update_status is zero (i.e., success or nothing done), test the `changed' flag and give an "up to date" msg iff it is clear. * make.h (files_remade): Renamed to commands_started. * remake.c: Changed defn. (update_goal_chain): Changed uses. * job.c (start_job_command): Increment commands_started here. (reap_children): Not here. * remake.c (update_goal_chain): Don't do anything with files' `prev' members. update_file now completely handles this. * variable.c (target_environment): Don't expand recursive variables if they came from the environment. * main.c (define_makeflags): For flags with omitted optional args, store {"", 0} with ADD_FLAG. When constructing FLAGSTRING, a flag so stored cannot have more flags appended to the same word. Fri Jan 22 14:46:16 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (print_variable_set): In vars/bucket calculation, don't spuriously multiply by 100. * Version 3.63. * job.c [!HAVE_UNION_WAIT] (WTERMSIG, WCOREDUMP, WEXITSTATUS): Don't define if already defined. * remake.c (update_file): Don't keep track of the command_state before calling update_file_1. Remove local variable COMMANDS_FINISHED, and don't test it to decide to print the "is up to date" msg. Testing for files_remade having changed should always be sufficient. The old method lost when we are called in the goal chain run on a makefile, because the makefile's command_state is already `cs_finished' from the makefile chain run. * misc.c [HAVE_SETRE[GU]ID]: Test these to decl setre[gu]id. * configure.in: Rewrote wait checking. Use AC_HAVE_HEADERS to check for . Use AC_HAVE_FUNCS to check for waitpid and wait3. Use a compile check to test just for `union wait'. * job.c: Rewrote conditionals accordingly. [HAVE_WAITPID]: Test this only to define WAIT_NOHANG. [HAVE_WAIT3]: Likewise. [HAVE_UNION_WAIT]: Test this to define WAIT_T and W*. * configure.in: Set CFLAGS and LDFLAGS before all checks. * dir.c: Add static forward decls of {open,read}_dirstream. Thu Jan 21 17:18:00 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.31. * job.c [NGROUPS_MAX && NGROUPS_MAX==0]: #undef NGROUPS_MAX. * compatMakefile (CFLAGS, LDFLAGS): Set to @CFLAGS@/@LDFLAGS@. * build.template (CFLAGS, LDFLAGS): Same here. * configure.in: AC_SUBST(CFLAGS) and LDFLAGS. Set them to -g if not defined in the environment. * remake.c (library_search): Use LIBNAME consistently, setting it only once, to be the passed name sans `-l'. Pass new var FILE to be modified by vpath_search. Mon Jan 18 14:53:54 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.30. * job.c (start_waiting_jobs): Return when job_slots_used is equal to job_slots. * configure.in: Add AC_CONST for the sake of getopt. * read.c (read_makefile): Continue after parsing `override' directive, rather than falling through to lossage. Check for EOL or blank after "override define". * compatMakefile (.c.o, remote.o): Put $(CFLAGS) after other switches. Fri Jan 15 12:52:52 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.29. * main.c (define_makeflags): After writing everything into FLAGSTRING, only back up two chars if [-1] is a dash, meaning we just wrote " -". Always terminate the string at *P. * remake.c (library_search): When constructing names in std dirs, use &(*LIB)[2] for the stem, not LIBNAME (which points at the buffer we are writing into!). Thu Jan 14 13:50:06 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Set IN_IGNORED_DEFINE for "override define" when IGNORING is true. * compatMakefile (distclean): Remove config.status and build.sh. Wed Jan 13 16:01:12 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.28. * misc.c (xmalloc, xrealloc): Cast result of malloc/realloc to (char *). * arscan.c (ar_scan) [AIAMAG]: Cast read arg to (char *). * variable.c (define_automatic_variables): Override SHELL value for origin o_env_override as well as o_env. * GNUmakefile (build.sh.in): Don't replace %globobjs%. Instead, add the names of the glob objects (w/subdir) to %objs%. * build.template (globobjs): Removed. Take basename of $objs before linking. Tue Jan 12 12:31:06 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.27. * configure.in (AC_OUTPUT): Also edit build.sh. * build.template: New file. * GNUmakefile (build.sh.in): New rule to create it from build.template. (make-$(version).tar.Z): Depend on build.sh.in. * main.c (die): Call print_data_base if -p. (main): Don't call it here. * compatMakefile (defines): Add @DEFS@. configure should turn this into -DHAVE_CONFIG_H. Mon Jan 11 14:39:23 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.26. * misc.c (init_access): Surround with #ifdef GETLOADAVG_PRIVILEGED. ({make,user,child}_access) [! GETLOADAVG_PRIVILEGED]: Make no-op. * compatMakefile (install_setgid): New var, set by configure. (install): Install setgid $(group) only if $(install_setgid) is true. Fri Jan 8 15:31:55 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (load_too_high): If getloadavg fails with errno==0, give a message saying that load limits are not supported. * vpath.c (construct_vpath_list): Rewrote path deletion code to not try to use PATH's next link after freeing PATH. * main.c (define_makeflags): Rewritten; now handles string-valued option, and has no arbitrary limits. (switches): Set `toenv' flag for -I and -v. * main.c (decode_env_switches): Cast return value of alloca to char *. * misc.c (child_access) [HAVE_SETREUID, HAVE_SETREGID]: Use setre[gu]id in place of set[gu]id. Wed Jan 6 15:06:12 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (main): Define MAKEOVERRIDES, MAKE, and MAKE_COMMAND with origin o_default. * make.h [POSIX]: Don't test this to use ANSI_STRING. Testing STDC_HEADERS should be sufficient. * job.h: Declare start_waiting_jobs. * read.c (read_makefile): Add missing parens in if stmt that find conditional directives. * main.c (main): Declare init_dir. * implicit.c (pattern_search): Always use two % specs in a DEBUGP2, and always pass two non-nil args. Cast field width args to int. Add missing parens in !RULE->subdir if stmt. * function.c (expand_function, patsubst_expand): Add parens around assignments inside `while' stmts. * commands.c (print_commands): Cast field width args to int. * read.c (do_define): Cast return value of alloca to (char *). * main.c (init_switches): New function, broken out of decode_switches. (decode_switches): Take new arg ENV. If set, ignore non-option args; print no error msgs; ignore options with clear `env' flags. (decode_env_switches): Rewritten to chop envar value into words and pass them to decode_switches. (switches): Set `env' flag for -I and -v. * dir.c (init_dir): Cast free to __glob_closedir_hook's type. Tue Jan 5 14:52:15 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.25. * job.c [HAVE_SYS_WAIT || !USG]: Don't #include and . interacts badly with , and we don't need these anyway. * configure.in (AC_HAVE_FUNCS): Check for setre[gu]id. * misc.c ({user,make}_access): Test #ifndef HAVE_SETRE[GU]ID, not #ifdef POSIX || USG. SunOS 4.1 is supposedly POSIX.1 compliant, but its set[gu]id functions aren't; its setre[gu]id functions work. * misc.c ({user,make,child}_access): Give name of caller in error msgs. * job.c (load_too_high): Say "cannot enforce load limit" in error msg. * configure.in: Call AC_PROG_CC. * compatMakefile (CC): Define to @CC@ (autoconf magic). * compatMakefile: Add .NOEXPORT magic target. Mon Jan 4 17:00:03 1993 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (print_version): Updated copyright to include 93. Thu Dec 31 12:26:15 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * make.h [_AIX]: Don't declare alloca. Tue Dec 29 13:45:13 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.24. * compatMakefile (objs): Add signame.o. (srcs): Add signame.[ch]. * compatMakefile (srcs): Add config.h.in. (remote.o): Add -I. before -I$(srcdir). Mon Dec 28 15:51:26 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.23. * read.c (readline): Fatal when LEN==0, indicating a line starting with a NUL. (readline): Take new arg LINENO, for use in error msg. (read_makefile, do_define): Pass it. * compatMakefile (glob/libglob.a): Pass -DHAVE_CONFIG_H in CPPFLAGS. (.c.o): Add -I. before -I$(srcdir). Wed Dec 23 12:12:04 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Accept and ignore a rule with no targets. * compatMakefile (ALLOCA_SRC): New variable. (srcs): Include its value. * read.c (struct conditional): Renamed member `max_ignoring' to `allocated'; added new member `seen_else'. (conditional_line): Initialize seen_else flag when starting an `if...'; set it when we see an `else'; fatal if set when we see `else'. (read_makefile): Fatal "missing `endif'" if there are any pending conditionals, not just if we are still ignoring. Tue Dec 22 15:36:28 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (manext): Set to 1, not l. ($(mandir)/$(instname).$(manext)): Use $(srcdir) for make.man in cmds. * file.c (file_hash_enter): Don't call uniquize_deps here. * read.c (record_files): Likewise. * implicit.c (pattern_search): Likewise. * commands.c (set_file_variables): Call it only here. * default.c (default_variables) [__convex__]: FC=fc. * variable.c (target_environment): Expand the values of recursively expanded variables when putting them into the environment. * expand.c (recursively_expand): Made global. * make.h (recursively_expand): Declare it. * remake.c (check_dep): Set FILE->command_state to cs_deps_running when a dep's command_state is cs_running or cs_deps_running. * read.c (read_makefile): Changed error msg for spurious cmds to not say "first target". Sun Dec 20 17:56:09 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * configure.in: Do AC_CONFIG_HEADER right after AC_INIT. * make.h (HAVE_CONFIG_H): #include "config.h", then #define this. * compatMakefile (config.h, configure, config.h.in): New rules. (defines): Removed @DEFS@. Thu Dec 17 16:11:40 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (realclean): Just depend on distclean; no cmds. (distclean): Do what realclean did before; also remove Makefile and config.h; don't remove configure. (info, dvi): New targets; depend on make.{info,dvi}. (doc): Removed target. (MAKEINFO, TEXI2DVI): New vars. (make.info, make.dvi): Use them instead of explicit cmds. Wed Dec 16 16:25:24 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * configure.in: Added fcntl.h to AC_HAVE_HEADERS. getloadavg cares. Wed Dec 9 15:21:01 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (long_option_aliases): Add --new-file alias for -W. * default.c (default_variables): Change all C++ to CXX and C++FLAGS to CXXFLAGS. * read.c (do_define): Expand the variable name before using it. * main.c (main): Define variable "MAKE_COMMAND" to argv[0]; define "MAKE=$(MAKE_COMMAND) $(MAKEOVERRIDES)" always. * remake.c (library_search): Search for libNAME.a in cwd; look in vpath before looking in standard dirs, not after. Changed order of std dirs to: /lib, /usr/lib, ${prefix}/lib. Mon Nov 23 14:57:34 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * default.c (default_pattern_rules, default_terminal_rules): Added brackets around initializers. * variable.c (try_variable_definition): Don't check for LINE[0]=='\t'. (try_variable_definition): Expand the name before defining the var. * job.c (init_siglist): Removed function. Removed decl of `sys_siglist'. * make.h [! HAVE_SYS_SIGLIST]: #include "signame.h". [HAVE_SYS_SIGLIST && !SYS_SIGLIST_DECLARED]: Declare sys_siglist only under these conditions. * main.c (main): Don't declare init_siglist. (main) [! HAVE_SYS_SIGLIST]: Call signame_init instead of init_siglist. Wed Nov 18 14:52:51 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (record_files): Don't try to append to FIRSTDEPS if it's nil; instead just set it to MOREDEPS. Mon Nov 16 17:49:17 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * vpath.c (construct_vpath_list): Initialize P to DIRPATH before loop that sets MAXELEM. Fri Nov 13 18:23:18 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.22. Thu Nov 12 15:45:31 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (start_job_command): Under -n, increment files_remade after processing (i.e., printing) all command lines. Tue Nov 10 15:33:53 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * read.c (record_files): Append new deps if this rule has no commands; prepend them to existing deps if this rule has no commands. * dir.c (open_dirstream): Return nil if DIR->contents->files is nil. * read.c (parse_file_seq): Removed last arg STRIP. Always strip `./'s. (read_makefile): Changed callers. * function.c (string_glob): Likewise. * rule.c (install_pattern_rule): Likewise. Mon Nov 9 17:50:16 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (files_remade): Made global. (notice_finished_file): Don't increment files_remade here; this function gets called in many situations where no remaking was in fact done. * job.c (reap_children): Do it here instead, when we know that actual commands have been run for the file. * make.h (files_remade): Declare it. Thu Nov 5 18:26:10 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * vpath.c (construct_vpath_list): Allow blanks as well as colons to separate elts in the search path. * read.c (read_makefile): Don't fatal on extra tokens in `vpath'. The search path can contain spaces now. Tue Nov 3 20:44:32 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (check): New target; no-op. * file.c (file_hash_enter): Mod OLDHASH by FILE_BUCKETS after testing for OLDHASH==0 but before using the value. (rename_file): Don't mod OLDHASH by FILE_BUCKETS before passing it to file_hash_enter. * file.c (rename_file): Notice when OLDFILE->cmds came from default.c, and don't try to print ->filename in that case. Sun Oct 25 01:48:23 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (update_file): Don't process F->also_make here. (notice_finished_file): Don't process FILE->also_make if no attempt to update FILE was actually made. Fixed to call f_mtime directly to refresh their modtimes. Sat Oct 24 22:08:59 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (find_percent): Don't increment P again after skipping an escaped %. * expand.c (variable_expand): In call to patsubst_expand, don't find `%'s ourselves; let that function do it. * read.c (read_makefile: record_waiting_files): Don't call record_files if FILENAMES is nil. (read_makefile): All alternatives in the parsing, except for rule lines, fall through to the end of the loop. At the end of the loop, do record_waiting_files so we notice later spurious cmds. Fri Oct 23 15:57:37 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (define_automatic_variables): Free old value of SHELL before replacing it. Thu Oct 15 18:57:56 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (.c.o): Add -I$(srcdir)/glob to flags. * dir.c (open_dirstream): Cast return value to __ptr_t. * default.c (default_variables: "GET") [_IBMR2]: Use USG defn. * make.h (MAXPATHLEN): Moved out of #ifndef POSIX. (GET_PATH_MAX): Moved from #ifdef POSIX to #ifdef PATH_MAX #else. Define as (get_path_max ()). [! PATH_MAX] (NEED_GET_PATH_MAX): Define. [! PATH_MAX] (get_path_max): Declare fn. * misc.c [NEED_GET_PATH_MAX] (get_path_max): New function. Mon Oct 12 13:34:45 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.21. * job.c (sys_siglist): Only declare #ifndef SYS_SIGLIST_DECLARED. * make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define SYS_SIGLIST_DECLARED. * dir.c (file_impossible): When initializing DIR->contents, set DIR->contents->dirstream to nil. * compatMakefile (GLOB): Define new variable. (objs): Use it, rather than glob/libglob.a explicitly. * read.c (parse_file_seq): When stripping "./", handle cases like ".///foo" and "./////". * file.c (lookup_file, enter_file): Likewise. Sun Oct 11 17:00:35 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * dir.c (struct dirstream, {open,read}_dirstream): New data type and functions to read a directory sequentially. (init_dir): New function to hook it into glob. * main.c (main): Call init_dir. * compatMakefile (objs): Added glob/libglob.a. * configure.in: Remove code to test for glob. Fri Oct 9 12:08:30 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (record_files): Generalized test for NAME pointing somewhere into F->name. * variable.c (define_variable_in_set): Free old value when replacing. * read.c (do_define): Free the linebuffer before returning. (record_files): When clearing .SUFFIXES deps, free their data. (multi_glob): Free OLD and its data when replacing it with results of glob run. * commands.c (set_file_variables): Use alloca in place of xmalloc for temp space for $^, $?, et al. * dir.c (struct directory): New member `contents' replaces `files' and `dirstream'. (struct directory_contents): New type. (directories_contents): New hash table. (dir_struct_file_exists_p): Take a struct directory_contents. (dir_file_exists_p): Pass it the `contents' member of the dir found. (dir_struct_file_exists_p): Renamed to dir_contents_file_exists_p; made static. Return 0 if DIR is nil (meaning it couldn't be stat'd). (dir_file_exists_p, find_directory): Change all callers. (file_impossible): Use DIR->contents, initializing it if nil. (print_dir_data_base): Use DIR->contents, and print out device and inode numbers with each directory. * Changes for performance win from John Gilmore : * dir.c (DIRECTORY_BUCKETS): Increase to 199. (DIRFILE_BUCKETS): Decrease to 107. (find_directory): Allocate and zero a multiple of sizeof (struct dirfile *), not of sizeof (struct dirfile). (dir_struct_file_exists_p): New function, nearly all code from dir_file_exists_p. (dir_file_exists_p): Just call find_directory+dir_struct_file_exists_p. * vpath.c (selective_vpath_search): Remove redundant dir_file_exists_p call. * configure.in: Comment out glob check; always use our code. Fri Oct 2 19:41:20 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * make.h [! HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define HAVE_SYS_SIGLIST; after doing #define sys_siglist _sys_siglist, we do have it. Wed Sep 30 19:21:01 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (main): Don't do -w automatically if -s. Tue Sep 29 21:07:55 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (printed_version): Move variable inside print_version. (print_version): Return immediately if printed_version is set. (die): Don't test printed_version here. (decode_switches): Under -v, do print_version before giving usage. (DESCRIPTION_COLUMN): New macro. (decode_switches): Use it when printing the usage message. Leave at least two spaces between options and their descriptions. Fri Sep 25 13:12:42 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.20. Wed Sep 16 16:15:22 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * read.c (read_makefile): Save errno value from trying to open FILENAME, and restore it before erring; otherwise we get the errno value from the last elt of the search path. Tue Sep 15 15:12:47 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (long_option_aliases): Add --stop for -S. * read.c (word1eq): Do strncmp before dereferencing someplace that may be out in space. Wed Sep 9 15:50:41 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (notice_finished_file): If all the command lines were recursive, don't do the touching. * job.c (start_job_command): Don't check for + here. * commands.c (chop_commands): Do it here instead. * default.c (default_terminal_rules): Prepend + to cmds for RCS. Wed Sep 2 17:53:08 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (objs): Include $(ALLOCA). * make.h [CRAY]: Move #define signal bsdsignal to before #includes. Thu Aug 27 17:45:43 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * read.c (default_include_directories): Add INCLUDEDIR first. * compatMakefile (includedir): Define. (defines): Add -D for INCLUDEDIR="$(includedir)". * read.c (read_makefile): Grok multiple files in `include'; globbing too. * remake.c (library_search): New function. (library_file_mtime): Remove function. (f_mtime): Use library_search instead of library_file_mtime. * compatMakefile (libdir): Define. (defines): Add -D for LIBDIR="$(libdir)". * make.texinfo (Libraries/Search): Document change. * file.c (rename_file): Fix file_hash_enter call with missing arg. Wed Aug 26 17:10:46 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.19. * main.c (main): Set command_state to cs_finished for temp files made for stdin makefiles. * main.c (decode_switches): Don't tell getopt to return non-option args in order. Ignore an argument of `-'. Thu Aug 20 13:36:04 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c (start_job_command): If (touch_flag && !RECURSIVE), ignore the command line and go to the next. (notice_finished_file): Under -t, touch FILE. * remake.c (remake_file): Don't touch it here. Wed Aug 19 16:06:09 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * function.c (pattern_matches): Use temporary for strlen (WORD) instead of two function calls. * compatMakefile (LOAD_AVG): Remove variable and comments. Tue Aug 18 14:58:58 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * make.texinfo (Running): Node renamed to `make Invocation'. Fri Aug 14 12:27:10 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * arscan.c (ar_name_equal): Don't compare [MAX-3..MAX] if NAMELEN != MEMLEN. Thu Aug 13 17:50:09 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.18. * main.c: Don't #include ; make.h already does. Mon Aug 10 17:03:01 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * implicit.c (pattern_search): Fixed copying of suffix when building also_make elts. * function.c (expand_function: `shell'): Make sure BUFFER is null-terminated before replacing newlines. * compatMakefile (mandir): Use man$(manext), not always manl. Sun Aug 2 01:42:50 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * rule.c (new_pattern_rule): Not static. * rule.h: Declare it. * file.c (file_hash_enter): New function, most code from rename_file. (rename_file): Call it. * file.h (file_hash_enter): Declare it. * dep.h: Doc fix. Thu Jul 30 15:40:48 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (decode_switches): Handle usage_and_exit when building long options vector. * default.c (default_terminal_rules): Make RCS rules use $(CHECKOUT,v). (default_variables): Define CHECKOUT,v (hairy). * make.h [!HAVE_SYS_SIGLIST && HAVE__SYS_SIGLIST]: #define sys_siglist to _sys_siglist. Sun Jul 26 16:56:32 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * NEWS: Add header and tail copyright info like Emacs NEWS. * make.h [ANSI_STRING]: Don't #define index, rindex, bcmp, bzero, bcopy if already #define'd. [STDC_HEADERS] (qsort, abort, exit): Declare here. [! __GNU_LIBRARY__ && !POSIX]: Not here. * make.h [_AIX]: #pragma alloca first thing. * job.c (start_waiting_job): Set the command_state to cs_running when we queue a job on waiting_jobs. Fri Jul 24 02:16:28 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.c (define_automatic_variables): Use "" instead of nil for empty value. Thu Jul 23 22:31:18 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.17. * main.c (struct command_switch.type): Add alternative usage_and_exit. (command_switches): Add -h/--help. Thu Jul 16 14:27:50 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * GNUmakefile (make-$(version).tar.Z): Include NEWS, not CHANGES. * README.template: Mention NEWS. * CHANGES: Renamed to NEWS. * main.c [! STDC_HEADERS] [sun]: Don't declare exit. Tue Jul 14 18:48:41 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (main): Set -o files' command_states to cs_finished. * rule.c (count_implicit_rule_limits): Decrement num_pattern_rules when tossing a rule. * main.c (main): Use alloca only in simple local var assignment, for braindead SGI compiler. * rule.c (print_rule_data_base): Barf if num_pattern_rules is inconsistent with the number computed when listing them. Mon Jul 13 17:51:53 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * commands.c (set_file_variables): For $? and $^ elts that are archive member refs, use member name only. Fri Jul 10 00:05:04 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * variable.h (struct variable.export): Add new alternative v_ifset. * variable.c (target_environment): Check for it. (define_automatic_variables): Set it for MAKEFILES. Thu Jul 9 21:24:28 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (objs): Remove getloadavg.o; $(extras) gets it. (remote.o): Use $(srcdir)/remote.c, not $remote.c<. (distclean, mostlyclean): New targets. Tue Jul 7 19:12:49 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.16. * compatMakefile (config.status): Remove rule. * job.c (start_waiting_job): Free C after using C->file, not before. Sat Jul 4 20:51:49 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * commands.c, job.c, main.c, make.h, remote-cstms.c: Use #ifdef HAVE_* instead of #ifndef *_MISSING. * configure.in: Use AC_HAVE_FUNCS instead of AC_MISSING_FUNCS (gone). Thu Jul 2 18:47:52 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * main.c (main): makelevel>0 or -C implies -w. Tue Jun 30 20:50:17 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * file.c, job.c, function.c: Don't #include . make.h: Do it here instead. * arscan.c (ar_member_touch): Don't declare errno. Thu Jun 25 17:06:55 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * GNUmakefile (make-$(version).tar.Z): Depend on INSTALL, configure.in. * remake.c (update_file): If commands or deps are running after update_file_1 returns, break out of the :: rule (->prev) loop and just return. * job.c (job_next_command): New function; code from start_job. (start_job_command): Renamed from start_job. Call job_next_command and recurse for empty command lines and -n. (start_waiting_job): Call start_job_command, not start_job. (new_job): Call job_next_command to prime the child structure, and then call start_waiting_job. (reap_children): Use job_next_command and start_job_command. (start_waiting_job): Call start_remote_job_p here, and store its result in C->remote. If zero, check the load average and maybe put C on waiting_jobs. (start_job_command): Test CHILD->remote rather than calling start_remote_job_p. Don't do load avg checking at all here. * main.c (main): Don't handle SIGILL, SIGIOT, SIGEMT, SIGBUS, SIGSEGV, SIGFPE or SIGTRAP. * compatMakefile (glob/libglob.a): Don't pass srcdir to sub-make. configure will set it in glob/Makefile. Wed Jun 24 19:40:34 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * dir.c [DIRENT] (direct): Don't define to dirent. [! DIRENT] (direct): Define to dirent. (dir_file_exists_p): Use struct dirent instead of struct direct. * make.h (getcwd): No space between macro and ( for args! * job.c (start_job): Don't put the job on waiting_jobs if job_slots_used==0. * make.texinfo (Missing): Shortened title. Tue Jun 23 18:42:21 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * file.c (remove_intermediates): Print "rm" commands under -n. Mon Jun 22 16:20:02 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.15. Fri Jun 19 16:20:26 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * arscan.c [M_UNIX]: #undef M_XENIX. Wed Jun 17 17:59:28 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * default.c (default_terminal_rules): Put @ prefix on RCS cmds. Tue Jun 16 19:24:17 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile (getloadavg.o): Removed special rule. (CFLAGS): Don't include $(defines). (.c.o): Define suffix rule. (glob/libglob.a): Pass CPPFLAGS=$(defines) to submake. (GETOPT_SRC, srcs, tagsrcs): Prefix files with $(srcdir)/. * arscan.c (ar_name_equal): Moved local vars inside #if'd block. * make.h (max): Removed. * expand.c (variable_buffer_output): Don't use it. * compatMakefile (INSTALL): Define. (Makefile): New rule to make from Makefile.in. (srcdir): Define. (VPATH): Define. (getloadavg.o, remote.o): Use autoconf $foo< hack. * commands.c (fatal_error_signal): Removed return. Mon Jun 15 17:42:51 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.14. * make.texinfo (Summary): New node. (Special Targets): Mention .EXPORT_ALL_VARIABLES here. * variable.c (max): Moved to make.h. * compatMakefile (objs, srcs): Added ar & arscan. * job.c (start_waiting_job): New function, 2nd half of new_job. (new_job): Call it. (start_waiting_jobs): New function. * remake.c (update_goal_chain): Call start_waiting_jobs at the top of the main loop. * compatMakefile (objs, srcs): Removed load, added getloadavg. Fri Jun 12 19:33:16 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c (load_too_high): New function. Uses getloadavg. (waiting_jobs): New variable. (start_job): Don't call wait_to_start_job. Instead, if load_too_high returns nonzero, add the child to the `waiting_jobs' chain and return without starting the job. Thu Jun 11 00:05:28 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * expand.c (variable_buffer_output): Made global again. * variable.h: And declare it. * arscan.c (PORTAR): Define for all systems if PORT5AR is not defined. (AR_NAMELEN, AR_TRAILING_SLASH): Removed. (ar_scan): Don't use it. Don't #ifdef AR_TRAILING_SLASH; just look for a slash in the archive at run time. (ar_name_equal): Rewrote .o hacking to not use AR_NAMELEN, and to cope with trailing-slash and non-trailing-slash archives. * main.c (main) [! SETVBUF_REVERSED]: Test this instead of USGr3 et al. [SETVBUF_REVERSED]: Always allocate a buffer ourselves. * load.c (load_average) [sgi]: Use sysmp call. * compatMakefile (INSTALL_DATA, INSTALL_PROGRAM): Define. ($(bindir)/$(instname), $(mandir)/make.$(manext)): Use them. * make.h [HAVE_VFORK_H]: #include . (vfork, VFORK_NAME): Don't define. * job.c (start_job): Use "vfork" in place of VFORK_NAME. * make.h [HAVE_LIMITS_H, HAVE_SYS_PARAM_H]: If #define'd, #include the each file. Rearranged PATH_MAX hacking. * job.c: Rearranged NGROUPS_MAX hacking. * remake.c (fstat, time): Don't declare. * compatMakefile (defines): Value is @DEFS@. (LOADLIBES): Value is @LIBS@. (extras): Value is @LIBOBJS@. (ARCHIVES, ARCHIVES_SRC, ALLOCASRC): Removed. * arscan.c, ar.c: Surround body with #ifndef NO_ARCHIVES. * misc.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl get*id. * make.h [GETCWD_MISSING]: Test instead of !USG && !POSIX et al. (getcwd): Just declare if present. If not, declare as a macro using getwd, and declare getwd. [PATH_MAX] (GET_PATH_MAX): #define to PATH_MAX. * main.c (main, log_working_directory): Use getcwd instead of getwd. * main.c (main) [SETLINEBUF_MISSING]: Test this instead of USG. * make.h (SIGHANDLER, SIGNAL): Removed. (RETSIGTYPE): Define if not #define'd. * main.c (main): Use signal in place of SIGNAL. * main.c [SYS_SIGLIST_MISSING]: Test instead of USG. * job.c (search_path) [GETGROUPS_MISSING]: Test instead of USG. [HAVE_UNISTD_H]: Test instead of POSIX to not decl getgroups. * main.c [! HAVE_UNISTD_H]: Test instead of !POSIX to decl chdir. [! STDC_HEADERS]: Test instead of !POSIX to decl exit & atof. * job.c (child_handler), commands.c (fatal_error_signal): Return RETSIGTYPE instead of int. * main.c (main): Declare fatal_error_signal and child_handler here to return RETSIGTYPE; removed top-level decl of former. * commands.c (fatal_error_signal), job.c (unblock_sigs, start_job), main.c [SIGSETMASK_MISSING]: Test this instead of USG. Wed Jun 10 22:06:13 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c [HAVE_WAITPID]: Test this instead of USG. [! HAVE_UNISTD_H]: Test this instead of !POSIX to declare misc fns. (GID_T): Don't #define. (search_path): Use gid_t instead of GID_T. [GETDTABLESIZE_MISSING, SYS_SIGLIST_MISSING, DUP2_MISSING]: Test these individually instead of USG for all. * make.h (ctime): Don't declare. #include time.h instead. [HAVE_UNISTD_H]: #include and #define POSIX #ifdef _POSIX_VERSION. * dir.c [__GNU_LIBRARY__] (D_NAMLEN): Define to use d_namlen member. * make.h [NEED_MEMORY_H]: Only include memory.h #ifdef this. * arscan.c: Removed #ifdef mess about string.h et al. Just #include make.h instead. * make.h (fstat, atol): Declare. * commands.c (fatal_error_signal): Don't use sigmask to check for propagated signals; use ||s instead. (PROPAGATED_SIGNAL_MASK): Removed. (fatal_error_signal) [POSIX]: Use sigprocmask in place of sigsetmask. * variable.c (variable_buffer, variable_buffer_length, initialize_variable_output, variable_output): Moved to expand.c; made all static. (struct output_state, save_variable_output, restore_variable_output): Removed. * expand.c (initialize_variable_output): Put a NUL at the beginning of the new buffer after allocating it. (allocated_variable_expand_for_file): Don't use {save,restore}_variable_output. Do it by hand instead, keeping state on the stack instead of malloc'ing it. (allocated_variable_expand): Removed. * variable.h (allocated_variable_expand): Define here as macro. (variable_buffer_output, initialize_variable_output, save_variable_output, restore_variable_output): Removed decls. * read.c (conditional_line): For an if cmd, if any elt of the conditionals stack is ignoring, just push a new level that ignores and return 1; don't evaluate the condition. Thu Jun 4 21:01:20 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (main): Put #ifdef's around frobbing SIGSYS and SIGBUS. * job.c (getdtablesize): Don't declare or #define if already #define'd. Wed Jun 3 23:42:36 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * file.c (snap_deps): If `.EXPORT_ALL_VARIABLES' is a target, set export_all_variables. * make.texinfo (Variables/Recursion): Document .EXPORT_ALL_VARIABLES. Tue Jun 2 21:08:35 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.13. * commands.c (set_file_variables): Calculate length for ^D and ?D individually, making sure to give them at least enough space for "./". * make.h [CRAY]: #define signal to bsdsignal. * default.c (default_variables) [CRAY]: Define PC, SEGLDR, CF77PPFLAGS, CF77PP, CFT, CF, and FC. * arscan.c (AR_HDR_SIZE): Define to sizeof (struct ar_hdr), if it wasn't defined by . Thu May 28 00:56:53 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.12. Tue May 26 01:26:30 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * rule.c (new_pattern_rule): Initialize LASTRULE to nil, not pattern_rules. Mon May 25 19:02:15 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (decode_switches): Initialize all the long_option elt members. Thu May 21 16:34:24 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * make.texinfo (Text Functions): Correct filter-out description. Tue May 19 20:50:01 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * compatMakefile (realclean): Don't remove backup files. * main.c (decode_switches): Allocate ARGC+1 elts in `other_args'. Sun May 17 16:38:48 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.62.11. Thu May 14 16:42:33 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * job.c (reap_children): Don't die if wait returns EINTR. Wed May 13 18:28:25 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c (reap_children): Always run the next command for a successful target. If we are going to die, we don't want to leave the target partially made. Tue May 12 00:39:19 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): After loop, if we only have one word, check it for being a shell command. * main.c (decode_switches): Allocate ARGC slots in other_args to begin with, so we never need to worry about growing it. If we get a non-option arg and POSIXLY_CORRECT is in the environment, break out of the loop. After the loop, add all remaining args to other_args list. * main.c (decode_switches): For positive_int and floating switches when optarg is nil, use next arg if it looks right (start with a digit, or maybe decimal point for floating). * variable.c (define_automatic_variables): Always set SHELL to default if it comes from the environment. Set its export bit. * make.texinfo (Environment): Document change. Mon May 11 00:32:46 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.62.10. * compatMakefile (tags, TAGS): Use vars for cmds. (ETAGS, CTAGS): Define. * main.c (decode_switches): If a switches elt has a nil long_name, make the long option name elt be "". Fixed loop to not ignore all the options. * make.texinfo (Option Summary): Added long options. * main.c (switches): Changed -m's description to "-b". (decode_switches): When printing the usage message, don't print switches whose descriptions start with -. When constructing the list of names for switch -C, search the switches vector for switches whose descriptions are "-C". * main.c (switches): Call -S --no-keep-going, not --dont-keep-going. Call -I --include-dir, not --include-path. (long_option_aliases): Added --new == -W, --assume-new == -W, --assume-old == -o, --max-load == -l, --dry-run == -n, --recon == -n, --makefile == -f. * main.c (switches): Removed bogus "silent" elt. (long_option_aliases): Define new var. (decode_switches): Add long_option_aliases onto the end of the long options vector created for getopt_long. Look through long_option_aliases for extra names to list in usage message. Sat May 9 00:21:05 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (log_working_directory): Fixed to properly not print the leaving message when we haven't printed the entering message. Fri May 8 21:55:35 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * main.c (struct command_switch): Added elts `long_name', `description', and `argdesc'. (switches): Added initializers for new members. (decode_switches): Rewritten to use getopt_long. * compatMakefile (GETOPT, GETOPT_SRC): Define. (objs, srcs): Include them. * job.c (child_died): Renamed to dead_children; made static. (child_handler): Increment dead_children instead of setting child_died. (reap_children): Decrement dead_children instead of clearing child_died. The point of all this is to avoid printing "waiting for unfinished jobs" when we don't actually need to block. This happened when multiple SIGCHLDs before reap_children was called. * job.c (reap_children): If ERR is set, so we don't call start_job on the child being reaped, instead set its command_state to cs_finished. (reap_children, child_handler, new_job): I added several debugging printf's while fixing this. I left them in if (debug_flag) because they may be useful for debugging this stuff again. Wed May 6 22:02:37 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * read.c (read_makefile): v_export is not 1. Mon May 4 17:27:37 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.9. * variable.c (export_all_variables): New variable. (target_environment): Export variables whose `export' member is v_default if export_all_variables is set and their names are benign. * variable.h: Declare export_all_variables. * read.c (read_makefile): If export or unexport is given with no args, set or clear export_all_variables, respectively. * variable.c (target_environment): Exclude MAKELEVEL in the loop, so it isn't duplicated when we add it at the end. Sun May 3 17:44:48 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.8. * variable.h (struct variable): Added new member `export'. * variable.c (define_variable_in_set): Initialize it to v_default. (target_environment): Don't check for .NOEXPORT. Export variables whose `export' member is v_default and that would have been exported under .NOEXPORT, and variables whose `export' member is v_export. (try_variable_definition): Return the variable defined. * variable.h (try_variable_definition): Changed decl. * read.c (read_makefile): Recognize `export' and `unexport' directives. Fri May 1 11:39:38 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * main.c (main) [POSIX]: Reversed args to sigaddset. Thu Apr 30 17:33:32 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c [POSIX || !USG] (unblock_sigs): New fn. (start_job): Block signals before forking. (new_job): Unblock signals after putting the new child on the chain. * main.c (main) [POSIX]: Use sigset_t fatal_signal_set instead of int fatal_signal_mask. * load.c [sgi] (LDAV_CVT): Define. Wed Apr 29 17:15:59 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.62.7. * load.c (load_average) [sgi]: Clear the high bit of the address from the symbol table before looking it up in kmem. * misc.c (fatal, makefile_fatal): Put *** in fatal error messages. (remake_file): No longer needed in message here. * main.c (die): Call reap_children with BLOCK==1. Tue Apr 28 20:44:35 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * rule.c (freerule): Don't set LASTRULE->next if LASTRULE is nil. Sun Apr 26 15:09:51 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * rule.c (count_implicit_rule_limits): Initialize LASTRULE to nil, not to head of chain. Extract next ptr before we might do freerule, and use that for next iteration. (freerule): Still do next ptr frobbing if LASTRULE is nil. Tue Apr 21 03:16:29 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * job.c (child_error): Removed extra %s from error msg format. * Version 3.62.6. * job.c (reap_children): Don't start later commands in a sequence if ERR is nonzero. * job.c (new_job): Always call reap_children with BLOCK==0 first thing. * job.c (reap_children): New function; work that used to be done in child_handler. (child_died): New global var. (child_handler): Now just sets child_died. (wait_for_children): Removed. (unknown_children_possible, block_signals, unblock_signals, push_signals_blocked_p, pop_signals_blocked_p): Removed. (child_execute_job): Removed call to unblock_signals. (new_job): Removed calls to push_signals_blocked_p and pop_signals_blocked_p. * job.h: Declare reap_children, not wait_for_children. * commands.c (fatal_error_signal), job.c (new_job), load.c [LDAV_BASED] (wait_to_start_job), main.c (die), remake.c (update_goal_chain), function.c (expand_function: `shell'): Changed wait_for_children calls to reap_children. Some needed to be loops to wait for all children to die. * commands.c (fatal_error_signal), main.c (main, log_working_directory), function.c (expand_function): Removed calls to push_signals_blocked_p and pop_signals_blocked_p. * job.h: Removed decls. * job.h: Added copyright notice. Wed Apr 15 02:02:40 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (child_error): No *** for ignored error. Tue Apr 14 18:31:21 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * implicit.c (DEBUGP2): Use do ... while (0) instead of if ... else to avoid compiler warnings. * read.c (parse_file_seq): Don't remove ./ when it is followed by a blank. Mon Apr 13 21:56:15 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h (DEBUGPR): Use do ... while (0) instead of if ... else to avoid compiler warnings. * remake.c (notice_finished_file): Run file_mtime on the also_make files, so vpath_search can happen. * GNUmakefile (tests): Use perl test suite from csa@sw.stratus.com. (alpha-files): Include test suite tar file. Fri Apr 3 00:50:13 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * Version 3.62.5. Wed Apr 1 05:31:18 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * remake.c (update_file, update_file_1): Do check_renamed on elts of dep chains when traversing them. Something unrelated might have renamed one of the files the dep chain points to. * file.c (rename_file): If FILE has been renamed, follow its `renamed' ptr, so we get to the final real FILE. Using the renamed ones loses because they are not in the hash table, so the removal code loops infinitely. * read.c (read_all_makefiles): Clobber null terminator into MAKEFILES expansion, so string passed to read_makefile is properly terminated. Mon Mar 30 20:18:02 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * commands.c (set_file_variables): $* for archive member with explicit cmds is stem of member, not of whole `lib(member)'. Thu Mar 26 15:24:38 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.62.4. Tue Mar 24 05:20:51 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * rule.c (new_pattern_rule): Rules are identical only if all their targets match (regardless of order). Wed Mar 11 13:49:54 1992 Roland McGrath (roland@geech.gnu.ai.mit.edu) * remake.c (remake_file): Changed error "no way to make" to "no rule to make". Fiat Hugh. * make.texinfo (Last Resort): Describe %:: rules and new .DEFAULT behavior. * remake.c (update_file_1): Only use .DEFAULT cmds if FILE is not a target. Tue Mar 10 18:13:13 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * remote-stub.c, remote-cstms.c (start_remote_job): Take new arg, environment to pass to child. * job.c (start_job): Pass it. Mon Mar 9 19:00:11 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * file.c (enter_file): Also strip ./s here, to get command-line target names. * remote-cstms.c: Add comment telling people to leave me alone. * compatMakefile (manpage install): Remove target before copying. Tue Mar 3 18:43:21 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.texinfo (Missing): Renamed to "Incompatibilities and ...". Added paragraph describing $? incompatibility with Unix and POSIX.2. Sun Mar 1 15:50:54 1992 Roland McGrath (roland@nutrimat.gnu.ai.mit.edu) * function.c (expand_function: `shell'): Don't declare fork or pipe. Use vfork instead of fork. Tue Feb 25 22:05:32 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * make.texinfo (Chained Rules): Clarify .PRECIOUS to save intermediate files. * load.c [sun] (LDAV_CVT): Define to divide by FSCALE. Sun Feb 16 02:05:16 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * Version 3.62.3. Sat Feb 15 17:12:20 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * compatMakefile (makeinfo): Use emacs batch-texinfo-format fn. Fri Feb 14 00:11:55 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * read.c (read_makefile): Correctly handle define & endef in ifdefs. * read.c (record_files): Pass arg for %s in error msg. * main.c (main) [__IBMR2, POSIX]: Use correct (a la USGr3) setvbuf call. Wed Feb 12 12:07:39 1992 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * make.texinfo (Libraries/Search): Say it does /usr/local/lib too. Sun Feb 9 23:06:24 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * read.c (read_makefile): Check for extraneous `endef' when ignoring. Thu Feb 6 16:15:48 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * Version 3.62.2. Tue Feb 4 20:04:46 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Correctly ignore whitespace after backslash-NL. Fri Jan 31 18:30:05 1992 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * compatMakefile: Ignore errors from chgrp and chmod when installing. Wed Jan 29 18:13:30 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * main.c (main): When setting MAKELEVEL in the env to re-exec, allocate space so as not to clobber past the end of the old string. * make.h [HAVE_ALLOCA_H]: Include * compatMakefile (defines): Document HAVE_ALLOCA_H. Mon Jan 20 13:40:05 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * make.h [VFORK_MISSING]: Use fork instead. * compatMakefile (defines): Document same. * job.c (construct_command_argv_internal): Don't create an empty arg if backslash-NL is at beginning of word. Sun Jan 19 16:26:53 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * main.c [DGUX]: Call setvbuf as for USGr3. * job.c (construct_command_argv_internal): Notice correctly that backslash-NL is the end of the arg (because it is replaced with a space). Thu Jan 16 18:42:38 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): If SHELL is nil, set it to default_shell before proceeding. * make.h [sgi]: No alloca.h, after all. Wed Jan 15 12:30:04 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * read.c (multi_glob): Cons up the chain of the results of glob from back to front, so it comes out in forward order. * job.c (construct_command_argv_internal): Don't eat char following backslash-NL. Mon Jan 13 19:16:56 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * Version 3.62.1. * default.c (default_variables) [ultrix]: GET=get, like USG. * job.c (construct_command_argv_internal): Remove tabs following backslash-NL combos in the input line, so they don't show up when that line is printed. * read.c (read_makefile): Don't collapse_continuations the line on input; do it on the copy we do remove_comments on. For rule lines, collapse_continuations the line after chopping ";cmds" off the end, so we don't eat conts in the cmds. Give error for ";cmds" with no rule. * job.c (construct_command_argv_internal): Eat backslash-NL combos when constructing the line to recurse on for slow, too. Sat Jan 11 02:20:27 1992 Roland McGrath (roland@albert.gnu.ai.mit.edu) * file.c (enter_file): Don't strip leading `./'s. * read.c (parse_file_seq): Take new arg STRIP; if nonzero, do it here. * default.c (set_default_suffixes), function.c (string_glob), read.c (read_makefile), rule.c (install_pattern_rule): Change callers. * default.c (default_variables) [_IBMR2]: FC=xlf * job.c (construct_command_argv_internal): Turn backslash-NL and following whitespace into a single space, rather than just eating the backslash. * make.texinfo (Copying): @include gpl.texinfo, rather than duplicating its contents. Fri Nov 8 20:06:03 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Make sure not to bother processing an empty line. * Version 3.62.0. * job.c (construct_command_argv_internal): Always recurse for slow; simple case didn't handle finding newlines. Tue Nov 5 18:51:10 1991 Roland McGrath (roland@wookumz.gnu.ai.mit.edu) * job.c (construct_command_argv_internal): Set RESTP properly when slow; don't \ify past a newline. Fri Nov 1 19:34:28 1991 Roland McGrath (roland@churchy.gnu.ai.mit.edu) * make.h [sgi]: #include . See ChangeLog.1, available in the CVS repository at: http://savannah.gnu.org/cvs/?group=make for earlier changes. Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/INSTALL000066400000000000000000000220711317072305000160260ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PREFIX', the package will use PREFIX as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. remake-4.1+dbg1.3~dfsg.1/INSTALL-from-source.md000066400000000000000000000017051317072305000206650ustar00rootroot00000000000000# Prerequisites: Build from sources you need: * a previous version of GNU make * gcc * gettext * GNU Readline * guile version 2.0 Additionally if installing from git you need: * git (duh) * autoconf * automake * autopoint Here is a `apt-get` command you can use to install on Debian-ish systems: ```console $ sudo apt-get install git gcc pkg-config autoconf automake autopoint libreadline-dev make guile-2.0 ``` Here is a `yum` command Redhat/CentOS: ```console $ sudo yum install git gcc pkgconfig autoconf automake readline-devel make guile ``` To build documentation you need: * texinfo Add that to the `apt-get` or `yum` command above. # Updating translation links After running `configure` run: make po-update to pull in the latest translation strings. # Building So the full sequence is: ```console $ cd remake* $ [ ! -f ./configure ] && autoreconf -f -i $ ./configure $ make po-update $ make $ make check ``` remake-4.1+dbg1.3~dfsg.1/Makefile.am000066400000000000000000000213041317072305000170270ustar00rootroot00000000000000# This is a -*-Makefile-*-, or close enough # # Copyright (C) 1997-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . AUTOMAKE_OPTIONS = 1.8 dist-bzip2 silent-rules std-options check-news ACLOCAL_AMFLAGS = -I config transform = s,make,@MAKE_NAME@, MAKE_HOST = @MAKE_HOST@ # Only process if target is MS-Windows if WINDOWSENV MAYBE_W32 = w32 W32INC = -I $(top_srcdir)/w32/include W32LIB = -Lw32 -lw32 endif SUBDIRS = glob config po doc $(MAYBE_W32) unittest bin_PROGRAMS = make include_HEADERS = gnumake.h if USE_CUSTOMS remote = remote-cstms.c else remote = remote-stub.c endif DEBUGGER_SRC = \ debugger/break.c \ debugger/cmd.c \ debugger/fns.c \ debugger/file2line.c \ debugger/msg.c \ debugger/stack.c DEBUGGER_H = \ debugger/break.h \ debugger/cmd.h \ debugger/fns.h \ debugger/msg.h \ debugger/command/break.h \ debugger/command/chdir.h \ debugger/command/comment.h \ debugger/command/continue.h \ debugger/command/delete.h \ debugger/command/down.h \ debugger/command/edit.h \ debugger/command/eval.h \ debugger/command/expand.h \ debugger/command/finish.h \ debugger/command/frame.h \ debugger/command/help.h \ debugger/command/info.h \ debugger/command/list.h \ debugger/command/next.h \ debugger/command/print.h \ debugger/command/pwd.h \ debugger/command/quit.h \ debugger/command/run.h \ debugger/command/set.h \ debugger/command/setq.h \ debugger/command/setqx.h \ debugger/command/shell.h \ debugger/command/show.h \ debugger/command/skip.h \ debugger/command/source.h \ debugger/command/step.h \ debugger/command/target.h \ debugger/command/up.h \ debugger/command/where.h \ debugger/command/write.h \ debugger/file2line.h \ debugger/fns.h \ debugger/info.h \ debugger/stack.h \ debugger/subcmd.h make_SOURCES = alloc.c ar.c arscan.c \ buildargv.c commands.c default.c \ debug.c dir.c \ expand.c file_basic.c file.c function.c \ getopt.c getopt1.c globals.c guile.c \ hash.c implicit.c job.c load.c loadapi.c main.c misc.c output.c \ profile.c print.c \ read.c remake.c rule.c \ signame.c strcache.c \ trace.c variable.c version.c vpath.c \ $(remote) \ $(DEBUGGER_SRC) EXTRA_make_SOURCES = remote-stub.c remote-cstms.c mock.c noinst_HEADERS = buildargv.h commands.h \ debug.h debugger.h dep.h expand.h \ file_basic.h file.h function.h filedef.h \ getopt.h gettext.h globals.h hash.h \ job.h main.h make.h makeint.h mock.h \ output.h implicit.h \ print.h profile.h \ read.h rule.h \ trace.h types.h variable.h vpath.h \ $(DEBUGGER_H) make_LDADD = @LIBOBJS@ @ALLOCA@ $(GLOBLIB) @GETLOADAVG_LIBS@ @LIBINTL@ \ $(GUILE_LIBS) # Only process if target is MS-Windows if WINDOWSENV make_LDADD += $(W32LIB) endif man_MANS = make.1 DEFS = -DLOCALEDIR=\"$(localedir)\" -DLIBDIR=\"$(libdir)\" -DINCLUDEDIR=\"$(includedir)\" @DEFS@ AM_CPPFLAGS = $(GLOBINC) AM_CFLAGS = $(GUILE_CFLAGS) # Only process if target is MS-Windows if WINDOWSENV AM_CPPFLAGS += $(W32INC) endif # Extra stuff to include in the distribution. EXTRA_DIST = ChangeLog README build.sh.in $(man_MANS) \ README.customs \ SCOPTIONS SMakefile \ make.lnk NMakefile \ make_msvc_net2003.sln make_msvc_net2003.vcproj \ gmk-default.scm gmk-default.h \ debugger/Makefile \ NEWS.remake README.remake REMAKE.todo Rakefile # This is built during configure, but behind configure's back DISTCLEANFILES = build.sh MOSTLYCLEANFILES = callgrind.out.* *.orig *.rej @MAKE_NAME@ # Forward targets html-local: cd doc && $(MAKE) $(AM_MAKEFLAGS) $@ #: Make (re)make make$(EXEEXT): $(make_OBJECTS) $(make_DEPENDENCIES) @rm -f make$(EXEEXT) @MAKE_NAME@$(EXEEXT) $(LINK) $(make_OBJECTS) $(make_LDADD) $(LIBS) $(LN_S) make$(EXEEXT) @MAKE_NAME@$(EXEEXT) .PHONY: html # --------------- Internationalization Section localedir = $(datadir)/locale # --------------- Local INSTALL Section # If necessary, change the gid of the app and turn on the setgid flag. # # Whether or not make needs to be installed setgid. # The value should be either 'true' or 'false'. # On many systems, the getloadavg function (used to implement the '-l' # switch) will not work unless make is installed setgid kmem. # inst_setgid = @NEED_SETGID@ # Install make setgid to this group so it can get the load average. # inst_group = @KMEM_GROUP@ #: install executables (e.g. remake) install-exec-local: @if $(inst_setgid); then \ app=$(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed '$(transform)'`; \ if chgrp $(inst_group) $$app && chmod g+s $$app; then \ echo "chgrp $(inst_group) $$app && chmod g+s $$app"; \ else \ echo "$$app needs to be owned by group $(inst_group) and setgid;"; \ echo "otherwise the '-l' option will probably not work."; \ echo "You may need special privileges to complete the installation"; \ echo "of $$app."; \ fi; \ else true; fi # --------------- #: Generate the Guile default module content guile.$(OBJEXT): gmk-default.h gmk-default.h: $(srcdir)/gmk-default.scm (echo 'static const char *const GUILE_module_defn = " '\\ \ && sed -e 's/;.*//' -e '/^[ \t]*$$/d' -e 's/"/\\"/g' -e 's/$$/ \\/' \ $(srcdir)/gmk-default.scm \ && echo '";') > $@ # --------------- Local DIST Section #: Install the w32 and tests subdirectories # dist-hook: (cd $(srcdir); \ sub=`find w32 tests -follow \( -name .git -o -name .deps -o -name work -o -name .gitignore -o -name \*.orig -o -name \*.rej -o -name \*~ -o -name Makefile \) -prune -o -type f -print`; \ tar chf - $$sub) \ | (cd $(distdir); tar xfBp -) # --------------- Local CHECK Section check-local: check-regression check-loadavg @banner=" Regression PASSED: GNU Make $(VERSION) ($(MAKE_HOST)) built with $(CC) "; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo; \ echo "$$dashes"; \ echo "$$banner"; \ echo "$$dashes"; \ echo .PHONY: check-loadavg check-regression #: Check internal load average routine against 'uptime' check-loadavg: loadavg$(EXEEXT) @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code thinks: -./loadavg$(EXEEXT) # FIXME: doesn't work. ##: Run remake-specific tests using Ruby rspec #check-rspec: # $(SHELL) -c 'ruby tests/spec/run-tests.rb' # The loadavg function is invoked during "make check" to test getloadavg. check_PROGRAMS = loadavg nodist_loadavg_SOURCES = getloadavg.c loadavg_CPPFLAGS = -DTEST loadavg_LDADD = @GETLOADAVG_LIBS@ # > check-regression # # Look for the make test suite, and run it if found and we can find perl. # If we're building outside the tree, we use symlinks to make a local copy of # the test suite. Unfortunately the test suite itself isn't localizable yet. # MAKETESTFLAGS = #: run regression tests in tests/scripts check-regression: tests/config-flags.pm @if test -f '$(srcdir)/tests/run_make_tests'; then \ ulimit -n 128; \ if $(PERL) -v >/dev/null 2>&1; then \ case `cd '$(srcdir)'; pwd` in `pwd`) : ;; \ *) test -d tests || mkdir tests; \ rm -f srctests; \ if ln -s '$(srcdir)/tests' srctests; then \ for f in run_make_tests run_make_tests.pl test_driver.pl scripts; do \ rm -f tests/$$f; ln -s ../srctests/$$f tests; \ done; fi ;; \ esac; \ echo "cd tests && $(PERL) -I . ./run_make_tests.pl -srcdir $(abs_srcdir) -make ../make$(EXEEXT) $(MAKETESTFLAGS)"; \ cd tests && $(PERL) -I . ./run_make_tests.pl -srcdir '$(abs_srcdir)' -make '../make$(EXEEXT)' $(MAKETESTFLAGS); \ else \ echo "Can't find a working Perl ($(PERL)); the test suite requires Perl."; \ fi; \ else \ echo "Can't find the GNU Make test suite ($(srcdir)/tests)."; \ fi %.short: $(MAKE) $(@:.short=) 2>&1 >/dev/null # --------------- Maintainer's Section # Tell automake that I haven't forgotten about this file and it will be # created before we build a distribution (see maintMakefile in the Git # distribution). README: @MAINT_MAKEFILE@ # FIXME fix up to use the git2cl in MAINT_MAKEFILE GIT2CL = ./git2cl if MAINTAINER_MODE #: create ChangeLog for distirbution from 'git log' ChangeLog: git log --pretty --numstat --summary | $(GIT2CL) > $@ endif remake-4.1+dbg1.3~dfsg.1/Makefile.ami000066400000000000000000000241361317072305000172060ustar00rootroot00000000000000# -*-Makefile-*- for GNU make on Amiga # # NOTE: If you have no 'make' program at all to process this makefile, run # 'build.sh' instead. # # Copyright (C) 1995-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # # Makefile for GNU Make # CC = sc RM = delete CFLAGS = CPPFLAGS = LDFLAGS = # Define these for your system as follows: # -DNO_ARCHIVES To disable 'ar' archive support. # -DNO_FLOAT To avoid using floating-point numbers. # -DENUM_BITFIELDS If the compiler isn't GCC but groks enum foo:2. # Some compilers apparently accept this # without complaint but produce losing code, # so beware. # NeXT 1.0a uses an old version of GCC, which required -D__inline=inline. # See also 'config.h'. defines = # Which flavor of remote job execution support to use. # The code is found in 'remote-$(REMOTE).c'. REMOTE = stub # If you are using the GNU C library, or have the GNU getopt functions in # your C library, you can comment these out. GETOPT = getopt.o getopt1.o GETOPT_SRC = $(srcdir)getopt.c $(srcdir)getopt1.c $(srcdir)getopt.h # If you are using the GNU C library, or have the GNU glob functions in # your C library, you can comment this out. GNU make uses special hooks # into the glob functions to be more efficient (by using make's directory # cache for globbing), so you must use the GNU functions even if your # system's C library has the 1003.2 glob functions already. Also, the glob # functions in the AIX and HPUX C libraries are said to be buggy. GLOB = glob/glob.lib # If your system doesn't have alloca, or the one provided is bad, define this. ALLOCA = alloca.o ALLOCA_SRC = $(srcdir)alloca.c # If your system needs extra libraries loaded in, define them here. # System V probably need -lPW for alloca. HP-UX 7.0's alloca in # libPW.a is broken on HP9000s300 and HP9000s400 machines. Use # alloca.c instead on those machines. LOADLIBES = # Any extra object files your system needs. extras = amiga.o # Common prefix for machine-independent installed files. prefix = # Common prefix for machine-dependent installed files. exec_prefix = # Directory to install 'make' in. bindir = sc:c # Directory to find libraries in for '-lXXX'. libdir = lib: # Directory to search by default for included makefiles. includedir = include: # Directory to install the Info files in. infodir = doc: # Directory to install the man page in. mandir = t: # Number to put on the man page filename. manext = 1 # Prefix to put on installed 'make' binary file name. binprefix = # Prefix to put on installed 'make' man page file name. manprefix = $(binprefix) # Whether or not make needs to be installed setgid. # The value should be either 'true' or 'false'. # On many systems, the getloadavg function (used to implement the '-l' # switch) will not work unless make is installed setgid kmem. install_setgid = false # Install make setgid to this group so it can read /dev/kmem. group = sys # Program to install 'make'. INSTALL_PROGRAM = copy # Program to install the man page. INSTALL_DATA = copy # Generic install program. INSTALL = copy # Program to format Texinfo source into Info files. MAKEINFO = makeinfo # Program to format Texinfo source into DVI files. TEXI2DVI = texi2dvi # Programs to make tags files. ETAGS = etags -w CTAGS = ctags -w #guile = guile.o objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o \ rule.o implicit.o default.o variable.o expand.o function.o \ vpath.o version.o ar.o arscan.o signame.o strcache.o hash.o \ remote-$(REMOTE).o $(GETOPT) $(ALLOCA) $(extras) $(guile) srcs = $(srcdir)commands.c $(srcdir)job.c $(srcdir)dir.c \ $(srcdir)file.c $(srcdir)getloadavg.c $(srcdir)misc.c \ $(srcdir)main.c $(srcdir)read.c $(srcdir)remake.c \ $(srcdir)rule.c $(srcdir)implicit.c $(srcdir)default.c \ $(srcdir)variable.c $(srcdir)expand.c $(srcdir)function.c \ $(srcdir)vpath.c $(srcdir)version.c $(srcdir)hash.c \ $(srcdir)guile.c $(srcdir)remote-$(REMOTE).c \ $(srcdir)ar.c $(srcdir)arscan.c $(srcdir)strcache.c \ $(srcdir)signame.c $(srcdir)signame.h $(GETOPT_SRC) \ $(srcdir)commands.h $(srcdir)dep.h $(srcdir)filedep.h \ $(srcdir)job.h $(srcdir)makeint.h $(srcdir)rule.h \ $(srcdir)variable.h $(ALLOCA_SRC) $(srcdir)config.h.in .SUFFIXES: .SUFFIXES: .o .c .h .ps .dvi .info .texinfo all: make info: make.info dvi: make.dvi # Some makes apparently use .PHONY as the default goal if it is before 'all'. .PHONY: all check info dvi make.info: make.texinfo $(MAKEINFO) -I$(srcdir) $(srcdir)make.texinfo -o make.info make.dvi: make.texinfo $(TEXI2DVI) $(srcdir)make.texinfo make.ps: make.dvi dvi2ps make.dvi > make.ps make: $(objs) $(GLOB) $(CC) Link $(LDFLAGS) $(objs) Lib $(GLOB) $(LOADLIBES) To make.new -delete make rename make.new make TMPFILE = t:Make$$ $(GLOB): cd glob @@\ $(MAKE) -$(MAKEFLAGS) -f Makefile # -I. is needed to find config.h in the build directory. OUTPUT_OPTION = .c.o: $(CC) $(defines) IDir "" IDir glob \ $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) # For some losing Unix makes. SHELL = /bin/sh #@SET_MAKE@ glob/libglob.a: FORCE config.h cd glob; $(MAKE) libglob.a FORCE: .PHONY: install installdirs install: installdirs \ $(bindir)$(binprefix)make $(infodir)make.info \ $(mandir)$(manprefix)make.$(manext) installdirs: $(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir) $(mandir) $(bindir)$(binprefix)make: make $(INSTALL_PROGRAM) make $@.new @if $(install_setgid); then \ if chgrp $(group) $@.new && chmod g+s $@.new; then \ echo "chgrp $(group) $@.new && chmod g+s $@.new"; \ else \ echo "$@ needs to be owned by group $(group) and setgid;"; \ echo "otherwise the '-l' option will probably not work."; \ echo "You may need special privileges to install $@."; \ fi; \ else true; fi # Some systems can't deal with renaming onto a running binary. -$(RM) $@.old -mv $@ $@.old mv $@.new $@ $(infodir)make.info: make.info if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \ for file in $${dir}/make.info*; do \ name="`basename $$file`"; \ $(INSTALL_DATA) $$file \ `echo $@ | sed "s,make.info\$$,$$name,"`; \ done # Run install-info only if it exists. # Use 'if' instead of just prepending '-' to the # line so we notice real errors from install-info. # We use '$(SHELL) -c' because some shells do not # fail gracefully when there is an unknown command. if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ if [ -r ./make.info ]; then dir=.; else dir=$(srcdir); fi; \ install-info --infodir=$(infodir) $$dir/make.info; \ else true; fi $(mandir)$(manprefix)make.$(manext): make.man $(INSTALL_DATA) $(srcdir)make.man $@ loadavg: loadavg.c config.h $(CC) $(defines) -DTEST -I. -I$(srcdir) $(CFLAGS) $(LDFLAGS) \ loadavg.c $(LOADLIBES) -o $@ # We copy getloadavg.c into a different file rather than compiling it # directly because some compilers clobber getloadavg.o in the process. loadavg.c: getloadavg.c ln $(srcdir)getloadavg.c loadavg.c || \ cp $(srcdir)getloadavg.c loadavg.c check-loadavg: loadavg @echo The system uptime program believes the load average to be: -uptime @echo The GNU load average checking code believes: ./loadavg check: check-loadavg .PHONY: clean realclean distclean mostlyclean clean: glob-clean -$(RM) make loadavg "#?.o" core make.dvi distclean: clean glob-realclean -$(RM) Makefile config.h config.status build.sh -$(RM) config.log config.cache -$(RM) TAGS tags -$(RM) make.?? make.??s make.log make.toc make.*aux -$(RM) loadavg.c realclean: distclean -$(RM) make.info* mostlyclean: clean .PHONY: glob-clean glob-realclean glob-clean glob-realclean: cd glob @@\ $(MAKE) $@ # This tells versions [3.59,3.63) of GNU make not to export all variables. .NOEXPORT: # The automatically generated dependencies below may omit config.h # because it is included with '#include ' rather than # '#include "config.h"'. So we add the explicit dependency to make sure. $(objs): config.h # Automatically generated dependencies will be put at the end of the file. # Automatically generated dependencies. commands.o: commands.c makeint.h dep.h filedef.h variable.h job.h \ commands.h job.o: job.c makeint.h job.h filedef.h commands.h variable.h dir.o: dir.c makeint.h file.o: file.c makeint.h dep.h filedef.h job.h commands.h variable.h misc.o: misc.c makeint.h dep.h main.o: main.c makeint.h dep.h filedef.h variable.h job.h commands.h \ getopt.h guile.o: guile.c makeint.h dep.h debug.h variable.h gmk-default.h read.o: read.c makeint.h dep.h filedef.h job.h commands.h variable.h \ glob/glob.h remake.o: remake.c makeint.h filedef.h job.h commands.h dep.h rule.o: rule.c makeint.h dep.h filedef.h job.h commands.h variable.h \ rule.h implicit.o: implicit.c makeint.h rule.h dep.h filedef.h default.o: default.c makeint.h rule.h dep.h filedef.h job.h commands.h \ variable.h variable.o: variable.c makeint.h dep.h filedef.h job.h commands.h \ variable.h expand.o: expand.c makeint.h filedef.h job.h commands.h variable.h function.o: function.c makeint.h filedef.h variable.h dep.h job.h \ commands.h amiga.h vpath.o: vpath.c makeint.h filedef.h variable.h strcache.o: strcache.c makeint.h hash.h version.o: version.c ar.o: ar.c makeint.h filedef.h dep.h arscan.o: arscan.c makeint.h signame.o: signame.c signame.h remote-stub.o: remote-stub.c makeint.h filedef.h job.h commands.h getopt.o: getopt.c getopt1.o : getopt1.c getopt.h getloadavg.o: getloadavg.c amiga.o: amiga.c makeint.h variable.h amiga.h remake-4.1+dbg1.3~dfsg.1/NEWS000066400000000000000000001530561317072305000155040ustar00rootroot00000000000000Version 4.1+dbg1.3 See NEWS.remake for remake news GNU make NEWS -*-indented-text-*- History of user-visible changes. 05 Oct 2014 See the end of this file for copyrights and conditions. All changes mentioned here are more fully described in the GNU make manual, which is contained in this distribution as the file doc/make.texi. See the README file and the GNU make manual for instructions for reporting bugs. Version 4.1 (05 Oct 2014) A complete list of bugs fixed in this version is available here: http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=105&set=custom * New variables: $(MAKE_TERMOUT) and $(MAKE_TERMERR) are set to non-empty values if stdout or stderr, respectively, are believed to be writing to a terminal. These variables are exported by default. * Allow a no-text-argument form of the $(file ...) function. Without a text argument nothing is written to the file: it is simply opened in the requested mode, then closed again. * Change the fatal error for mixed explicit and implicit rules, that was introduced in GNU make 3.82, to a non-fatal error. However, this syntax is still deprecated and may return to being illegal in a future version of GNU make. Makefiles that rely on this syntax should be fixed. See https://savannah.gnu.org/bugs/?33034 Version 4.0 (09 Oct 2013) A complete list of bugs fixed in this version is available here: http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set=custom * WARNING: Backward-incompatibility! If .POSIX is specified, then make adheres to the POSIX backslash/newline handling requirements, which introduces the following changes to the standard backslash/newline handling in non-recipe lines: * Any trailing space before the backslash is preserved * Each backslash/newline (plus subsequent whitespace) is converted to a single space * New feature: GNU Guile integration This version of GNU make can be compiled with GNU Guile integration. GNU Guile serves as an embedded extension language for make. See the "Guile Function" section in the GNU Make manual for details. Currently GNU Guile 1.8 and 2.0+ are supported. In Guile 1.8 there is no support for internationalized character sets. In Guile 2.0+, scripts can be encoded in UTF-8. * New command line option: --output-sync (-O) enables grouping of output by target or by recursive make. This is useful during parallel builds to avoid mixing output from different jobs together giving hard-to-understand results. Original implementation by David Boyce . Reworked and enhanced by Frank Heckenbach . Windows support by Eli Zaretskii . * New command line option: --trace enables tracing of targets. When enabled the recipe to be invoked is printed even if it would otherwise be suppressed by .SILENT or a "@" prefix character. Also before each recipe is run the makefile name and linenumber where it was defined are shown as well as the prerequisites that caused the target to be considered out of date. * New command line option argument: --debug now accepts a "n" (none) flag which disables all debugging settings that are currently enabled. * New feature: The "job server" capability is now supported on Windows. Implementation contributed by Troy Runkel * New feature: The .ONESHELL capability is now supported on Windows. Support added by Eli Zaretskii . * New feature: "!=" shell assignment operator as an alternative to the $(shell ...) function. Implemented for compatibility with BSD makefiles. Note there are subtle differences between "!=" and $(shell ...). See the description in the GNU make manual. WARNING: Backward-incompatibility! Variables ending in "!" previously defined as "variable!= value" will now be interpreted as shell assignment. Change your assignment to add whitespace between the "!" and "=": "variable! = value" * New feature: "::=" simple assignment operator as defined by POSIX in 2012. This operator has identical functionality to ":=" in GNU make, but will be portable to any implementation of make conforming to a sufficiently new version of POSIX (see http://austingroupbugs.net/view.php?id=330). It is not necessary to define the .POSIX target to access this operator. * New feature: Loadable objects This version of GNU make contains a "technology preview": the ability to load dynamic objects into the make runtime. These objects can be created by the user and can add extended functionality, usable by makefiles. * New function: $(file ...) writes to a file. * New variable: $(GNUMAKEFLAGS) will be parsed for make flags, just like MAKEFLAGS is. It can be set in the environment or the makefile, containing GNU make-specific flags to allow your makefile to be portable to other versions of make. Once this variable is parsed, GNU make will set it to the empty string so that flags will not be duplicated on recursion. * New variable: `MAKE_HOST' gives the name of the host architecture make was compiled for. This is the same value you see after 'Built for' when running 'make --version'. * Behavior of MAKEFLAGS and MFLAGS is more rigorously defined. All simple flags are grouped together in the first word of MAKEFLAGS. No options that accept arguments appear in the first word. If no simple flags are present MAKEFLAGS begins with a space. Flags with both short and long versions always use the short versions in MAKEFLAGS. Flags are listed in alphabetical order using ASCII ordering. MFLAGS never begins with "- ". * Setting the -r and -R options in MAKEFLAGS inside a makefile now works as expected, removing all built-in rules and variables, respectively. * If a recipe fails, the makefile name and linenumber of the recipe are shown. * A .RECIPEPREFIX setting is remembered per-recipe and variables expanded in that recipe also use that recipe prefix setting. * In -p output, .RECIPEPREFIX settings are shown and all target-specific variables are output as if in a makefile, instead of as comments. * On MS-Windows, recipes that use ".." quoting will no longer force invocation of commands via temporary batch files and stock Windows shells, they will be short-circuited and invoked directly. (In other words, " is no longer a special character for stock Windows shells.) This avoids hitting shell limits for command length when quotes are used, but nothing else in the command requires the shell. This change could potentially mean some minor incompatibilities in behavior when the recipe uses quoted string on shell command lines. Version 3.82 (28 Jul 2010) A complete list of bugs fixed in this version is available here: http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=104&set=custom * Compiling GNU make now requires a conforming ISO C 1989 compiler and standard runtime library. * WARNING: Backward-incompatibility! The POSIX standard for make was changed in the 2008 version in a fundamentally incompatible way: make is required to invoke the shell as if the '-e' flag were provided. Because this would break many makefiles that have been written to conform to the original text of the standard, the default behavior of GNU make remains to invoke the shell with simply '-c'. However, any makefile specifying the .POSIX special target will follow the new POSIX standard and pass '-e' to the shell. See also .SHELLFLAGS below. * WARNING: Backward-incompatibility! The '$?' variable now contains all prerequisites that caused the target to be considered out of date, even if they do not exist (previously only existing targets were provided in $?). * WARNING: Backward-incompatibility! Wildcards were not documented as returning sorted values, but the results have been sorted up until this release.. If your makefiles require sorted results from wildcard expansions, use the $(sort ...) function to request it explicitly. * WARNING: Backward-incompatibility! As a result of parser enhancements, three backward-compatibility issues exist: first, a prerequisite containing an "=" cannot be escaped with a backslash any longer. You must create a variable containing an "=" and use that variable in the prerequisite. Second, variable names can no longer contain whitespace, unless you put the whitespace in a variable and use the variable. Third, in previous versions of make it was sometimes not flagged as an error for explicit and pattern targets to appear in the same rule. Now this is always reported as an error. * WARNING: Backward-incompatibility! The pattern-specific variables and pattern rules are now applied in the shortest stem first order instead of the definition order (variables and rules with the same stem length are still applied in the definition order). This produces the usually-desired behavior where more specific patterns are preferred. To detect this feature search for 'shortest-stem' in the .FEATURES special variable. * WARNING: Backward-incompatibility! The library search behavior has changed to be compatible with the standard linker behavior. Prior to this version for prerequisites specified using the -lfoo syntax make first searched for libfoo.so in the current directory, vpath directories, and system directories. If that didn't yield a match, make then searched for libfoo.a in these directories. Starting with this version make searches first for libfoo.so and then for libfoo.a in each of these directories in order. * New command line option: --eval=STRING causes STRING to be evaluated as makefile syntax (akin to using the $(eval ...) function). The evaluation is performed after all default rules and variables are defined, but before any makefiles are read. * New special variable: .RECIPEPREFIX allows you to reset the recipe introduction character from the default (TAB) to something else. The first character of this variable value is the new recipe introduction character. If the variable is set to the empty string, TAB is used again. It can be set and reset at will; recipes will use the value active when they were first parsed. To detect this feature check the value of $(.RECIPEPREFIX). * New special variable: .SHELLFLAGS allows you to change the options passed to the shell when it invokes recipes. By default the value will be "-c" (or "-ec" if .POSIX is set). * New special target: .ONESHELL instructs make to invoke a single instance of the shell and provide it with the entire recipe, regardless of how many lines it contains. As a special feature to allow more straightforward conversion of makefiles to use .ONESHELL, any recipe line control characters ('@', '+', or '-') will be removed from the second and subsequent recipe lines. This happens _only_ if the SHELL value is deemed to be a standard POSIX-style shell. If not, then no interior line control characters are removed (as they may be part of the scripting language used with the alternate SHELL). * New variable modifier 'private': prefixing a variable assignment with the modifier 'private' suppresses inheritance of that variable by prerequisites. This is most useful for target- and pattern-specific variables. * New make directive: 'undefine' allows you to undefine a variable so that it appears as if it was never set. Both $(flavor) and $(origin) functions will return 'undefined' for such a variable. To detect this feature search for 'undefine' in the .FEATURES special variable. * The parser for variable assignments has been enhanced to allow multiple modifiers ('export', 'override', 'private') on the same line as variables, including define/endef variables, and in any order. Also, it is possible to create variables and targets named as these modifiers. * The 'define' make directive now allows a variable assignment operator after the variable name, to allow for simple, conditional, or appending multi-line variable assignment. Version 3.81 (01 Apr 2006) * GNU make is ported to OS/2. * GNU make is ported to MinGW. The MinGW build is only supported by the build_w32.bat batch file; see the file README.W32 for more details. * WARNING: Future backward-incompatibility! Up to and including this release, the '$?' variable does not contain any prerequisite that does not exist, even though that prerequisite might have caused the target to rebuild. Starting with the _next_ release of GNU make, '$?' will contain all prerequisites that caused the target to be considered out of date. See http://savannah.gnu.org/bugs/?16051 * WARNING: Backward-incompatibility! GNU make now implements a generic "second expansion" feature on the prerequisites of both explicit and implicit (pattern) rules. In order to enable this feature, the special target '.SECONDEXPANSION' must be defined before the first target which takes advantage of it. If this feature is enabled then after all rules have been parsed the prerequisites are expanded again, this time with all the automatic variables in scope. This means that in addition to using standard SysV $$@ in prerequisites lists, you can also use complex functions such as $$(notdir $$@) etc. This behavior applies to implicit rules, as well, where the second expansion occurs when the rule is matched. However, this means that when '.SECONDEXPANSION' is enabled you must double-quote any "$" in your filenames; instead of "foo: boo$$bar" you now must write "foo: foo$$$$bar". Note that the SysV $$@ etc. feature, which used to be available by default, is now ONLY available when the .SECONDEXPANSION target is defined. If your makefiles take advantage of this SysV feature you will need to update them. * WARNING: Backward-incompatibility! In order to comply with POSIX, the way in which GNU make processes backslash-newline sequences in recipes has changed. If your makefiles use backslash-newline sequences inside of single-quoted strings in recipes you will be impacted by this change. See the GNU make manual subsection "Splitting Recipe Lines" (node "Splitting Lines"), in section "Recipe Syntax", chapter "Writing Recipe in Rules", for details. * WARNING: Backward-incompatibility! Some previous versions of GNU make had a bug where "#" in a function invocation such as $(shell ...) was treated as a make comment. A workaround was to escape these with backslashes. This bug has been fixed: if your makefile uses "\#" in a function invocation the backslash is now preserved, so you'll need to remove it. * New command line option: -L (--check-symlink-times). On systems that support symbolic links, if this option is given then GNU make will use the most recent modification time of any symbolic links that are used to resolve target files. The default behavior remains as it always has: use the modification time of the actual target file only. * The "else" conditional line can now be followed by any other valid conditional on the same line: this does not increase the depth of the conditional nesting, so only one "endif" is required to close the conditional. * All pattern-specific variables that match a given target are now used (previously only the first match was used). * Target-specific variables can be marked as exportable using the "export" keyword. * In a recursive $(call ...) context, any extra arguments from the outer call are now masked in the context of the inner call. * Implemented a solution for the "thundering herd" problem with "-j -l". This version of GNU make uses an algorithm suggested by Thomas Riedl to track the number of jobs started in the last second and artificially adjust GNU make's view of the system's load average accordingly. * New special variables available in this release: - .INCLUDE_DIRS: Expands to a list of directories that make searches for included makefiles. - .FEATURES: Contains a list of special features available in this version of GNU make. - .DEFAULT_GOAL: Set the name of the default goal make will use if no goals are provided on the command line. - MAKE_RESTARTS: If set, then this is the number of times this instance of make has been restarted (see "How Makefiles Are Remade" in the manual). - New automatic variable: $| (added in 3.80, actually): contains all the order-only prerequisites defined for the target. * New functions available in this release: - $(lastword ...) returns the last word in the list. This gives identical results as $(word $(words ...) ...), but is much faster. - $(abspath ...) returns the absolute path (all "." and ".." directories resolved, and any duplicate "/" characters removed) for each path provided. - $(realpath ...) returns the canonical pathname for each path provided. The canonical pathname is the absolute pathname, with all symbolic links resolved as well. - $(info ...) prints its arguments to stdout. No makefile name or line number info, etc. is printed. - $(flavor ...) returns the flavor of a variable. - $(or ...) provides a short-circuiting OR conditional: each argument is expanded. The first true (non-empty) argument is returned; no further arguments are expanded. Expands to empty if there are no true arguments. - $(and ...) provides a short-circuiting AND conditional: each argument is expanded. The first false (empty) argument is returned; no further arguments are expanded. Expands to the last argument if all arguments are true. * Changes made for POSIX compatibility: - Only touch targets (under -t) if they have a recipe. - Setting the SHELL make variable does NOT change the value of the SHELL environment variable given to programs invoked by make. As an enhancement to POSIX, if you export the make variable SHELL then it will be set in the environment, just as before. * On MS Windows systems, explicitly setting SHELL to a pathname ending in "cmd" or "cmd.exe" (case-insensitive) will force GNU make to use the DOS command interpreter in batch mode even if a UNIX-like shell could be found on the system. * On VMS there is now support for case-sensitive filesystems such as ODS5. See the README.VMS file for information. * Parallel builds (-jN) no longer require a working Bourne shell on Windows platforms. They work even with the stock Windows shells, such as cmd.exe and command.com. * Updated to autoconf 2.59, automake 1.9.5, and gettext 0.14.1. Users should not be impacted. * New translations for Swedish, Chinese (simplified), Ukrainian, Belarusian, Finnish, Kinyarwandan, and Irish. Many updated translations. A complete list of bugs fixed in this version is available here: http://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=103 Version 3.80 (03 Oct 2002) * A new feature exists: order-only prerequisites. These prerequisites affect the order in which targets are built, but they do not impact the rebuild/no-rebuild decision of their dependents. That is to say, they allow you to require target B be built before target A, without requiring that target A will always be rebuilt if target B is updated. Patch for this feature provided by Greg McGary . * For compatibility with SysV make, GNU make now supports the peculiar syntax $$@, $$(@D), and $$(@F) in the prerequisites list of a rule. This syntax is only valid within explicit and static pattern rules: it cannot be used in implicit (suffix or pattern) rules. Edouard G. Parmelan provided a patch implementing this feature; however, I decided to implement it in a different way. * The argument to the "ifdef" conditional is now expanded before it's tested, so it can be a constructed variable name. Similarly, the arguments to "export" (when not used in a variable definition context) and "unexport" are also now expanded. * A new function is defined: $(value ...). The argument to this function is the _name_ of a variable. The result of the function is the value of the variable, without having been expanded. * A new function is defined: $(eval ...). The arguments to this function should expand to makefile commands, which will then be evaluated as if they had appeared in the makefile. In combination with define/endef multiline variable definitions this is an extremely powerful capability. The $(value ...) function is also sometimes useful here. * A new built-in variable is defined, $(MAKEFILE_LIST). It contains a list of each makefile GNU make has read, or started to read, in the order in which they were encountered. So, the last filename in the list when a makefile is just being read (before any includes) is the name of the current makefile. * A new built-in variable is defined: $(.VARIABLES). When it is expanded it returns a complete list of variable names defined by all makefiles at that moment. * A new command line option is defined, -B or --always-make. If specified GNU make will consider all targets out-of-date even if they would otherwise not be. * The arguments to $(call ...) functions were being stored in $1, $2, etc. as recursive variables, even though they are fully expanded before assignment. This means that escaped dollar signs ($$ etc.) were not behaving properly. Now the arguments are stored as simple variables. This may mean that if you added extra escaping to your $(call ...) function arguments you will need to undo it now. * The variable invoked by $(call ...) can now be recursive: unlike other variables it can reference itself and this will not produce an error when it is used as the first argument to $(call ...) (but only then). * New pseudo-target .LOW_RESOLUTION_TIME, superseding the configure option --disable-nsec-timestamps. You might need this if your build process depends on tools like "cp -p" preserving time stamps, since "cp -p" (right now) doesn't preserve the subsecond portion of a time stamp. * Updated translations for French, Galician, German, Japanese, Korean, and Russian. New translations for Croatian, Danish, Hebrew, and Turkish. * Updated internationalization support to Gettext 0.11.5. GNU make now uses Gettext's "external" feature, and does not include any internationalization code itself. Configure will search your system for an existing implementation of GNU Gettext (only GNU Gettext is acceptable) and use it if it exists. If not, NLS will be disabled. See ABOUT-NLS for more information. * Updated to autoconf 2.54 and automake 1.7. Users should not be impacted. A complete list of bugs fixed in this version is available here: http://savannah.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=102 Version 3.79.1 (23 Jun 2000) * .SECONDARY with no prerequisites now prevents any target from being removed because make thinks it's an intermediate file, not just those listed in the makefile. * New configure option --disable-nsec-timestamps, but this was superseded in later versions by the .LOW_RESOLUTION_TIME pseudo-target. Version 3.79 (04 Apr 2000) * GNU make optionally supports internationalization and locales via the GNU gettext (or local gettext if suitable) package. See the ABOUT-NLS file for more information on configuring GNU make for NLS. * Previously, GNU make quoted variables such as MAKEFLAGS and MAKEOVERRIDES for proper parsing by the shell. This allowed them to be used within make build scripts. However, using them there is not proper behavior: they are meant to be passed to subshells via the environment. Unfortunately the values were not quoted properly to be passed through the environment. This meant that make didn't properly pass some types of command line values to submakes. With this version we change that behavior: now these variables are quoted properly for passing through the environment, which is the correct way to do it. If you previously used these variables explicitly within a make rule you may need to re-examine your use for correctness given this change. * A new pseudo-target .NOTPARALLEL is available. If defined, the current makefile is run serially regardless of the value of -j. However, submakes are still eligible for parallel execution. * The --debug option has changed: it now allows optional flags controlling the amount and type of debugging output. By default only a minimal amount information is generated, displaying the names of "normal" targets (not makefiles) that were deemed out of date and in need of being rebuilt. Note that the -d option behaves as before: it takes no arguments and all debugging information is generated. * The `-p' (print database) output now includes filename and linenumber information for variable definitions, to aid debugging. * The wordlist function no longer reverses its arguments if the "start" value is greater than the "end" value. If that's true, nothing is returned. * Hartmut Becker provided many updates for the VMS port of GNU make. See the README.VMS file for more details. Version 3.78 (22 Sep 1999) * Two new functions, $(error ...) and $(warning ...) are available. The former will cause make to fail and exit immediately upon expansion of the function, with the text provided as the error message. The latter causes the text provided to be printed as a warning message, but make proceeds normally. * A new function $(call ...) is available. This allows users to create their own parameterized macros and invoke them later. Original implementation of this function was provided by Han-Wen Nienhuys . * A new function $(if ...) is available. It provides if-then-else capabilities in a builtin function. Original implementation of this function was provided by Han-Wen Nienhuys . * Make defines a new variable, .LIBPATTERNS. This variable controls how library dependency expansion (dependencies like ``-lfoo'') is performed. * Make accepts CRLF sequences as well as traditional LF, for compatibility with makefiles created on other operating systems. * Make accepts a new option: -R, or --no-builtin-variables. This option disables the definition of the rule-specific builtin variables (CC, LD, AR, etc.). Specifying this option forces -r (--no-builtin-rules) as well. * A "job server" feature, suggested by Howard Chu . On systems that support POSIX pipe(2) semantics, GNU make can now pass -jN options to submakes rather than forcing them all to use -j1. The top make and all its sub-make processes use a pipe to communicate with each other to ensure that no more than N jobs are started across all makes. To get the old behavior of -j back, you can configure make with the --disable-job-server option. * The confusing term "dependency" has been replaced by the more accurate and standard term "prerequisite", both in the manual and in all GNU make output. * GNU make supports the "big archive" library format introduced in AIX 4.3. * GNU make supports large files on AIX, HP-UX, and IRIX. These changes were provided by Paul Eggert . (Large file support for Solaris and Linux was introduced in 3.77, but the configuration had issues: these have also been resolved). * The Windows 95/98/NT (W32) version of GNU make now has native support for the Cygnus Cygwin release B20.1 shell (bash). * The GNU make regression test suite, long available separately "under the table", has been integrated into the release. You can invoke it by running "make check" in the distribution. Note that it requires Perl (either Perl 4 or Perl 5) to run. Version 3.77 (28 Jul 1998) * Implement BSD make's "?=" variable assignment operator. The variable is assigned the specified value only if that variable is not already defined. * Make defines a new variable, "CURDIR", to contain the current working directory (after the -C option, if any, has been processed). Modifying this variable has no effect on the operation of make. * Make defines a new default RCS rule, for new-style master file storage: ``% :: RCS/%'' (note no ``,v'' suffix). Make defines new default rules for DOS-style C++ file naming conventions, with ``.cpp'' suffixes. All the same rules as for ``.cc'' and ``.C'' suffixes are provided, along with LINK.cpp and COMPILE.cpp macros (which default to the same value as LINK.cc and COMPILE.cc). Note CPPFLAGS is still C preprocessor flags! You should use CXXFLAGS to change C++ compiler flags. * A new feature, "target-specific variable values", has been added. This is a large change so please see the appropriate sections of the manual for full details. Briefly, syntax like this: TARGET: VARIABLE = VALUE defines VARIABLE as VALUE within the context of TARGET. This is similar to SunOS make's "TARGET := VARIABLE = VALUE" feature. Note that the assignment may be of any type, not just recursive, and that the override keyword is available. COMPATIBILITY: This new syntax means that if you have any rules where the first or second dependency has an equal sign (=) in its name, you'll have to escape them with a backslash: "foo : bar\=baz". Further, if you have any dependencies which already contain "\=", you'll have to escape both of them: "foo : bar\\\=baz". * A new appendix listing the most common error and warning messages generated by GNU make, with some explanation, has been added to the GNU make User's Manual. * Updates to the GNU make Customs library support (see README.customs). * Updates to the Windows 95/NT port from Rob Tulloh (see README.W32), and to the DOS port from Eli Zaretski (see README.DOS). Version 3.76.1 (19 Sep 1997) * Small (but serious) bug fix. Quick rollout to get into the GNU source CD. Version 3.76 (16 Sep 1997) * GNU make now uses automake to control Makefile.in generation. This should make it more consistent with the GNU standards. * VPATH functionality has been changed to incorporate the VPATH+ patch, previously maintained by Paul Smith . See the manual. * Make defines a new variable, `MAKECMDGOALS', to contain the goals that were specified on the command line, if any. Modifying this variable has no effect on the operation of make. * A new function, `$(wordlist S,E,TEXT)', is available: it returns a list of words from number S to number E (inclusive) of TEXT. * Instead of an error, detection of future modification times gives a warning and continues. The warning is repeated just before GNU make exits, so it is less likely to be lost. * Fix the $(basename) and $(suffix) functions so they only operate on the last filename, not the entire string: Command Old Result New Result ------- ---------- ---------- $(basename a.b) a a $(basename a.b/c) a a.b/c $(suffix a.b) b b $(suffix a.b/c) b/c * The $(strip) function now removes newlines as well as TABs and spaces. * The $(shell) function now changes CRLF (\r\n) pairs to a space as well as newlines (\n). * Updates to the Windows 95/NT port from Rob Tulloh (see README.W32). * Eli Zaretskii has updated the port to 32-bit protected mode on MSDOS and MS-Windows, building with the DJGPP v2 port of GNU C/C++ compiler and utilities. See README.DOS for details, and direct all questions concerning this port to Eli Zaretskii or DJ Delorie . * John W. Eaton has updated the VMS port to support libraries and VPATH. Version 3.75 (27 Aug 1996) * The directory messages printed by `-w' and implicitly in sub-makes, are now omitted if Make runs no commands and has no other messages to print. * Make now detects files that for whatever reason have modification times in the future and gives an error. Files with such impossible timestamps can result from unsynchronized clocks, or archived distributions containing bogus timestamps; they confuse Make's dependency engine thoroughly. * The new directive `sinclude' is now recognized as another name for `-include', for compatibility with some other Makes. * Aaron Digulla has contributed a port to AmigaDOS. See README.Amiga for details, and direct all Amiga-related questions to . * Rob Tulloh of Tivoli Systems has contributed a port to Windows NT or 95. See README.W32 for details, and direct all Windows-related questions to . Version 3.73 (05 Apr 1995) * Converted to use Autoconf version 2, so `configure' has some new options. See INSTALL for details. * You can now send a SIGUSR1 signal to Make to toggle printing of debugging output enabled by -d, at any time during the run. Version 3.72 (04 Nov 1994) * DJ Delorie has ported Make to MS-DOS using the GO32 extender. He is maintaining the DOS port, not the GNU Make maintainer; please direct bugs and questions for DOS to . MS-DOS binaries are available for FTP from ftp.simtel.net in /pub/simtelnet/gnu/djgpp/. * The `MAKEFLAGS' variable (in the environment or in a makefile) can now contain variable definitions itself; these are treated just like command line variable definitions. Make will automatically insert any variable definitions from the environment value of `MAKEFLAGS' or from the command line, into the `MAKEFLAGS' value exported to children. The `MAKEOVERRIDES' variable previously included in the value of `$(MAKE)' for sub-makes is now included in `MAKEFLAGS' instead. As before, you can reset `MAKEOVERRIDES' in your makefile to avoid putting all the variables in the environment when its size is limited. * If `.DELETE_ON_ERROR' appears as a target, Make will delete the target of a rule if it has changed when its recipe exits with a nonzero status, just as when the recipe gets a signal. * The automatic variable `$+' is new. It lists all the dependencies like `$^', but preserves duplicates listed in the makefile. This is useful for linking rules, where library files sometimes need to be listed twice in the link order. * You can now specify the `.IGNORE' and `.SILENT' special targets with dependencies to limit their effects to those files. If a file appears as a dependency of `.IGNORE', then errors will be ignored while running the recipe to update that file. Likewise if a file appears as a dependency of `.SILENT', then the recipe to update that file will not be printed before it is run. (This change was made to conform to POSIX.2.) Version 3.71 (21 May 1994) * The automatic variables `$(@D)', `$(%D)', `$(*D)', `$(. remake-4.1+dbg1.3~dfsg.1/NEWS.remake000066400000000000000000000254721317072305000167470ustar00rootroot00000000000000Version 4.1+dbg-1.3 (no +dbg-1.2) 2017-09-17 - Add --port-mortem option - Add more information int "write" command: the complete target name and dependencies Format a little nicer - Some lint-like fixes. - Sync with 4.2+dbg-1.2 and 1.3 Version 4.1+dbg-1.1 2015-06-23 * Fix segv in set command * Add setqx which is like setq (set a varable) but expands the value before it assigns Version 4.1+dbg-1.0 2015-06-3 Marilyn release * Add --profile This creates callgrind profile output for a given run the callgrind output can be used with kcachegrind, callgrind_annotate, or gprof2dot to analyze data. You can get not only timings, but a graph of the target dependencies checked Version 4.1+dbg-0.91 2015-01-1 * Code now based on GNU Make 4.1 * add -verbosity option. Can be used to suppress version information; version info only shown at level 0. * More targets should have file locations now Version 3.82+dbg-0.9 2012-10-3 * More aggressive on showing --target descriptions * -X and -x are boolean options only use --trace and --debugger to supply an optional parameter * readline headers are no longer optional * small packaging changes Version 3.82+dbg-0.8 2011-10-27 * Add --tasks descriptions * Fix indentation bug in --trace * Give process id in output line when --jobs != 1 * More correct target depth calculation Version 3.82+dbg-0.7 2011-06-12 Fleetwood release * Add --tasks (akin to rake --tasks) option to list interesting targets --targets is similar * Allow negative frame numbers to count from the other end * Output changes to make it easier for front-ends like the emacs-dbgr * builds better on OS's with various versions of GNU readline Version 3.82+dbg-0.6 2011-04-10 * Allow breakpoints on line numbers. "info lines" shows the lines. * List also allows line numbers now. * Remove duplicate stops in stepping and breakpoints * Help and error message text greatly improved * Documentation updated * break/continue *target* run fixed * "info files" more user friendly * Correct order-only target display * Recover from a fatal error when inside the debugger Version 3.82+dbg-0.5 2011-04-01 * Track updating goal targets and more targets in general * We track more target locations earlier and show that in tracing * Add debugger "source" command * Add --no-readline option to disable use of GNU Readline * variable names are expanded on "break" and "continue" target names * bug in history count fixed. * Update manual to reflect the various changes. * Don't unstall reremake Version 3.82+dbg-0.4 2011-03-25 * Completely revise using GNU make 3.82 as a base. Much cleaner code, and should support all of GNU make's OS's. * Stepping now stops before each line of code is run. * Add debugger "edit" command * allow target name on "continue" command * breakpoints can now stop after prerequisite checking and after remaking a target. * Show line number in break command * Change semantics of debugger "finish" command. Is now more similar to gdb, i.e is a "step out" up to a higher-level target * Add back in command separator lines ##<<<< and ##>>>> * Add stopping-event icons; --, ++, ->, <-, ||, !! * Added support for making debugger when GNU Readline is not available * Start debugger tests via RSpec (in Ruby). * Add "eval" command * Start to revise documentation for current release. * Remove emacs. Please use emacs-dbgr code. See https://github.com/rocky/emacs-dbgr/wiki * mdb<> prompt is now remake<> * The usual doc fixes after a release Version 3.81+dbg-0.3 2010-05-01 * Bug fixes * Compiles on Solaris Version 3.81+dbg-0.2 - Sam Woodward Release 2009-01-10 * Bug in trying to fake file information for a .PHONY target * Some merge cleanup. Add debugger-specific documentation (from 3.80+dbg-0.61) Version 3.81+dbg-0.1 2008-10-27 * Merge in code from 3.80+dbg-0.63cvs. * Add "info rules" and "info vpath" Version 3.80+dbg-0.63cvs 2006-04-01 * Add a "list" command. Basically same as "target x depends commands" for now. "list -" shows the parent. * Help commands now show short usage. * Ctrl-d leaves debugger * Add Emacs regression test and allow space in filename for MS Windows Version 3.80+dbg-0.62 2007-02-27 * Changes to make more Debian compatibile. * Track some GNU Make 3.81 changes, which include a bugfix and making more strings "const". * Miscellaneous bugfixes Version 3.80+dbg-0.61 2006-03-24 * Add comint shell tracking - taken from python's pdbtrack * Add gdb's cd and pwd commands. * "write" command now adds "cd " as a comment. * configure options: --with-default-shell to specify the default value for SHELL (useful on say Solaris), --with-shell-trace to specify the option to turn on tracing, e.g. (-x). * Add configure option --with-shell-trace to specify how to turn on tracing when running shell commands. * Add --trace=normal. * run wasn't reading any (optional) arguments supplied. * Guard against dereferencing NULL pointers. * Some 3.81 features and bugfixes have been incorporated. At present not everything is there. * More doxygen documentation and docuementation improvements. Note debugger options in Manual page. Version 3.80+dbg-0.60 2005-12-25 * On a fatal error we now show command arguments used to invoke program. * tracing now sets shell tracing (+x) when invoking commands * The default behavior on error is to show call trace. To turn off use --no-extended-errors. Recently added --extended-errors and -E (not in standard GNU Make) have been removed. * "quit" can now terminate several levels of nested make (if "make" was called directly and not via a shell string). * prompt now shows target and prerequisites. * Fix bugs and memory leaks involving improper use of memory can weak casting. (shown in the vpath regression test dash-I on cygwin). * Reorganize help command. Is more ddd-friendly (and more gdb like). * More explicit free's of memory at termination. * Give line numbers and target names on --just-print. Print delmiters around the commands. * More debug tracing funnelled through db_level. Debugger command "show debug" shows the debug mask in a more understandable way. * Incorporate patches from GNU/Linux make 3.80. * Incorporate new functions from GNU Make 3.81: abspath, realpath, lastword * Expand documentation. * NOTE: the prompt has changed from "makedb" to "mdb" as has the Emacs Lisp command name to run the debugger. This change was made to avoid confusion between the Make debugger and a program which creates a DBM file. If you were using ddd-3.3.12-test.tar.gz you will need to get a newer version. Version 3.80+dbg-0.5 2005-12-10 * Errors in eval issued from the debugger no longer cause termination. * Separation of "Step" and "Next. "Step" command granularity is now "Next". "Step" stepping is more fine grained. * "target" command improvements: - sets file variables when showing is requested - add "target expand" to list target commands with "make" variables expanded. - allow @ or $@ as a target name * Add "info makefiles" to show what Makefiles have been read in. * Add "info breakpoints" * Breakpoints can now be listed and deleted by number - like gdb. This also helps ddd and should pave the way for more sophisticated kinds of breaking/watching. * Add a number of aliases (e.g. backtrace, bt, !!, L) and via an internal alias mechanism * Remove hash stats on printing variables -- generally not wanted for users (rather than GNU Make maintainers) * Add explicit memory free and reduce reading uninitialized values. * Revise testing mechanism for a more modern use of Perl. Can specify test program file name (./scripts/variables/special) test name (variables/special). The former is works better with command completion. Document some more regression tests. * Make build work outside of source tree. "make distcheck" doesn't bomb. It doesn't run the regression tests though :-( * More documentation and doxygenization. * Remove AMIGA support :-( Version 3.80+dbg-0.4 2005-12-10 * Add eval! * Add ability to stop before reading Makefiles - may be useful in debugging macros and variables --debugger=preread. We can now trace makefile reading activity with -d r or via --trace = {read,full} * "where" command expanded to include above new Makefile read stack. * Add call tracing. * Fix bugs in showing automatic variables * Line number in Makefile commands is more accurate * More ddd (gdb/bashdb) compatible: - "help set" added - "help show" works like the others - "info locals" added - "show command" (history) added - file/line reporting more like bash/perl * write file takes basename of target file (well, at least for POSIX systems) * Update documentation quite a bit * Start to remove VMS support Version 3.80+dbg-0.3 * tracing adds GNU Make "basic" debugging. If debugging, then we also enter the debugger read loop. Hopefully this adds more granularity but not the diarrhea that "make -d" gives. To reduce this, "next" could be used to skip over remaking targets that don't have commands. * print and examine now show origin status * print/examine work for automatic variables. examine still has problems with automatic variables in strings though. * Allow abbreviations of debugger command attributes. As a result some attributes were renamed slighly, e.g. vars -> variables, deps -> depends, cmds -> commands. But note that since substrings are allowed, "command" and "com", and even "c" is the same as "commands". * Make option --trace (-x) overrules using the --silent option and not echoing @ commands. * "list" command renamed to "target". A future "list" command will look more like gdb. * fixed compilation issue(s) on systems that have readline, but do not have termcap. * fixed failure of enter_debugger to exit on an empty line from readline. * install program as remake by default (not make). * misc bug fixes and compilations fixes for various OS's Version 3.80+dbg-0.2 * Add ability to print specified attributes of a target, e.g. "time", "deps", "vars"... * Improve reporting target locations. * Improve target stack tracking. * Add "write" command - ability to write target commands to a file with MAKE variables expanded, or show that inside a debugger session. * Separate info from show. Make these act more like they do in gdb * Stay in debugger when a Makefile exits. * First debugger documentation. Version 3.80+dbg-0.1 Fork from version 3.80 * New options --extended-errors (-E) call stack reporting, extended error reporting --trace (-x) gives tracing information before a command is run. * Line numbers of commands in a target as they execute * --debugger enters debugger comamnds are execution step, next, continue, skip restart, quit, exit breakpoints break target delete target data print variable examine string up, down, frame set, setq where debugger show, info trace {on, off, toggle} help * Emacs debug interface makedb.el and a patched to gud.el remake-4.1+dbg1.3~dfsg.1/NMakefile.template000066400000000000000000000076441317072305000203760ustar00rootroot00000000000000# -*-Makefile-*- to build GNU make with nmake # # NOTE: If you have no 'make' program at all to process this makefile, # run 'build_w32.bat' instead. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . LINK = link CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile SUBPROC_MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Zi /YX /I . /I glob /I w32/include /D WIN32 /D WINDOWS32 /D _CONSOLE /D HAVE_CONFIG_H CFLAGS_debug = $(CFLAGS_any) /Od /D DEBUG /D _DEBUG /FR.\WinDebug/ /Fp.\WinDebug/make.pch /Fo.\WinDebug/ /Fd.\WinDebug/make.pdb CFLAGS_release = $(CFLAGS_any) /O2 /D NDEBUG /FR.\WinRel/ /Fp.\WinRel/make.pch /Fo.\WinRel/ LDFLAGS_debug = w32\subproc\WinDebug\subproc.lib /NOLOGO /SUBSYSTEM:console\ /INCREMENTAL:no /PDB:WinDebug/make.pdb /OUT:WinDebug/make.exe /DEBUG LDFLAGS_release = w32\subproc\WinRel\subproc.lib /NOLOGO /SUBSYSTEM:console\ /INCREMENTAL:no /OUT:WinRel/make.exe all: config.h subproc Release Debug # # Make sure we build the subproc library first. It has it's own # makefile. To be portable to Windows 95, we put the instructions # on how to build the library into a batch file. On NT, we could # simply have done foo && bar && dog, but this doesn't port. # subproc: w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib w32/subproc/WinDebug/subproc.lib w32/subproc/WinRel/subproc.lib: w32/subproc/misc.c w32/subproc/sub_proc.c w32/subproc/w32err.c subproc.bat $(SUBPROC_MAKEFILE) $(MAKE) if exist WinDebug\make.exe erase WinDebug\make.exe if exist WinRel\make.exe erase WinRel\make.exe config.h: config.h.W32 copy $? $@ Release: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_release)" CFLAGS="$(CFLAGS_release)" OUTDIR=WinRel WinRel/make.exe Debug: $(MAKE) /f $(MAKEFILE) LDFLAGS="$(LDFLAGS_debug)" CFLAGS="$(CFLAGS_debug)" OUTDIR=WinDebug WinDebug/make.exe clean: if exist WinDebug\nul rmdir /s /q WinDebug if exist WinRel\nul rmdir /s /q WinRel if exist w32\subproc\WinDebug\nul rmdir /s /q w32\subproc\WinDebug if exist w32\subproc\WinRel\nul rmdir /s /q w32\subproc\WinRel if exist config.h erase config.h erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ LIBS = kernel32.lib user32.lib advapi32.lib OBJS = \ $(OUTDIR)/ar.obj \ $(OUTDIR)/arscan.obj \ $(OUTDIR)/commands.obj \ $(OUTDIR)/default.obj \ $(OUTDIR)/dir.obj \ $(OUTDIR)/expand.obj \ $(OUTDIR)/file.obj \ $(OUTDIR)/function.obj \ $(OUTDIR)/getloadavg.obj \ $(OUTDIR)/getopt.obj \ $(OUTDIR)/getopt1.obj \ $(OUTDIR)/hash.obj \ $(OUTDIR)/implicit.obj \ $(OUTDIR)/job.obj \ $(OUTDIR)/main.obj \ $(OUTDIR)/misc.obj \ $(OUTDIR)/read.obj \ $(OUTDIR)/remake.obj \ $(OUTDIR)/remote-stub.obj \ $(OUTDIR)/rule.obj \ $(OUTDIR)/signame.obj \ $(OUTDIR)/strcache.obj \ $(OUTDIR)/variable.obj \ $(OUTDIR)/version.obj \ $(OUTDIR)/vpath.obj \ $(OUTDIR)/glob.obj \ $(OUTDIR)/fnmatch.obj \ $(OUTDIR)/dirent.obj \ $(OUTDIR)/pathstuff.obj $(OUTDIR)/make.exe: $(OUTDIR) $(OBJS) $(LINK) @<< $(LDFLAGS) $(LIBS) $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/glob.obj : glob/glob.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/fnmatch.obj : glob/fnmatch.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/dirent.obj : w32/compat/dirent.c $(CC) $(CFLAGS) /c $? $(OUTDIR)/pathstuff.obj : w32/pathstuff.c $(CC) $(CFLAGS) /c $? remake-4.1+dbg1.3~dfsg.1/README.customs000066400000000000000000000106171317072305000173540ustar00rootroot00000000000000 -*-indented-text-*- GNU make can utilize the Customs library, distributed with Pmake, to provide builds distributed across multiple hosts. In order to utilize this capability, you must first download and build the Customs library. It is contained in the Pmake distribution, which can be obtained at: ftp://ftp.icsi.berkeley.edu/pub/ai/stolcke/software/ This integration was tested (superficially) with Pmake 2.1.33. BUILDING CUSTOMS ---------------- First, build pmake and Customs. You need to build pmake first, because Customs require pmake to build. Unfortunately, this is not trivial; please see the pmake and Customs documentation for details. The best place to look for instructions is in the pmake-2.1.33/INSTALL file. Note that the 2.1.33 Pmake distribution comes with a set of patches to GNU make, distributed in the pmake-2.1.33/etc/gnumake/ directory. These patches are based on GNU make 3.75 (there are patches for earlier versions of GNU make, also). The parts of this patchfile which relate directly to Customs support have already been incorporated into this version of GNU make, so you should _NOT_ apply the patch file. However, there are a few non-Customs specific (as far as I could tell) changes here which are not incorporated (for example, the modification to try expanding -lfoo to libfoo.so). If you rely on these changes you'll need to re-apply them by hand. Install the Customs library and header files according to the documentation. You should also install the man pages (contrary to comments in the documentation, they weren't installed automatically for me; I had to cd to the 'pmake-2.1.33/doc' directory and run 'pmake install' there directly). BUILDING GNU MAKE ----------------- Once you've installed Customs, you can build GNU make to use it. When configuring GNU make, merely use the '--with-customs=DIR' option. Provide the directory containing the 'lib' and 'include/customs' subdirectories as DIR. For example, if you installed the customs library in /usr/local/lib and the headers in /usr/local/include/customs, then you'd pass '--with-customs=/usr/local' as an option to configure. Run make (or use build.sh) normally to build GNU make as described in the INSTALL file. See the documentation for Customs for information on starting and configuring Customs. INVOKING CUSTOMS-IZED GNU MAKE ----------------------------- One thing you should be aware of is that the default build environment for Customs requires root permissions. Practically, this means that GNU make must be installed setuid root to use Customs. If you don't want to do this, you can build Customs such that root permissions are not necessary. Andreas Stolcke writes: > pmake, gnumake or any other customs client program is not required to > be suid root if customs was compiled WITHOUT the USE_RESERVED_PORTS > option in customs/config.h. Make sure the "customs" service in > /etc/services is defined accordingly (port 8231 instead of 1001). > Not using USE_RESERVED_PORTS means that a user with programming > skills could impersonate another user by writing a fake customs > client that pretends to be someone other than himself. See the > discussion in etc/SECURITY. PROBLEMS -------- SunOS 4.1.x: The customs/sprite.h header file #includes the header files; this conflicts with GNU make's configuration so you'll get a compile error if you use GCC (or any other ANSI-capable C compiler). I commented out the #include in sprite.h:107: #if defined(sun) || defined(ultrix) || defined(hpux) || defined(sgi) /* #include */ #else YMMV. ------------------------------------------------------------------------------- Copyright (C) 1998-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/README.md000066400000000000000000000055541317072305000162630ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/rocky/remake.png)](https://travis-ci.org/rocky/remake) Patched GNU Make 4.1 sources to add improved error reporting, tracing, target listing, graph visualization, and profiling. It also contains debugger. See the remake-3-82 and remake-4-2 branches for patched GNU Make versions 3.82 and 4.2.1. Tracing and Debugging --------------------- Although there's a full debugger here, most of the time I can get by using no options since normal output is a little more verbose and detailed. When that isn't enough, I use the *--trace* or *-x* option, e.g: ```console $ remake -x # ... add other make options ``` But if you want the full debugger, use *--debugger* or *-X*: ```console $ remake -X # ... add other make options ``` If you want to get into the debugger only after an error is encountered use *--post-mortem*: ```console $ remake --post-mortem # ... add other make options ``` To enter the debugger from inside a Makefile, use the built-in function *$(debugger)*. For example here is a Makefile: ```makefile all: $(debugger 'arg not used') echo Nothing here, move along ``` When GNU Make is inside the *all* target, it will make a call to the debugger. The string after *debugger* is not used, but seems to be needed to get parsing right. Getting Makefile Information ---------------------------- If there is project that you want a list of "interesting" Makefile targets, try: ```console $ remake --tasks ``` If the project has commented its Makefile using remake-friendly comments you may get output like this: ``` ChangeLog # create ChangeLog fom git log via git2cl build # Do what it takes to build software locally check # Run all tests clean # Remove OS- and platform-specific derived files. dist # Create source and binary distribution distclean # Remove all derived files. Like "clean" on steroids. install # Install package test # Same as check ``` To get a list of *all* targets, interesting or not, use *--targets* instead of *--tasks*. To build from a tarball: ```console $ ./configure && make && make check && sudo make install ``` To build from git, run first: ```console $ $SHELL ./autogen.sh ``` Profiling and Visualization ---------------------------- To profile and get a graph of targets encountered used the `--profile` option. For example: ```console $ remake --profile # target... ``` *remake* outputs [callgrind profile format](http://valgrind.org/docs/manual/cl-format.html) data which can be used with [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html) or [other](https://github.com/icefox/callgrind_tools) [tools](https://github.com/zenkj/callgrind2dot) that work with this format. See also -------- See also https://github.com/rocky/remake/wiki where there are a couple of demos listed and https://github.com/rocky/remake/blob/master/profile/README.md for infomation on how to profile a "make" run. remake-4.1+dbg1.3~dfsg.1/README.remake000066400000000000000000000011511317072305000171140ustar00rootroot00000000000000See the file NEWS.remake for the user-visible changes With steady progress, this debugger for make has gotten decent with lots of room for improvement. But since it's only been me working on this, this will have to do. Although there are a number of gaps the debugger is very usable -- at least for me. It passes the standard GNU Make regression tests, and I have now added tests for the debugger. For that you need RSpec (a ruby "gem"). Documentation for the revised GNU Make Debugger is in the doc directory under the name "remake". The wiki https://github.com/rocky/remake/wiki will contain other information. remake-4.1+dbg1.3~dfsg.1/README.template000066400000000000000000000142511317072305000174700ustar00rootroot00000000000000This directory contains the %VERSION% release of GNU Make. See the file NEWS for the user-visible changes from previous releases. In addition, there have been bugs fixed. Please check the system-specific notes below for any caveats related to your operating system. For general building and installation instructions, see the file INSTALL. If you need to build GNU Make and have no other `make' program to use, you can use the shell script `build.sh' instead. To do this, first run `configure' as described in INSTALL. Then, instead of typing `make' to build the program, type `sh build.sh'. This should compile the program in the current directory. Then you will have a Make program that you can use for `./make install', or whatever else. Some systems' Make programs are broken and cannot process the Makefile for GNU Make. If you get errors from your system's Make when building GNU Make, try using `build.sh' instead. GNU Make is free software. See the file COPYING for copying conditions. Downloading ----------- GNU Make can be obtained in many different ways. See a description here: http://www.gnu.org/software/software.html Documentation ------------- GNU make is fully documented in the GNU Make manual, which is contained in this distribution as the file make.texinfo. You can also find on-line and preformatted (PostScript and DVI) versions at the FSF's web site. There is information there about ordering hardcopy documentation. http://www.gnu.org/ http://www.gnu.org/doc/doc.html http://www.gnu.org/manual/manual.html Development ----------- GNU Make development is hosted by Savannah, the FSF's online development management tool. Savannah is here: http://savannah.gnu.org And the GNU Make development page is here: http://savannah.gnu.org/projects/make/ You can find most information concerning the development of GNU Make at this site. Bug Reporting ------------- You can send GNU make bug reports to . Please see the section of the GNU make manual entitled `Problems and Bugs' for information on submitting useful and complete bug reports. You can also use the online bug tracking system in the Savannah GNU Make project to submit new problem reports or search for existing ones: http://savannah.gnu.org/bugs/?group=make If you need help using GNU make, try these forums: help-make@gnu.org help-utils@gnu.org news:gnu.utils.help news:gnu.utils.bug http://savannah.gnu.org/support/?group=make You may also find interesting patches to GNU Make available here: http://savannah.gnu.org/patch/?group=make Note these patches are provided by our users as a service and we make no statements regarding their correctness. Please contact the authors directly if you have a problem or suggestion for a patch available on this page. CVS Access ---------- The GNU make source repository is available via anonymous CVS from the GNU Subversions CVS server; look here for details: http://savannah.gnu.org/cvs/?group=make Please note: you won't be able to build GNU make from CVS without installing appropriate maintainer's tools, such as GNU m4, automake, autoconf, Perl, GNU make, and GCC. See the README.cvs file for hints on how to build GNU make once these tools are available. We make no guarantees about the contents or quality of the latest code in the CVS repository: it is not unheard of for code that is known to be broken to be checked in. Use at your own risk. System-specific Notes --------------------- It has been reported that the XLC 1.2 compiler on AIX 3.2 is buggy such that if you compile make with `cc -O' on AIX 3.2, it will not work correctly. It is said that using `cc' without `-O' does work. The standard /bin/sh on SunOS 4.1.3_U1 and 4.1.4 is broken and cannot be used to configure GNU make. Please install a different shell such as bash or pdksh in order to run "configure". See this message for more information: http://mail.gnu.org/archive/html/bug-autoconf/2003-10/msg00190.html One area that is often a problem in configuration and porting is the code to check the system's current load average. To make it easier to test and debug this code, you can do `make check-loadavg' to see if it works properly on your system. (You must run `configure' beforehand, but you need not build Make itself to run this test.) Another potential source of porting problems is the support for large files (LFS) in configure for those operating systems that provide it. Please report any bugs that you find in this area. If you run into difficulties, then as a workaround you should be able to disable LFS by adding the `--disable-largefile' option to the `configure' script. On systems that support micro- and nano-second timestamp values and where stat(2) provides this information, GNU make will use it when comparing timestamps to get the most accurate possible result. However, note that many current implementations of tools that *set* timestamps do not preserve micro- or nano-second granularity. This means that "cp -p" and other similar tools (tar, etc.) may not exactly duplicate timestamps with micro- and nano-second granularity on some systems. If your build system contains rules that depend on proper behavior of tools like "cp -p", you should consider using the .LOW_RESOLUTION_TIME pseudo-target to force make to treat them properly. See the manual for details. ------------------------------------------------------------------------------- Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/REMAKE.todo000066400000000000000000000030521317072305000166260ustar00rootroot00000000000000Most of what's here are things I know need to be done. Volunteers are welcome. I'll probably do only the things that either most interest me or I most want to have. So even though something below may be a major gap, Things marked :-( are important but something I'll probably live with. :-( Should have remote invocation interface so debugger command loop can live outside of the make environment. With this global state like breakpoints would survive across forks and subshells returns. Without that, something hacky for saving and passing state as is done in the bash debugger has to be done. For now, I'll probably live with no global state. :-( Ability to save breakpoints and debugger state on a restart. :-( Add a debugger profile mechanism. (Should be a stack of file descriptors so profiles can nest). :-( Redo command parsing. Make more like gdb. trace -> set trace set foo bar -> set variable foo = bar add set annotate :-( More debugger regression tests, existing regression tests should work. :-( Allow breakpoint on file:line. :-( MAKELEVEL seems buggy :-( "expand" doesn't handle automatic variables :-( better line info stored for commands :-( Run until recursive call? :-( breakpoint actions? :-( More sophisticated debugger inquiries such as comparing two target timestamps, listing targets that need remaking. There are probably many make-specific commands (e.g like the ones listed above). Using the debugger will probably uncover many areas. such as specialized things to trace. $Id: TODO,v 1.3 2005/11/15 01:37:45 rockyb Exp $ remake-4.1+dbg1.3~dfsg.1/Rakefile000066400000000000000000000011001317072305000164300ustar00rootroot00000000000000#!/usr/bin/env rake # -*- Ruby -*- ROOT_DIR = File.dirname(__FILE__) SPEC_FILES = FileList["#{ROOT_DIR}/tests/spec/test-*.rb"] task :default => [:test] task :check => [:test] desc 'Test everything - the default.' task :test => [:'test:basic', :'test:dbg'] desc 'The normal GNU make test suite' task :'test:basic' do sh "make check" end desc 'Install via make' task :'install' do sh "make install" end desc 'Debugger-specific tests' task :'test:dbg' do sh "rspec #{SPEC_FILES.to_a.join(' ')}" end desc 'Make ChangeLog' task :ChangeLog do sh 'make ChangeLog' end remake-4.1+dbg1.3~dfsg.1/SCOPTIONS000066400000000000000000000003031317072305000162730ustar00rootroot00000000000000ERRORREXX OPTIMIZE NOVERSION OPTIMIZERTIME OPTIMIZERALIAS DEFINE INCLUDEDIR="include:" DEFINE LIBDIR="lib:" DEFINE NO_ALLOCA DEFINE NO_FLOAT DEFINE NO_ARCHIVES IGNORE=161 IGNORE=100 STARTUP=cres remake-4.1+dbg1.3~dfsg.1/SMakefile.template000066400000000000000000000152231317072305000203730ustar00rootroot00000000000000# -*-Makefile-*- for building GNU make with smake # # NOTE: If you have no 'make' program at all to process this makefile, # run 'build.sh' instead. # # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # # Makefile for GNU Make # # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /make-%VERSION%/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /make-%VERSION%/ CC = sc RM = delete MAKE = smake CFLAGS = CPPFLAGS = LDFLAGS = # Define these for your system as follows: # -DNO_ARCHIVES To disable `ar' archive support. # -DNO_FLOAT To avoid using floating-point numbers. # -DENUM_BITFIELDS If the compiler isn't GCC but groks enum foo:2. # Some compilers apparently accept this # without complaint but produce losing code, # so beware. # NeXT 1.0a uses an old version of GCC, which required -D__inline=inline. # See also `config.h'. defines = # Which flavor of remote job execution support to use. # The code is found in `remote-$(REMOTE).c'. REMOTE = stub # If you are using the GNU C library, or have the GNU getopt functions in # your C library, you can comment these out. GETOPT = getopt.o getopt1.o GETOPT_SRC = $(srcdir)getopt.c $(srcdir)getopt1.c $(srcdir)getopt.h # If you are using the GNU C library, or have the GNU glob functions in # your C library, you can comment this out. GNU make uses special hooks # into the glob functions to be more efficient (by using make's directory # cache for globbing), so you must use the GNU functions even if your # system's C library has the 1003.2 glob functions already. Also, the glob # functions in the AIX and HPUX C libraries are said to be buggy. GLOB = Lib glob/glob.lib # If your system doesn't have alloca, or the one provided is bad, define this. ALLOCA = alloca.o ALLOCA_SRC = $(srcdir)alloca.c # If your system needs extra libraries loaded in, define them here. # System V probably need -lPW for alloca. HP-UX 7.0's alloca in # libPW.a is broken on HP9000s300 and HP9000s400 machines. Use # alloca.c instead on those machines. LOADLIBES = # Any extra object files your system needs. extras = amiga.o # Common prefix for machine-independent installed files. prefix = # Common prefix for machine-dependent installed files. exec_prefix = # Directory to install `make' in. bindir = sc:c # Directory to find libraries in for `-lXXX'. libdir = lib: # Directory to search by default for included makefiles. includedir = include: # Directory to install the Info files in. infodir = doc: # Directory to install the man page in. mandir = t: # Number to put on the man page filename. manext = 1 # Prefix to put on installed `make' binary file name. binprefix = # Prefix to put on installed `make' man page file name. manprefix = $(binprefix) # Whether or not make needs to be installed setgid. # The value should be either `true' or `false'. # On many systems, the getloadavg function (used to implement the `-l' # switch) will not work unless make is installed setgid kmem. install_setgid = false # Install make setgid to this group so it can read /dev/kmem. group = sys # Program to install `make'. INSTALL_PROGRAM = copy # Program to install the man page. INSTALL_DATA = copy # Generic install program. INSTALL = copy # Program to format Texinfo source into Info files. MAKEINFO = makeinfo # Program to format Texinfo source into DVI files. TEXI2DVI = texi2dvi # Programs to make tags files. ETAGS = etags -w CTAGS = ctags -w objs = commands.o job.o dir.o file.o misc.o main.o read.o remake.o \ rule.o implicit.o default.o variable.o expand.o function.o \ vpath.o version.o ar.o arscan.o signame.o strcache.o hash.o \ remote-$(REMOTE).o $(GLOB) $(GETOPT) $(ALLOCA) $(extras) srcs = $(srcdir)commands.c $(srcdir)job.c $(srcdir)dir.c \ $(srcdir)file.c $(srcdir)getloadavg.c $(srcdir)misc.c \ $(srcdir)main.c $(srcdir)read.c $(srcdir)remake.c \ $(srcdir)rule.c $(srcdir)implicit.c $(srcdir)default.c \ $(srcdir)variable.c $(srcdir)expand.c $(srcdir)function.c \ $(srcdir)vpath.c $(srcdir)version.c $(srcdir)hash.c \ $(srcdir)remote-$(REMOTE).c \ $(srcdir)ar.c $(srcdir)arscan.c $(srcdir)strcache.c \ $(srcdir)signame.c $(srcdir)signame.h $(GETOPT_SRC) \ $(srcdir)commands.h $(srcdir)dep.h $(srcdir)file.h \ $(srcdir)job.h $(srcdir)make.h $(srcdir)rule.h \ $(srcdir)variable.h $(ALLOCA_SRC) $(srcdir)config.h.in .SUFFIXES: .SUFFIXES: .o .c .h .ps .dvi .info .texinfo all: make info: make.info dvi: make.dvi # Some makes apparently use .PHONY as the default goal if it is before `all'. .PHONY: all check info dvi make.info: make.texinfo $(MAKEINFO) -I$(srcdir) $(srcdir)make.texinfo -o make.info make.dvi: make.texinfo $(TEXI2DVI) $(srcdir)make.texinfo make.ps: make.dvi dvi2ps make.dvi > make.ps make: $(objs) glob/glob.lib $(CC) Link $(LDFLAGS) $(objs) $(LOADLIBES) To make.new -delete quiet make rename make.new make # -I. is needed to find config.h in the build directory. .c.o: $(CC) $(defines) IDir "" IDir $(srcdir)glob \ $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) glob/glob.lib: execute << cd glob smake < tagsrcs = $(srcs) $(srcdir)remote-*.c TAGS: $(tagsrcs) $(ETAGS) $(tagsrcs) tags: $(tagsrcs) $(CTAGS) $(tagsrcs) .PHONY: install installdirs install: copy make sc:c loadavg: loadavg.c config.h $(CC) $(defines) -DTEST -I. -I$(srcdir) $(CFLAGS) $(LDFLAGS) \ loadavg.c $(LOADLIBES) -o $@ clean: glob-clean -$(RM) -f make loadavg *.o core make.dvi distclean: clean glob-realclean -$(RM) -f Makefile config.h config.status build.sh -$(RM) -f config.log config.cache -$(RM) -f TAGS tags -$(RM) -f make.?? make.??s make.log make.toc make.*aux -$(RM) -f loadavg.c realclean: distclean -$(RM) -f make.info* mostlyclean: clean .PHONY: glob-clean glob-realclean glob-clean glob-realclean: execute << cd glob smake $@ < remake-4.1+dbg1.3~dfsg.1/TODO.private000066400000000000000000000154561317072305000171470ustar00rootroot00000000000000 -*-Indented-Text-*- GNU Make TODO List ------------------ This list comes both from the authors and from users of GNU make. They are listed in no particular order! Also, I don't gaurantee that all of them will be ultimately deemed "good ideas" and implemented. These are just the ones that, at first blush, seem to have some merit (and that I can remember). However, if you see something here you really, really want, speak up. All other things being equal, I will tend to implement things that seem to maximize user satisfaction. If you want to implement some of them yourself, barring the ones I've marked below, have at it! Please contact me first to let me know you're working on it, and give me some info about the design--and, critically, information about any user-visible syntax change, etc. The Top Item ------------ If you know perl (or want to learn DejaGNU or similar), the number one priority on my list of things I don't have time to do right now is fixing up the GNU make test suite. Most importantly it needs to be made "parallelizable", so more than one regression can run at the same time (essentially, make the "work" directory local). Also, the CWD during the test should be in the work directory or, better, a test-specific temporary directory so each test gets a new directory; right now sometimes tests leak files into the main directory which causes subsequent tests to fail (some tests may need to be tweaked). Beyond that, any cleanup done to make writing, reading, or handling tests simpler would be great! Please feel free to make whatever changes you like to the current tests, given some high-level goals, and that you'll port the current tests to whatever you do :). The Rest of the List -------------------- 1) Option to check more than timestamps to determine if targets have changed. This is also a very big one. It's _close_ to my plate :), and I have very definite ideas about how I would like it done. Please pick something else unless you must have this feature. If you try it, please work _extremely_ closely with me on it. 1a) Possibly a special case of this is the .KEEP_STATE feature of Sun's make. Some great folks at W U. in Canada did an implementation of this for a class project. Their approach is reasonable and workable, but doesn't really fit into my ideas for #2. Maybe that's OK. I have paperwork for their work so if you want to do this one talk to me to get what they've already done. [K R Praveen ] 2) Currently you can use "%.foo %.bar : %.baz" to mean that one invocation of the rule builds both targets. GNU make needs a way to do that for explicit rules, too. I heard a rumor that some versions of make all you to say "a.foo + a.bar : a.baz" to do this (i.e., a "+" means one invocation builds both). Don't know if this is the best syntax or not... what if you say "a.foo + a.bar a.bam : a.baz"; what does that mean? 3) Multi-token pattern rule matching (allow %1/%2.c : %1/obj/%2.o, etc., or something like that). Maybe using regex? 4) Provide a .TARGETS variable, containing the names of the targets defined in the makefile. Actually, I now think a $(targets ...) function, at least, might be better than a MAKETARGETS variable. The argument would be types of targets to list: "phony" is the most useful one. I suppose "default" might also be useful. Maybe some others; check the bitfields to see what might be handy. 5) Some sort of operating-system independent way of handling paths would be outstanding, so makefiles can be written for UNIX, VMS, DOS, MS-Windows, Amiga, etc. with a minimum of specialization. Or, perhaps related/instead of, some sort of meta-quoting syntax so make can deal with filenames containing spaces, colons, etc. I dunno, maybe something like $[...]? This may well not be worth doing until #1 is done. 6) Right now the .PRECIOUS, .INTERMEDIATE, and .SECONDARY pseudo-targets have different capabilities. For example, .PRECIOUS can take a "%", the others can't. Etc. These should all work the same, insofar as that makes sense. 7) Improved debugging/logging/etc. capabilities. Part of this is done: I introduced a number of debugging enhancements. Tim Magill is (I think) looking into options to control output more selectively. One thing I want to do in debugging is add a flag to allow debugging of variables as they're expanded (!). This would be incredibly verbose, but could be invaluable when nothing else seems to work and you just can't figure it out. The way variables are expanded now means this isn't 100% trivial, but it probably won't be hard. 8) Integration of Guile as an embedded scripting language. This means: allowing Guile functions to be declared in makefiles somehow, then providing a syntax for invoking them. At least one formulation of that would have the function resolve to a string which would be substituted in the makefile, kind of like $(shell ...) does now, but using the embedded interpreter so there's no process forked of course. Obviously this is an optional add-on feature. It could be more advanced than that, even, who knows? Maybe make could provide Guile functions that allow Guile scripts more direct access to internal make structures, somehow. This kind of thing needs a lot of thought. Also there's always the flip side: in some very fundamental ways make isn't the best choice right now for a complex build tool. It's great for simple-to-medium tasks, but there are already other tools available for the really tough situations. Ask yourself, realistically, how much work is worthwhile to add to make, given the fundamentals you can't really overcome without significantly affecting backward compatibility--and then why not use another tool in the first place? Something to think about. ------------------------------------------------------------------------------- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/acinclude.m4000066400000000000000000000115721317072305000171720ustar00rootroot00000000000000dnl acinclude.m4 -- Extra macros needed for GNU make. dnl dnl Automake will incorporate this into its generated aclocal.m4. dnl Copyright (C) 1998-2014 Free Software Foundation, Inc. dnl This file is part of GNU Make. dnl dnl GNU Make is free software; you can redistribute it and/or modify it under dnl the terms of the GNU General Public License as published by the Free dnl Software Foundation; either version 3 of the License, or (at your option) dnl any later version. dnl dnl GNU Make is distributed in the hope that it will be useful, but WITHOUT dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. dnl more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program. If not, see . dnl --------------------------------------------------------------------------- dnl Got this from the lynx 2.8 distribution. dnl by T.E.Dickey dnl and Jim Spath dnl and Philippe De Muyter dnl dnl Created: 1997/1/28 dnl Updated: 1997/12/23 dnl --------------------------------------------------------------------------- dnl After checking for functions in the default $LIBS, make a further check dnl for the functions that are netlib-related (these aren't always in the dnl libc, etc., and have to be handled specially because there are conflicting dnl and broken implementations. dnl Common library requirements (in order): dnl -lresolv -lsocket -lnsl dnl -lnsl -lsocket dnl -lsocket dnl -lbsd AC_DEFUN([CF_NETLIBS],[ cf_test_netlibs=no AC_MSG_CHECKING(for network libraries) AC_CACHE_VAL(cf_cv_netlibs,[ AC_MSG_RESULT(working...) cf_cv_netlibs="" cf_test_netlibs=yes AC_CHECK_FUNCS(gethostname,,[ CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[ CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])]) # # FIXME: sequent needs this library (i.e., -lsocket -linet -lnsl), but # I don't know the entrypoints - 97/7/22 TD AC_CHECK_LIB(inet,main,cf_cv_netlibs="-linet $cf_cv_netlibs") # if test "$ac_cv_func_lsocket" != no ; then AC_CHECK_FUNCS(socket,,[ CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[ CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])]) fi # AC_CHECK_FUNCS(gethostbyname,,[ CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)]) ]) LIBS="$LIBS $cf_cv_netlibs" test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG ])dnl dnl --------------------------------------------------------------------------- dnl Re-check on a function to see if we can pick it up by adding a library. dnl $1 = function to check dnl $2 = library to check in dnl $3 = environment to update (e.g., $LIBS) dnl $4 = what to do if this fails dnl dnl This uses 'unset' if the shell happens to support it, but leaves the dnl configuration variable set to 'unknown' if not. This is a little better dnl than the normal autoconf test, which gives misleading results if a test dnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is dnl used (autoconf does not distinguish between a null token and one that is dnl set to 'no'). AC_DEFUN([CF_RECHECK_FUNC],[ AC_CHECK_LIB($2,$1,[ CF_UPPER(cf_tr_func,$1) AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func,1,[Define if you have function $1]) ac_cv_func_$1=yes $3="-l$2 [$]$3"],[ ac_cv_func_$1=unknown unset ac_cv_func_$1 2>/dev/null $4], [[$]$3]) ])dnl dnl --------------------------------------------------------------------------- dnl Make an uppercase version of a variable dnl $1=uppercase($2) AC_DEFUN([CF_UPPER], [ changequote(,)dnl $1=`echo $2 | tr '[a-z]' '[A-Z]'` changequote([,])dnl ])dnl dnl --------------------------------------------------------------------------- dnl From Paul Eggert dnl Update for Darwin by Troy Runkel dnl Update for AIX by Olexiy Buyanskyy (Savannah bug 32485) AC_DEFUN([AC_STRUCT_ST_MTIM_NSEC], [AC_CACHE_CHECK([for nanoseconds field of struct stat], ac_cv_struct_st_mtim_nsec, [ac_save_CPPFLAGS="$CPPFLAGS" ac_cv_struct_st_mtim_nsec=no # st_mtim.tv_nsec -- the usual case # st_mtim._tv_nsec -- Solaris 2.6, if # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1 # && !defined __EXTENSIONS__) # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2 # st_mtime_n -- AIX 5.2 and above # st_mtimespec.tv_nsec -- Darwin (Mac OSX) for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val" AC_TRY_COMPILE([#include #include ], [struct stat s; s.ST_MTIM_NSEC;], [ac_cv_struct_st_mtim_nsec=$ac_val; break]) done CPPFLAGS="$ac_save_CPPFLAGS" ]) if test $ac_cv_struct_st_mtim_nsec != no; then AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec], [Define if struct stat contains a nanoseconds field]) fi ] ) remake-4.1+dbg1.3~dfsg.1/alloc.c000066400000000000000000000043671317072305000162430ustar00rootroot00000000000000/* Miscellaneous allocations functions for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" /* Like malloc but get fatal error if memory is exhausted. */ /* Don't bother if we're using dmalloc; it provides these for us. */ #ifndef HAVE_DMALLOC_H #undef xmalloc #undef xcalloc #undef xrealloc #undef xstrdup void * xmalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = malloc (size ? size : 1); if (result == 0) OUT_OF_MEM(); return result; } void * xcalloc (unsigned int size) { /* Make sure we don't allocate 0, for pre-ISO implementations. */ void *result = calloc (size ? size : 1, 1); if (result == 0) OUT_OF_MEM(); return result; } void * xrealloc (void *ptr, unsigned int size) { void *result; /* Some older implementations of realloc() don't conform to ISO. */ if (! size) size = 1; result = ptr ? realloc (ptr, size) : malloc (size); if (result == 0) OUT_OF_MEM(); return result; } char * xstrdup (const char *ptr) { char *result; #ifdef HAVE_STRDUP result = strdup (ptr); #else result = malloc (strlen (ptr) + 1); #endif if (result == 0) OUT_OF_MEM(); #ifdef HAVE_STRDUP return result; #else return strcpy (result, ptr); #endif } #endif /* HAVE_DMALLOC_H */ char * xstrndup (const char *str, unsigned int length) { char *result; #ifdef HAVE_STRNDUP result = strndup (str, length); if (result == 0) OUT_OF_MEM(); #else result = xmalloc (length + 1); if (length > 0) strncpy (result, str, length); result[length] = '\0'; #endif return result; } remake-4.1+dbg1.3~dfsg.1/alloca.c000066400000000000000000000336271317072305000164050ustar00rootroot00000000000000/* alloca.c -- allocate automatically reclaimed memory (Mostly) portable public-domain implementation -- D A Gwyn This implementation of the PWB library alloca function, which is used to allocate space off the run-time stack so that it is automatically reclaimed upon procedure exit, was inspired by discussions with J. Q. Johnson of Cornell. J.Otto Tennant contributed the Cray support. There are some preprocessor constants that can be defined when compiling for your specific system, for improved efficiency; however, the defaults should be okay. The general concept of this implementation is to keep track of all alloca-allocated blocks, and reclaim any that are found to be deeper in the stack than the current invocation. This heuristic does not reclaim storage as soon as it becomes invalid, but it will do so eventually. As a special case, alloca(0) reclaims storage without allocating any. It is a good idea to use alloca(0) in your main control loop, etc. to force garbage collection. */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef emacs #include "blockinput.h" #endif /* If compiling with GCC 2, this file's not needed. */ #if !defined (__GNUC__) || __GNUC__ < 2 /* If someone has defined alloca as a macro, there must be some other way alloca is supposed to work. */ #ifndef alloca #ifdef emacs #ifdef static /* actually, only want this if static is defined as "" -- this is for usg, in which emacs must undefine static in order to make unexec workable */ #ifndef STACK_DIRECTION you lose -- must know STACK_DIRECTION at compile-time #endif /* STACK_DIRECTION undefined */ #endif /* static */ #endif /* emacs */ /* If your stack is a linked list of frames, you have to provide an "address metric" ADDRESS_FUNCTION macro. */ #if defined (CRAY) && defined (CRAY_STACKSEG_END) long i00afunc (); #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) #else #define ADDRESS_FUNCTION(arg) &(arg) #endif #if __STDC__ typedef void *pointer; #else typedef char *pointer; #endif #ifndef NULL #define NULL 0 #endif /* Different portions of Emacs need to call different versions of malloc. The Emacs executable needs alloca to call xmalloc, because ordinary malloc isn't protected from input signals. On the other hand, the utilities in lib-src need alloca to call malloc; some of them are very simple, and don't have an xmalloc routine. Non-Emacs programs expect this to call use xmalloc. Callers below should use malloc. */ #ifndef emacs #define malloc xmalloc #endif extern pointer malloc (); /* Define STACK_DIRECTION if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #ifndef STACK_DIRECTION #define STACK_DIRECTION 0 /* Direction unknown. */ #endif #if STACK_DIRECTION != 0 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ #else /* STACK_DIRECTION == 0; need run-time code. */ static int stack_dir; /* 1 or -1 once known. */ #define STACK_DIR stack_dir static void find_stack_direction (void) { static char *addr = NULL; /* Address of first 'dummy', once known. */ auto char dummy; /* To get stack address. */ if (addr == NULL) { /* Initial entry. */ addr = ADDRESS_FUNCTION (dummy); find_stack_direction (); /* Recurse once. */ } else { /* Second entry. */ if (ADDRESS_FUNCTION (dummy) > addr) stack_dir = 1; /* Stack grew upward. */ else stack_dir = -1; /* Stack grew downward. */ } } #endif /* STACK_DIRECTION == 0 */ /* An "alloca header" is used to: (a) chain together all alloca'ed blocks; (b) keep track of stack depth. It is very important that sizeof(header) agree with malloc alignment chunk size. The following default should work okay. */ #ifndef ALIGN_SIZE #define ALIGN_SIZE sizeof(double) #endif typedef union hdr { char align[ALIGN_SIZE]; /* To force sizeof(header). */ struct { union hdr *next; /* For chaining headers. */ char *deep; /* For stack depth measure. */ } h; } header; static header *last_alloca_header = NULL; /* -> last alloca header. */ /* Return a pointer to at least SIZE bytes of storage, which will be automatically reclaimed upon exit from the procedure that called alloca. Originally, this space was supposed to be taken from the current stack frame of the caller, but that method cannot be made to work for some implementations of C, for example under Gould's UTX/32. */ pointer alloca (unsigned size) { auto char probe; /* Probes stack depth: */ register char *depth = ADDRESS_FUNCTION (probe); #if STACK_DIRECTION == 0 if (STACK_DIR == 0) /* Unknown growth direction. */ find_stack_direction (); #endif /* Reclaim garbage, defined as all alloca'd storage that was allocated from deeper in the stack than currently. */ { register header *hp; /* Traverses linked list. */ #ifdef emacs BLOCK_INPUT; #endif for (hp = last_alloca_header; hp != NULL;) if ((STACK_DIR > 0 && hp->h.deep > depth) || (STACK_DIR < 0 && hp->h.deep < depth)) { register header *np = hp->h.next; free ((pointer) hp); /* Collect garbage. */ hp = np; /* -> next header. */ } else break; /* Rest are not deeper. */ last_alloca_header = hp; /* -> last valid storage. */ #ifdef emacs UNBLOCK_INPUT; #endif } if (size == 0) return NULL; /* No allocation required. */ /* Allocate combined header + user data storage. */ { register pointer new = malloc (sizeof (header) + size); /* Address of header. */ if (new == 0) abort(); ((header *) new)->h.next = last_alloca_header; ((header *) new)->h.deep = depth; last_alloca_header = (header *) new; /* User storage begins just after header. */ return (pointer) ((char *) new + sizeof (header)); } } #if defined (CRAY) && defined (CRAY_STACKSEG_END) #ifdef DEBUG_I00AFUNC #include #endif #ifndef CRAY_STACK #define CRAY_STACK #ifndef CRAY2 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ struct stack_control_header { long shgrow:32; /* Number of times stack has grown. */ long shaseg:32; /* Size of increments to stack. */ long shhwm:32; /* High water mark of stack. */ long shsize:32; /* Current size of stack (all segments). */ }; /* The stack segment linkage control information occurs at the high-address end of a stack segment. (The stack grows from low addresses to high addresses.) The initial part of the stack segment linkage control information is 0200 (octal) words. This provides for register storage for the routine which overflows the stack. */ struct stack_segment_linkage { long ss[0200]; /* 0200 overflow words. */ long sssize:32; /* Number of words in this segment. */ long ssbase:32; /* Offset to stack base. */ long:32; long sspseg:32; /* Offset to linkage control of previous segment of stack. */ long:32; long sstcpt:32; /* Pointer to task common address block. */ long sscsnm; /* Private control structure number for microtasking. */ long ssusr1; /* Reserved for user. */ long ssusr2; /* Reserved for user. */ long sstpid; /* Process ID for pid based multi-tasking. */ long ssgvup; /* Pointer to multitasking thread giveup. */ long sscray[7]; /* Reserved for Cray Research. */ long ssa0; long ssa1; long ssa2; long ssa3; long ssa4; long ssa5; long ssa6; long ssa7; long sss0; long sss1; long sss2; long sss3; long sss4; long sss5; long sss6; long sss7; }; #else /* CRAY2 */ /* The following structure defines the vector of words returned by the STKSTAT library routine. */ struct stk_stat { long now; /* Current total stack size. */ long maxc; /* Amount of contiguous space which would be required to satisfy the maximum stack demand to date. */ long high_water; /* Stack high-water mark. */ long overflows; /* Number of stack overflow ($STKOFEN) calls. */ long hits; /* Number of internal buffer hits. */ long extends; /* Number of block extensions. */ long stko_mallocs; /* Block allocations by $STKOFEN. */ long underflows; /* Number of stack underflow calls ($STKRETN). */ long stko_free; /* Number of deallocations by $STKRETN. */ long stkm_free; /* Number of deallocations by $STKMRET. */ long segments; /* Current number of stack segments. */ long maxs; /* Maximum number of stack segments so far. */ long pad_size; /* Stack pad size. */ long current_address; /* Current stack segment address. */ long current_size; /* Current stack segment size. This number is actually corrupted by STKSTAT to include the fifteen word trailer area. */ long initial_address; /* Address of initial segment. */ long initial_size; /* Size of initial segment. */ }; /* The following structure describes the data structure which trails any stack segment. I think that the description in 'asdef' is out of date. I only describe the parts that I am sure about. */ struct stk_trailer { long this_address; /* Address of this block. */ long this_size; /* Size of this block (does not include this trailer). */ long unknown2; long unknown3; long link; /* Address of trailer block of previous segment. */ long unknown5; long unknown6; long unknown7; long unknown8; long unknown9; long unknown10; long unknown11; long unknown12; long unknown13; long unknown14; }; #endif /* CRAY2 */ #endif /* not CRAY_STACK */ #ifdef CRAY2 /* Determine a "stack measure" for an arbitrary ADDRESS. I doubt that "lint" will like this much. */ static long i00afunc (long *address) { struct stk_stat status; struct stk_trailer *trailer; long *block, size; long result = 0; /* We want to iterate through all of the segments. The first step is to get the stack status structure. We could do this more quickly and more directly, perhaps, by referencing the $LM00 common block, but I know that this works. */ STKSTAT (&status); /* Set up the iteration. */ trailer = (struct stk_trailer *) (status.current_address + status.current_size - 15); /* There must be at least one stack segment. Therefore it is a fatal error if "trailer" is null. */ if (trailer == 0) abort (); /* Discard segments that do not contain our argument address. */ while (trailer != 0) { block = (long *) trailer->this_address; size = trailer->this_size; if (block == 0 || size == 0) abort (); trailer = (struct stk_trailer *) trailer->link; if ((block <= address) && (address < (block + size))) break; } /* Set the result to the offset in this segment and add the sizes of all predecessor segments. */ result = address - block; if (trailer == 0) { return result; } do { if (trailer->this_size <= 0) abort (); result += trailer->this_size; trailer = (struct stk_trailer *) trailer->link; } while (trailer != 0); /* We are done. Note that if you present a bogus address (one not in any segment), you will get a different number back, formed from subtracting the address of the first block. This is probably not what you want. */ return (result); } #else /* not CRAY2 */ /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. Determine the number of the cell within the stack, given the address of the cell. The purpose of this routine is to linearize, in some sense, stack addresses for alloca. */ static long i00afunc (long address) { long stkl = 0; long size, pseg, this_segment, stack; long result = 0; struct stack_segment_linkage *ssptr; /* Register B67 contains the address of the end of the current stack segment. If you (as a subprogram) store your registers on the stack and find that you are past the contents of B67, you have overflowed the segment. B67 also points to the stack segment linkage control area, which is what we are really interested in. */ stkl = CRAY_STACKSEG_END (); ssptr = (struct stack_segment_linkage *) stkl; /* If one subtracts 'size' from the end of the segment, one has the address of the first word of the segment. If this is not the first segment, 'pseg' will be nonzero. */ pseg = ssptr->sspseg; size = ssptr->sssize; this_segment = stkl - size; /* It is possible that calling this routine itself caused a stack overflow. Discard stack segments which do not contain the target address. */ while (!(this_segment <= address && address <= stkl)) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); #endif if (pseg == 0) break; stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; this_segment = stkl - size; } result = address - this_segment; /* If you subtract pseg from the current end of the stack, you get the address of the previous stack segment's end. This seems a little convoluted to me, but I'll bet you save a cycle somewhere. */ while (pseg != 0) { #ifdef DEBUG_I00AFUNC fprintf (stderr, "%011o %011o\n", pseg, size); #endif stkl = stkl - pseg; ssptr = (struct stack_segment_linkage *) stkl; size = ssptr->sssize; pseg = ssptr->sspseg; result += size; } return (result); } #endif /* not CRAY2 */ #endif /* CRAY */ #endif /* no alloca */ #endif /* not GCC version 2 */ remake-4.1+dbg1.3~dfsg.1/ar.c000066400000000000000000000213341317072305000155440ustar00rootroot00000000000000/* Interface to 'ar' archives for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #ifndef NO_ARCHIVES #include "filedef.h" #include "dep.h" #include /* Return nonzero if NAME is an archive-member reference, zero if not. An archive-member reference is a name like 'lib(member)' where member is a non-empty string. If a name like 'lib((entry))' is used, a fatal error is signaled at the attempt to use this unsupported feature. */ int ar_name (const char *name) { const char *p = strchr (name, '('); const char *end; if (p == 0 || p == name) return 0; end = p + strlen (p) - 1; if (*end != ')' || end == p + 1) return 0; if (p[1] == '(' && end[-1] == ')') OS (fatal, NILF, _("attempt to use unsupported feature: '%s'"), name); return 1; } /* Parse the archive-member reference NAME into the archive and member names. Creates one allocated string containing both names, pointed to by ARNAME_P. MEMNAME_P points to the member. */ void ar_parse_name (const char *name, char **arname_p, char **memname_p) { char *p; *arname_p = xstrdup (name); p = strchr (*arname_p, '('); *(p++) = '\0'; p[strlen (p) - 1] = '\0'; *memname_p = p; } /* This function is called by 'ar_scan' to find which member to look at. */ struct member_date_lookup { const char *name; time_t *member_date; }; /* ARGSUSED */ static long int ar_member_date_1 (int desc UNUSED, const char *mem, int truncated, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *data) { const struct member_date_lookup *lookup_data = data; if (ar_name_equal (lookup_data->name, mem, truncated)) { *lookup_data->member_date = date; return 1; } return 0; } /* Read the modtime of NAME in MEMBER_DATE. Returns 1 if NAME exists, 0 otherwise. */ int ar_member_date (const char *name, time_t *member_date) { char *arname; char *memname; int found; struct member_date_lookup lookup_data; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself because we are likely to be called just before commands to remake a member are run, and they will change the archive itself. But we must be careful not to enter_file the archive itself if it does not exist, because pattern_search assumes that files found in the data base exist or can be made. */ { struct file *arfile; arfile = lookup_file (arname); if (arfile == 0 && file_exists_p (arname)) arfile = enter_file (strcache_add (arname)); if (arfile != 0) (void) f_mtime (arfile, 0); } lookup_data.name = memname; lookup_data.member_date = member_date; found = ar_scan (arname, ar_member_date_1, &lookup_data); free (arname); /* return 0 (not found) if the archive does not exist or has invalid format. */ return (found == 1) ? 1 : 0; } /* Set the archive-member NAME's modtime to now. */ #ifdef VMS int ar_touch (const char *name) { O (error, NILF, _("touch archive member is not available on VMS")); return -1; } #else int ar_touch (const char *name) { char *arname, *memname; int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself before we touch the member, since this will change the archive modtime. */ { struct file *arfile; arfile = enter_file (strcache_add (arname)); f_mtime (arfile, 0); } val = 1; switch (ar_member_touch (arname, memname)) { case -1: OS (error, NILF, _("touch: Archive '%s' does not exist"), arname); break; case -2: OS (error, NILF, _("touch: '%s' is not a valid archive"), arname); break; case -3: perror_with_name ("touch: ", arname); break; case 1: OSS (error, NILF, _("touch: Member '%s' does not exist in '%s'"), memname, arname); break; case 0: val = 0; break; default: OS (error, NILF, _("touch: Bad return code from ar_member_touch on '%s'"), name); } free (arname); return val; } #endif /* !VMS */ /* State of an 'ar_glob' run, passed to 'ar_glob_match'. */ /* On VMS, (object) modules in libraries do not have suffixes. That is, to find a match for a pattern, the pattern must not have any suffix. So the suffix of the pattern is saved and the pattern is stripped (ar_glob). If there is a match and the match, which is a module name, is added to the chain, the saved suffix is added back to construct a source filename (ar_glob_match). */ struct ar_glob_state { const char *arname; const char *pattern; #ifdef VMS char *suffix; #endif unsigned int size; struct nameseq *chain; unsigned int n; }; /* This function is called by 'ar_scan' to match one archive element against the pattern in STATE. */ static long int ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED, long int hdrpos UNUSED, long int datapos UNUSED, long int size UNUSED, long int date UNUSED, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *arg) { struct ar_glob_state *state = (struct ar_glob_state *)arg; if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) { /* We have a match. Add it to the chain. */ struct nameseq *new = xcalloc (state->size); #ifdef VMS if (state->suffix) new->name = strcache_add( concat(5, state->arname, "(", mem, state->suffix, ")")); else #endif new->name = strcache_add(concat(4, state->arname, "(", mem, ")")); new->next = state->chain; state->chain = new; ++state->n; } return 0L; } /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ static int glob_pattern_p (const char *pattern, int quote) { const char *p; int opened = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote) ++p; break; case '[': opened = 1; break; case ']': if (opened) return 1; break; } return 0; } /* Glob for MEMBER_PATTERN in archive ARNAME. Return a malloc'd chain of matching elements (or nil if none). */ struct nameseq * ar_glob (const char *arname, const char *member_pattern, unsigned int size) { struct ar_glob_state state; struct nameseq *n; const char **names; unsigned int i; #ifdef VMS char *vms_member_pattern; #endif if (! glob_pattern_p (member_pattern, 1)) return 0; /* Scan the archive for matches. ar_glob_match will accumulate them in STATE.chain. */ state.arname = arname; state.pattern = member_pattern; #ifdef VMS { /* In a copy of the pattern, find the suffix, save it and remove it from the pattern */ char *lastdot; vms_member_pattern = xstrdup(member_pattern); lastdot = strrchr(vms_member_pattern, '.'); state.suffix = lastdot; if (lastdot) { state.suffix = xstrdup(lastdot); *lastdot = 0; } state.pattern = vms_member_pattern; } #endif state.size = size; state.chain = 0; state.n = 0; ar_scan (arname, ar_glob_match, &state); #ifdef VMS /* Deallocate any duplicated string */ free(vms_member_pattern); if (state.suffix) { free(state.suffix); } #endif if (state.chain == 0) return 0; /* Now put the names into a vector for sorting. */ names = alloca (state.n * sizeof (const char *)); i = 0; for (n = state.chain; n != 0; n = n->next) names[i++] = n->name; /* Sort them alphabetically. */ /* MSVC erroneously warns without a cast here. */ qsort ((void *)names, i, sizeof (*names), alpha_compare); /* Put them back into the chain in the sorted order. */ i = 0; for (n = state.chain; n != 0; n = n->next) n->name = names[i++]; return state.chain; } #endif /* Not NO_ARCHIVES. */ remake-4.1+dbg1.3~dfsg.1/arscan.c000066400000000000000000000551701317072305000164160ustar00rootroot00000000000000/* Library function for scanning an archive file. Copyright (C) 1987-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #ifdef TEST /* Hack, the real error() routine eventually pulls in die from main.c */ #define error(a, b, c, d) #endif #ifdef HAVE_FCNTL_H #include #else #include #endif #ifndef NO_ARCHIVES #ifdef VMS #include #include #include #include #include #include #include #include globalvalue unsigned int LBR$_HDRTRUNC; #include #include /* Takes three arguments ARCHIVE, FUNCTION and ARG. Open the archive named ARCHIVE, find its members one by one, and for each one call FUNCTION with the following arguments: archive file descriptor for reading the data, member name, member name might be truncated flag, member header position in file, member data position in file, member data size, member date, member uid, member gid, member protection mode, ARG. NOTE: on VMS systems, only name, date, and arg are meaningful! The descriptor is poised to read the data of the member when FUNCTION is called. It does not matter how much data FUNCTION reads. If FUNCTION returns nonzero, we immediately return what FUNCTION returned. Returns -1 if archive does not exist, Returns -2 if archive has invalid format. Returns 0 if have scanned successfully. */ long int ar_scan (const char *archive, ar_member_func_t function, const void *varg) { char *vms_archive; static struct dsc$descriptor_s libdesc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; const unsigned long func = LBR$C_READ; const unsigned long type = LBR$C_TYP_UNK; const unsigned long index = 1; unsigned long lib_idx; int status; VMS_saved_arg = varg; /* Null archive string can show up in test and cause an access violation */ if (archive == NULL) { /* Null filenames do not exist */ return -1; } /* archive path name must be in VMS format */ vms_archive = (char *) vmsify(archive, 0); status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0); if (!$VMS_STATUS_SUCCESS(status)) { ON(error, NILF, _("lbr$ini_control() failed with status = %d"), status); return -2; } libdesc.dsc$a_pointer = vms_archive; libdesc.dsc$w_length = strlen(vms_archive); status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0); if (!$VMS_STATUS_SUCCESS(status)) { /* TODO: A library format failure could mean that this is a file generated by the GNU AR utility and in that case, we need to take the UNIX codepath. This will also take a change to the GNV AR wrapper program. */ switch (status) { case RMS$_FNF: /* Archive does not exist */ return -1; default: #ifndef TEST OSN(error, NILF, _("unable to open library '%s' to lookup member status %d"), archive, status); #endif /* For library format errors, specification says to return -2 */ return -2; } } VMS_function = function; /* Clear the return status, as we are supposed to stop calling the callback function if it becomes non-zero, and this is a static variable. */ VMS_function_ret = 0; status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0); lbr$close(&VMS_lib_idx); /* Unless a failure occurred in the lbr$ routines, return the the status from the 'function' routine. */ if ($VMS_STATUS_SUCCESS(status)) { return VMS_function_ret; } /* This must be something wrong with the library and an error message should already have been printed. */ return -2; } #else /* !VMS */ /* SCO Unix's compiler defines both of these. */ #ifdef M_UNIX #undef M_XENIX #endif /* On the sun386i and in System V rel 3, ar.h defines two different archive formats depending upon whether you have defined PORTAR (normal) or PORT5AR (System V Release 1). There is no default, one or the other must be defined to have a nonzero value. */ #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0) #undef PORTAR #ifdef M_XENIX /* According to Jim Sievert , for SCO XENIX defining PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the right one. */ #define PORTAR 0 #else #define PORTAR 1 #endif #endif /* On AIX, define these symbols to be sure to get both archive formats. AIX 4.3 introduced the "big" archive format to support 64-bit object files, so on AIX 4.3 systems we need to support both the "normal" and "big" archive formats. An archive's format is indicated in the "fl_magic" field of the "FL_HDR" structure. For a normal archive, this field will be the string defined by the AIAMAG symbol. For a "big" archive, it will be the string defined by the AIAMAGBIG symbol (at least on AIX it works this way). Note: we'll define these symbols regardless of which AIX version we're compiling on, but this is okay since we'll use the new symbols only if they're present. */ #ifdef _AIX # define __AR_SMALL__ # define __AR_BIG__ #endif #ifndef WINDOWS32 # if !defined (__ANDROID__) && !defined (__BEOS__) # include # else /* These platforms don't have but have archives in the same format * as many other Unices. This was taken from GNU binutils for BeOS. */ # define ARMAG "!\n" /* String that begins an archive file. */ # define SARMAG 8 /* Size of that string. */ # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */ struct ar_hdr { char ar_name[16]; /* Member file name, sometimes / terminated. */ char ar_date[12]; /* File date, decimal seconds since Epoch. */ char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ char ar_mode[8]; /* File mode, in ASCII octal. */ char ar_size[10]; /* File size, in ASCII decimal. */ char ar_fmag[2]; /* Always contains ARFMAG. */ }; # endif # define TOCHAR(_m) (_m) #else /* These should allow us to read Windows (VC++) libraries (according to Frank * Libbrecht ) */ # include # include # include # define ARMAG IMAGE_ARCHIVE_START # define SARMAG IMAGE_ARCHIVE_START_SIZE # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER # define ar_name Name # define ar_mode Mode # define ar_size Size # define ar_date Date # define ar_uid UserID # define ar_gid GroupID /* In Windows the member names have type BYTE so we must cast them. */ # define TOCHAR(_m) ((char *)(_m)) #endif /* Cray's apparently defines this. */ #ifndef AR_HDR_SIZE # define AR_HDR_SIZE (sizeof (struct ar_hdr)) #endif /* Takes three arguments ARCHIVE, FUNCTION and ARG. Open the archive named ARCHIVE, find its members one by one, and for each one call FUNCTION with the following arguments: archive file descriptor for reading the data, member name, member name might be truncated flag, member header position in file, member data position in file, member data size, member date, member uid, member gid, member protection mode, ARG. The descriptor is poised to read the data of the member when FUNCTION is called. It does not matter how much data FUNCTION reads. If FUNCTION returns nonzero, we immediately return what FUNCTION returned. Returns -1 if archive does not exist, Returns -2 if archive has invalid format. Returns 0 if have scanned successfully. */ long int ar_scan (const char *archive, ar_member_func_t function, const void *arg) { #ifdef AIAMAG FL_HDR fl_header; # ifdef AIAMAGBIG int big_archive = 0; FL_HDR_BIG fl_header_big; # endif #endif char *namemap = 0; int desc = open (archive, O_RDONLY, 0); if (desc < 0) return -1; #ifdef SARMAG { char buf[SARMAG]; register int nread = read (desc, buf, SARMAG); if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG)) { (void) close (desc); return -2; } } #else #ifdef AIAMAG { register int nread = read (desc, &fl_header, FL_HSZ); if (nread != FL_HSZ) { (void) close (desc); return -2; } #ifdef AIAMAGBIG /* If this is a "big" archive, then set the flag and re-read the header into the "big" structure. */ if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG)) { big_archive = 1; /* seek back to beginning of archive */ if (lseek (desc, 0, 0) < 0) { (void) close (desc); return -2; } /* re-read the header into the "big" structure */ nread = read (desc, &fl_header_big, FL_HSZ_BIG); if (nread != FL_HSZ_BIG) { (void) close (desc); return -2; } } else #endif /* Check to make sure this is a "normal" archive. */ if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG)) { (void) close (desc); return -2; } } #else { #ifndef M_XENIX int buf; #else unsigned short int buf; #endif register int nread = read (desc, &buf, sizeof (buf)); if (nread != sizeof (buf) || buf != ARMAG) { (void) close (desc); return -2; } } #endif #endif /* Now find the members one by one. */ { #ifdef SARMAG register long int member_offset = SARMAG; #else #ifdef AIAMAG long int member_offset; long int last_member_offset; #ifdef AIAMAGBIG if ( big_archive ) { sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset); sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset); } else #endif { sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset); sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset); } if (member_offset == 0) { /* Empty archive. */ close (desc); return 0; } #else register long int member_offset = sizeof (int); #endif #endif while (1) { register int nread; struct ar_hdr member_header; #ifdef AIAMAGBIG struct ar_hdr_big member_header_big; #endif #ifdef AIAMAG char name[256]; int name_len; long int dateval; int uidval, gidval; long int data_offset; #else char namebuf[sizeof member_header.ar_name + 1]; char *name; int is_namemap; /* Nonzero if this entry maps long names. */ int long_name = 0; #endif long int eltsize; unsigned int eltmode; long int fnval; if (lseek (desc, member_offset, 0) < 0) { (void) close (desc); return -2; } #ifdef AIAMAG #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name)) #ifdef AIAMAGBIG if (big_archive) { nread = read (desc, &member_header_big, AR_MEMHDR_SZ(member_header_big) ); if (nread != AR_MEMHDR_SZ(member_header_big)) { (void) close (desc); return -2; } sscanf (member_header_big.ar_namlen, "%4d", &name_len); nread = read (desc, name, name_len); if (nread != name_len) { (void) close (desc); return -2; } name[name_len] = 0; sscanf (member_header_big.ar_date, "%12ld", &dateval); sscanf (member_header_big.ar_uid, "%12d", &uidval); sscanf (member_header_big.ar_gid, "%12d", &gidval); sscanf (member_header_big.ar_mode, "%12o", &eltmode); sscanf (member_header_big.ar_size, "%20ld", &eltsize); data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big) + name_len + 2); } else #endif { nread = read (desc, &member_header, AR_MEMHDR_SZ(member_header) ); if (nread != AR_MEMHDR_SZ(member_header)) { (void) close (desc); return -2; } sscanf (member_header.ar_namlen, "%4d", &name_len); nread = read (desc, name, name_len); if (nread != name_len) { (void) close (desc); return -2; } name[name_len] = 0; sscanf (member_header.ar_date, "%12ld", &dateval); sscanf (member_header.ar_uid, "%12d", &uidval); sscanf (member_header.ar_gid, "%12d", &gidval); sscanf (member_header.ar_mode, "%12o", &eltmode); sscanf (member_header.ar_size, "%12ld", &eltsize); data_offset = (member_offset + AR_MEMHDR_SZ(member_header) + name_len + 2); } data_offset += data_offset % 2; fnval = (*function) (desc, name, 0, member_offset, data_offset, eltsize, dateval, uidval, gidval, eltmode, arg); #else /* Not AIAMAG. */ nread = read (desc, &member_header, AR_HDR_SIZE); if (nread == 0) /* No data left means end of file; that is OK. */ break; if (nread != AR_HDR_SIZE #if defined(ARFMAG) || defined(ARFZMAG) || ( # ifdef ARFMAG memcmp (member_header.ar_fmag, ARFMAG, 2) # else 1 # endif && # ifdef ARFZMAG memcmp (member_header.ar_fmag, ARFZMAG, 2) # else 1 # endif ) #endif ) { (void) close (desc); return -2; } name = namebuf; memcpy (name, member_header.ar_name, sizeof member_header.ar_name); { register char *p = name + sizeof member_header.ar_name; do *p = '\0'; while (p > name && *--p == ' '); #ifndef AIAMAG /* If the member name is "//" or "ARFILENAMES/" this may be a list of file name mappings. The maximum file name length supported by the standard archive format is 14 characters. This member will actually always be the first or second entry in the archive, but we don't check that. */ is_namemap = (!strcmp (name, "//") || !strcmp (name, "ARFILENAMES/")); #endif /* Not AIAMAG. */ /* On some systems, there is a slash after each member name. */ if (*p == '/') *p = '\0'; #ifndef AIAMAG /* If the member name starts with a space or a slash, this is an index into the file name mappings (used by GNU ar). Otherwise if the member name looks like #1/NUMBER the real member name appears in the element data (used by 4.4BSD). */ if (! is_namemap && (name[0] == ' ' || name[0] == '/') && namemap != 0) { name = namemap + atoi (name + 1); long_name = 1; } else if (name[0] == '#' && name[1] == '1' && name[2] == '/') { int namesize = atoi (name + 3); name = alloca (namesize + 1); nread = read (desc, name, namesize); if (nread != namesize) { close (desc); return -2; } name[namesize] = '\0'; long_name = 1; } #endif /* Not AIAMAG. */ } sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode); eltsize = atol (TOCHAR (member_header.ar_size)); fnval = (*function) (desc, name, ! long_name, member_offset, member_offset + AR_HDR_SIZE, eltsize, atol (TOCHAR (member_header.ar_date)), atoi (TOCHAR (member_header.ar_uid)), atoi (TOCHAR (member_header.ar_gid)), eltmode, arg); #endif /* AIAMAG. */ if (fnval) { (void) close (desc); return fnval; } #ifdef AIAMAG if (member_offset == last_member_offset) /* End of the chain. */ break; #ifdef AIAMAGBIG if (big_archive) sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset); else #endif sscanf (member_header.ar_nxtmem, "%12ld", &member_offset); if (lseek (desc, member_offset, 0) != member_offset) { (void) close (desc); return -2; } #else /* If this member maps archive names, we must read it in. The name map will always precede any members whose names must be mapped. */ if (is_namemap) { char *clear; char *limit; namemap = alloca (eltsize); nread = read (desc, namemap, eltsize); if (nread != eltsize) { (void) close (desc); return -2; } /* The names are separated by newlines. Some formats have a trailing slash. Null terminate the strings for convenience. */ limit = namemap + eltsize; for (clear = namemap; clear < limit; clear++) { if (*clear == '\n') { *clear = '\0'; if (clear[-1] == '/') clear[-1] = '\0'; } } is_namemap = 0; } member_offset += AR_HDR_SIZE + eltsize; if (member_offset % 2 != 0) member_offset++; #endif } } close (desc); return 0; } #endif /* !VMS */ /* Return nonzero iff NAME matches MEM. If TRUNCATED is nonzero, MEM may be truncated to sizeof (struct ar_hdr.ar_name) - 1. */ int ar_name_equal (const char *name, const char *mem, int truncated) { const char *p; p = strrchr (name, '/'); if (p != 0) name = p + 1; #ifndef VMS if (truncated) { #ifdef AIAMAG /* TRUNCATED should never be set on this system. */ abort (); #else struct ar_hdr hdr; #if !defined (__hpux) && !defined (cray) return strneq (name, mem, sizeof (hdr.ar_name) - 1); #else return strneq (name, mem, sizeof (hdr.ar_name) - 2); #endif /* !__hpux && !cray */ #endif /* !AIAMAG */ } return !strcmp (name, mem); #else /* VMS members do not have suffixes, but the filenames usually have. Do we need to strip VMS disk/directory format paths? Most VMS compilers etc. by default are case insensitive but produce uppercase external names, incl. module names. However the VMS librarian (ar) and the linker by default are case sensitive: they take what they get, usually uppercase names. So for the non-default settings of the compilers etc. there is a need to have a case sensitive mode. */ { int len; len = strlen(mem); int match; char *dot; if ((dot=strrchr(name,'.'))) match = (len == dot - name) && !strncasecmp(name, mem, len); else match = !strcasecmp (name, mem); return match; } #endif /* !VMS */ } #ifndef VMS /* ARGSUSED */ static long int ar_member_pos (int desc UNUSED, const char *mem, int truncated, long int hdrpos, long int datapos UNUSED, long int size UNUSED, long int date UNUSED, int uid UNUSED, int gid UNUSED, int mode UNUSED, const void *name) { if (!ar_name_equal (name, mem, truncated)) return 0; return hdrpos; } /* Set date of member MEMNAME in archive ARNAME to current time. Returns 0 if successful, -1 if file ARNAME does not exist, -2 if not a valid archive, -3 if other random system call error (including file read-only), 1 if valid but member MEMNAME does not exist. */ int ar_member_touch (const char *arname, const char *memname) { long int pos = ar_scan (arname, ar_member_pos, memname); int fd; struct ar_hdr ar_hdr; int i; unsigned int ui; struct stat statbuf; if (pos < 0) return (int) pos; if (!pos) return 1; fd = open (arname, O_RDWR, 0666); if (fd < 0) return -3; /* Read in this member's header */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; /* Write back the header, thus touching the archive file. */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; /* The file's mtime is the time we we want. */ EINTRLOOP (i, fstat (fd, &statbuf)); if (i < 0) goto lose; #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32) /* Advance member's time to that time */ for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++) ar_hdr.ar_date[ui] = ' '; sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime); #ifdef AIAMAG ar_hdr.ar_date[strlen (ar_hdr.ar_date)] = ' '; #endif #else ar_hdr.ar_date = statbuf.st_mtime; #endif /* Write back this member's header */ if (lseek (fd, pos, 0) < 0) goto lose; if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE)) goto lose; close (fd); return 0; lose: i = errno; close (fd); errno = i; return -3; } #endif #ifdef TEST long int describe_member (int desc, const char *name, int truncated, long int hdrpos, long int datapos, long int size, long int date, int uid, int gid, int mode, const void *arg) { extern char *ctime (); printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"), name, truncated ? _(" (name might be truncated)") : "", size, hdrpos, datapos); printf (_(" Date %s"), ctime (&date)); printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode); return 0; } int main (int argc, char **argv) { ar_scan (argv[1], describe_member, NULL); return 0; } #endif /* TEST. */ #endif /* NO_ARCHIVES. */ remake-4.1+dbg1.3~dfsg.1/autogen.sh000077500000000000000000000004371317072305000170000ustar00rootroot00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. # Additional options go to configure. echo "Rebuilding ./configure with autoreconf..." autoreconf -f -i if [ $? -ne 0 ]; then echo "autoreconf failed" exit $? fi ./configure --enable-maintainer-mode "$@" make update remake-4.1+dbg1.3~dfsg.1/build.template000066400000000000000000000050741317072305000176350ustar00rootroot00000000000000#!/bin/sh # Shell script to build GNU Make in the absence of any `make' program. # @configure_input@ # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # See Makefile.in for comments describing these variables. srcdir='@srcdir@' CC='@CC@' CFLAGS='@CFLAGS@' CPPFLAGS='@CPPFLAGS@' LDFLAGS='@LDFLAGS@' ALLOCA='@ALLOCA@' LOADLIBES='@LIBS@ @LIBINTL@' eval extras=\'@LIBOBJS@\' REMOTE='@REMOTE@' GLOBLIB='@GLOBLIB@' PATH_SEPARATOR='@PATH_SEPARATOR@' OBJEXT='@OBJEXT@' EXEEXT='@EXEEXT@' # Common prefix for machine-independent installed files. prefix='@prefix@' # Common prefix for machine-dependent installed files. exec_prefix=`eval echo @exec_prefix@` # Directory to find libraries in for `-lXXX'. libdir=${exec_prefix}/lib # Directory to search by default for included makefiles. includedir=${prefix}/include localedir=${prefix}/share/locale aliaspath=${localedir}${PATH_SEPARATOR}. defines="-DALIASPATH=\"${aliaspath}\" -DLOCALEDIR=\"${localedir}\" -DLIBDIR=\"${libdir}\" -DINCLUDEDIR=\"${includedir}\""' @DEFS@' # Exit as soon as any command fails. set -e # These are all the objects we need to link together. objs="%objs% remote-${REMOTE}.${OBJEXT} ${extras} ${ALLOCA}" if [ x"$GLOBLIB" != x ]; then objs="$objs %globobjs%" globinc=-I${srcdir}/glob fi # Compile the source files into those objects. for file in `echo ${objs} | sed 's/\.'${OBJEXT}'/.c/g'`; do echo compiling ${file}... $CC $defines $CPPFLAGS $CFLAGS \ -c -I. -I${srcdir} ${globinc} ${srcdir}/$file done # The object files were actually all put in the current directory. # Remove the source directory names from the list. srcobjs="$objs" objs= for obj in $srcobjs; do objs="$objs `basename $obj`" done # Link all the objects together. echo linking make... $CC $CFLAGS $LDFLAGS $objs $LOADLIBES -o makenew${EXEEXT} echo done mv -f makenew${EXEEXT} make${EXEEXT} remake-4.1+dbg1.3~dfsg.1/build_w32.bat000066400000000000000000000662241317072305000172670ustar00rootroot00000000000000@echo off rem Copyright (C) 1996-2014 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . if "%1" == "-h" GoTo Usage if "%1" == "--help" GoTo Usage if not exist config.h.W32.template GoTo NotSCM sed -n "s/^AC_INIT(\[GNU make\],\[\([^]]\+\)\].*/s,%%VERSION%%,\1,g/p" configure.ac > config.h.W32.sed echo s,%%PACKAGE%%,make,g >> config.h.W32.sed sed -f config.h.W32.sed config.h.W32.template > config.h.W32 echo static const char *const GUILE_module_defn = ^" \> gmk-default.h sed -e "s/;.*//" -e "/^[ \t]*$/d" -e "s/\"/\\\\\"/g" -e "s/$/ \\/" gmk-default.scm >> gmk-default.h echo ^";>> gmk-default.h :NotSCM copy config.h.W32 config.h rem Guile configuration set GUILECFLAGS= set GUILELIBS= set NOGUILE= set OPT=-O2 set COMPILER= set PKGMSC= :ParseSW if "%1" == "--debug" GoTo SetOpt if "%1" == "--without-guile" GoTo NoGuile if "%1" == "gcc" GoTo SetCC if "%1" == "" GoTo ChkGuile :SetOpt set OPT=-O0 shift GoTo ParseSW :NoGuile set NOGUILE=Y echo "Building without Guile" shift GoTo ParseSW :SetCC set COMPILER=gcc echo "Building with GCC" shift GoTo ParseSW rem Build with Guile is supported only on NT and later versions :ChkGuile if "%NOGUILE%" == "Y" GoTo GuileDone if not "%OS%" == "Windows_NT" GoTo NoGuile pkg-config --help > guile.tmp 2> NUL if ERRORLEVEL 1 GoTo NoPkgCfg echo "Checking for Guile 2.0" if not "%COMPILER%" == "gcc" set PKGMSC=--msvc-syntax pkg-config --cflags --short-errors "guile-2.0" > guile.tmp if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp pkg-config --libs --static --short-errors %PKGMSC% "guile-2.0" > guile.tmp if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp if not "%GUILECFLAGS%" == "" GoTo GuileDone echo "Checking for Guile 1.8" pkg-config --cflags --short-errors "guile-1.8" > guile.tmp if not ERRORLEVEL 1 set /P GUILECFLAGS= < guile.tmp pkg-config --libs --static --short-errors %PKGMSC% "guile-1.8" > guile.tmp if not ERRORLEVEL 1 set /P GUILELIBS= < guile.tmp if not "%GUILECFLAGS%" == "" GoTo GuileDone echo "No Guile found, building without Guile" GoTo GuileDone :NoPkgCfg echo "pkg-config not found, building without Guile" :GuileDone if not "%GUILECFLAGS%" == "" echo "Guile found, building with Guile" if not "%GUILECFLAGS%" == "" set GUILECFLAGS=%GUILECFLAGS% -DHAVE_GUILE if "%COMPILER%" == "gcc" if "%OPT%" == "-O0" echo "Building without compiler optimizations" cd w32\subproc echo. echo "Creating the subproc library" %ComSpec% /c build.bat cd ..\.. if exist link.dbg del link.dbg if exist link.rel del link.rel echo. echo "Creating GNU Make for Windows 9X/NT/2K/XP/Vista/7/8" if "%COMPILER%" == "gcc" GoTo GCCBuild set make=gnumake echo on if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D TIVOLI /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c variable.c echo WinDebug\variable.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c rule.c echo WinDebug\rule.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remote-stub.c echo WinDebug\remote-stub.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c commands.c echo WinDebug\commands.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c file.c echo WinDebug\file.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getloadavg.c echo WinDebug\getloadavg.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c default.c echo WinDebug\default.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c signame.c echo WinDebug\signame.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c expand.c echo WinDebug\expand.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c dir.c echo WinDebug\dir.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c main.c echo WinDebug\main.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt1.c echo WinDebug\getopt1.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c job.c echo WinDebug\job.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c output.c echo WinDebug\output.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c read.c echo WinDebug\read.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c version.c echo WinDebug\version.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c getopt.c echo WinDebug\getopt.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c arscan.c echo WinDebug\arscan.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c hash.c echo WinDebug\hash.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c strcache.c echo WinDebug\strcache.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c remake.c echo WinDebug\remake.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c misc.c echo WinDebug\misc.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c ar.c echo WinDebug\ar.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c function.c echo WinDebug\function.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c vpath.c echo WinDebug\vpath.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c implicit.c echo WinDebug\implicit.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c loadapi.c echo WinDebug\loadapi.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c load.c echo WinDebug\load.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\dirent.c echo WinDebug\dirent.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\compat\posixfcn.c echo WinDebug\posixfcn.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\glob.c echo WinDebug\glob.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\glob\fnmatch.c echo WinDebug\fnmatch.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c .\w32\pathstuff.c echo WinDebug\pathstuff.obj >>link.dbg cl.exe /nologo /MT /W4 /GX /Zi /YX /Od %GUILECFLAGS% /I . /I glob /I w32/include /D _DEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinDebug/ /Fp.\WinDebug/%make%.pch /Fo.\WinDebug/ /Fd.\WinDebug/%make%.pdb /c guile.c echo WinDebug\guile.obj >>link.dbg :LinkDbg echo off echo "Linking WinDebug/%make%.exe" rem link.exe %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe .\WinDebug/variable.obj .\WinDebug/rule.obj .\WinDebug/remote-stub.obj .\WinDebug/commands.obj .\WinDebug/file.obj .\WinDebug/getloadavg.obj .\WinDebug/default.obj .\WinDebug/signame.obj .\WinDebug/expand.obj .\WinDebug/dir.obj .\WinDebug/main.obj .\WinDebug/getopt1.obj .\WinDebug/job.obj .\WinDebug/output.obj .\WinDebug/read.obj .\WinDebug/version.obj .\WinDebug/getopt.obj .\WinDebug/arscan.obj .\WinDebug/remake.obj .\WinDebug/hash.obj .\WinDebug/strcache.obj .\WinDebug/misc.obj .\WinDebug/ar.obj .\WinDebug/function.obj .\WinDebug/vpath.obj .\WinDebug/implicit.obj .\WinDebug/dirent.obj .\WinDebug/glob.obj .\WinDebug/fnmatch.obj .\WinDebug/pathstuff.obj echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\windebug\subproc.lib >>link.dbg link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:.\WinDebug/%make%.pdb /DEBUG /OUT:.\WinDebug/%make%.exe @link.dbg if not exist .\WinDebug/%make%.exe echo "WinDebug build failed" if exist .\WinDebug/%make%.exe echo "WinDebug build succeeded!" if not exist .\WinRel\nul mkdir .\WinRel echo on cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /D TIVOLI /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c variable.c echo WinRel\variable.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c rule.c echo WinRel\rule.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remote-stub.c echo WinRel\remote-stub.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c commands.c echo WinRel\commands.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c file.c echo WinRel\file.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getloadavg.c echo WinRel\getloadavg.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c default.c echo WinRel\default.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c signame.c echo WinRel\signame.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c expand.c echo WinRel\expand.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c dir.c echo WinRel\dir.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c main.c echo WinRel\main.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt1.c echo WinRel\getopt1.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c job.c echo WinRel\job.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c output.c echo WinRel\output.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c read.c echo WinRel\read.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c version.c echo WinRel\version.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c getopt.c echo WinRel\getopt.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c arscan.c echo WinRel\arscan.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c remake.c echo WinRel\remake.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c hash.c echo WinRel\hash.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c strcache.c echo WinRel\strcache.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c misc.c echo WinRel\misc.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c ar.c echo WinRel\ar.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c function.c echo WinRel\function.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c vpath.c echo WinRel\vpath.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c implicit.c echo WinRel\implicit.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c loadapi.c echo WinRel\loadapi.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c load.c echo WinRel\load.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\dirent.c echo WinRel\dirent.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\compat\posixfcn.c echo WinRel\posixfcn.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\glob.c echo WinRel\glob.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\glob\fnmatch.c echo WinRel\fnmatch.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c .\w32\pathstuff.c echo WinRel\pathstuff.obj >>link.rel cl.exe /nologo /MT /W4 /GX /YX /O2 %GUILECFLAGS% /I . /I glob /I w32/include /D NDEBUG /D WINDOWS32 /D WIN32 /D _CONSOLE /D HAVE_CONFIG_H /FR.\WinRel/ /Fp.\WinRel/%make%.pch /Fo.\WinRel/ /c guile.c echo WinRel\guile.obj >>link.rel :LinkRel echo off echo "Linking WinRel/%make%.exe" rem link.exe %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe .\WinRel/variable.obj .\WinRel/rule.obj .\WinRel/remote-stub.obj .\WinRel/commands.obj .\WinRel/file.obj .\WinRel/getloadavg.obj .\WinRel/default.obj .\WinRel/signame.obj .\WinRel/expand.obj .\WinRel/dir.obj .\WinRel/main.obj .\WinRel/getopt1.obj .\WinRel/job.obj .\WinRel/output.obj .\WinRel/read.obj .\WinRel/version.obj .\WinRel/getopt.obj .\WinRel/arscan.obj .\WinRel/remake.obj .\WinRel/misc.obj .\WinRel/hash.obj .\WinRel/strcache.obj .\WinRel/ar.obj .\WinRel/function.obj .\WinRel/vpath.obj .\WinRel/implicit.obj .\WinRel/dirent.obj .\WinRel/glob.obj .\WinRel/fnmatch.obj .\WinRel/pathstuff.obj echo %GUILELIBS% kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib w32\subproc\winrel\subproc.lib >>link.rel link.exe /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:.\WinRel/%make%.pdb /OUT:.\WinRel/%make%.exe @link.rel if not exist .\WinRel/%make%.exe echo "WinRel build failed" if exist .\WinRel/%make%.exe echo "WinRel build succeeded!" set make= GoTo BuildEnd :GCCBuild echo on gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c variable.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c rule.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remote-stub.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c commands.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c file.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getloadavg.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c default.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c signame.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c expand.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c dir.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H %GUILECFLAGS% -c main.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt1.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c job.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c output.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c read.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c version.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c getopt.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c arscan.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c remake.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c hash.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c strcache.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c misc.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ar.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c function.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c vpath.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c implicit.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c loadapi.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c load.c gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/glob.c -o glob.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./glob/fnmatch.c -o fnmatch.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/pathstuff.c -o pathstuff.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c ./w32/compat/posixfcn.c -o posixfcn.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% %GUILECFLAGS% -I. -I./glob -I./w32/include -DWINDOWS32 -DHAVE_CONFIG_H -c guile.c :LinkGCC @echo off Rem The version NN of libgnumake-NN.dll.a should be bumped whenever Rem the API changes in binary-incompatible manner. @echo on gcc -mthreads -gdwarf-2 -g3 -o gnumake.exe variable.o rule.o remote-stub.o commands.o file.o getloadavg.o default.o signame.o expand.o dir.o main.o getopt1.o guile.o job.o output.o read.o version.o getopt.o arscan.o remake.o misc.o hash.o strcache.o ar.o function.o vpath.o implicit.o loadapi.o load.o glob.o fnmatch.o pathstuff.o posixfcn.o w32_misc.o sub_proc.o w32err.o %GUILELIBS% -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -Wl,--out-implib=libgnumake-1.dll.a @GoTo BuildEnd :Usage echo Usage: %0 [options] [gcc] echo Options: echo. --debug For GCC only, make a debug build echo. (MSVC build always makes both debug and release) echo. --without-guile Do not compile Guile support even if found echo. --help Display these instructions and exit :BuildEnd @echo off set GUILELIBS= set GUILECFLAGS= set PKGMSC= set OPT= set COMPILER= set NOGUILE= echo on remake-4.1+dbg1.3~dfsg.1/buildargv.c000066400000000000000000000131231317072305000171160ustar00rootroot00000000000000/* $Id: buildargv.c,v 1.2 2006/02/27 03:17:51 rockyb Exp $ */ /* Create and destroy argument vectors (argv's) Copyright (C) 1992, 2001 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support Copyright (C) 2008 R. Bernstein rocky@gnu.org This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Libiberty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* rocky: Below we only need/use the freeargv and buildargv routine from the above. Some small adaption was made to include outside of libiberty. */ #include #ifdef HAVE_ALLOCA_H #include #endif #include #include #include "buildargv.h" #ifndef EOS #define EOS '\0' #endif #define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */ #define ISBLANK(ch) ((ch) == ' ' || (ch) == '\t') /* @deftypefn Extension void freeargv (char **@var{vector}) Free an argument vector that was built using @code{buildargv}. Simply scans through @var{vector}, freeing the memory for each argument until the terminating @code{NULL} is found, and then frees @var{vector} itself. @end deftypefn */ void freeargv (vector) char **vector; { register char **scan; if (vector != NULL) { for (scan = vector; *scan != NULL; scan++) { free (*scan); } free (vector); } } /* @deftypefn Extension char** buildargv (char *@var{sp}) Given a pointer to a string, parse the string extracting fields separated by whitespace and optionally enclosed within either single or double quotes (which are stripped off), and build a vector of pointers to copies of the string for each field. The input string remains unchanged. The last element of the vector is followed by a @code{NULL} element. All of the memory for the pointer array and copies of the string is obtained from @code{malloc}. All of the memory can be returned to the system with the single function call @code{freeargv}, which takes the returned result of @code{buildargv}, as it's argument. Returns a pointer to the argument vector if successful. Returns @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient memory to complete building the argument vector. If the input is a null string (as opposed to a @code{NULL} pointer), then buildarg returns an argument vector that has one arg, a null string. @end deftypefn The memory for the argv array is dynamically expanded as necessary. In order to provide a working buffer for extracting arguments into, with appropriate stripping of quotes and translation of backslash sequences, we allocate a working buffer at least as long as the input string. This ensures that we always have enough space in which to work, since the extracted arg is never larger than the input string. The argument vector is always kept terminated with a @code{NULL} arg pointer, so it can be passed to @code{freeargv} at any time, or returned, as appropriate. */ char **buildargv (input) const char *input; { char *arg; char *copybuf; int squote = 0; int dquote = 0; int bsquote = 0; int argc = 0; int maxargc = 0; char **argv = NULL; char **nargv; if (input != NULL) { copybuf = (char *) alloca (strlen (input) + 1); /* Is a do{}while to always execute the loop once. Always return an argv, even for null strings. See NOTES above, test case below. */ do { /* Pick off argv[argc] */ while (ISBLANK (*input)) { input++; } if ((maxargc == 0) || (argc >= (maxargc - 1))) { /* argv needs initialization, or expansion */ if (argv == NULL) { maxargc = INITIAL_MAXARGC; nargv = (char **) malloc (maxargc * sizeof (char *)); } else { maxargc *= 2; nargv = (char **) realloc (argv, maxargc * sizeof (char *)); } if (nargv == NULL) { if (argv != NULL) { freeargv (argv); argv = NULL; } break; } argv = nargv; argv[argc] = NULL; } /* Begin scanning arg */ arg = copybuf; while (*input != EOS) { if (ISBLANK (*input) && !squote && !dquote && !bsquote) { break; } else { if (bsquote) { bsquote = 0; *arg++ = *input; } else if (*input == '\\') { bsquote = 1; } else if (squote) { if (*input == '\'') { squote = 0; } else { *arg++ = *input; } } else if (dquote) { if (*input == '"') { dquote = 0; } else { *arg++ = *input; } } else { if (*input == '\'') { squote = 1; } else if (*input == '"') { dquote = 1; } else { *arg++ = *input; } } input++; } } *arg = EOS; argv[argc] = strdup (copybuf); if (argv[argc] == NULL) { freeargv (argv); argv = NULL; break; } argc++; argv[argc] = NULL; while (ISBLANK (*input)) { input++; } } while (*input != EOS); } return (argv); } remake-4.1+dbg1.3~dfsg.1/buildargv.h000066400000000000000000000061141317072305000171250ustar00rootroot00000000000000/* $Id: buildargv.h,v 1.1 2006/01/21 13:40:21 rockyb Exp $ */ /* Create and destroy argument vectors (argv's) Copyright (C) 1992, 2001 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support Copyright (C) 2008 R. Bernstein rocky@gnu.org This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Libiberty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with libiberty; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* rocky: Below we only need/use the freeargv and buildargv routine from the above. Some small adaption was made to include outside of libiberty. */ /* @deftypefn Extension void freeargv (char **@var{vector}) Free an argument vector that was built using @code{buildargv}. Simply scans through @var{vector}, freeing the memory for each argument until the terminating @code{NULL} is found, and then frees @var{vector} itself. @end deftypefn */ void freeargv (char **vector); /* @deftypefn Extension char** buildargv (char *@var{sp}) Given a pointer to a string, parse the string extracting fields separated by whitespace and optionally enclosed within either single or double quotes (which are stripped off), and build a vector of pointers to copies of the string for each field. The input string remains unchanged. The last element of the vector is followed by a @code{NULL} element. All of the memory for the pointer array and copies of the string is obtained from @code{malloc}. All of the memory can be returned to the system with the single function call @code{freeargv}, which takes the returned result of @code{buildargv}, as it's argument. Returns a pointer to the argument vector if successful. Returns @code{NULL} if @var{sp} is @code{NULL} or if there is insufficient memory to complete building the argument vector. If the input is a null string (as opposed to a @code{NULL} pointer), then buildarg returns an argument vector that has one arg, a null string. @end deftypefn The memory for the argv array is dynamically expanded as necessary. In order to provide a working buffer for extracting arguments into, with appropriate stripping of quotes and translation of backslash sequences, we allocate a working buffer at least as long as the input string. This ensures that we always have enough space in which to work, since the extracted arg is never larger than the input string. The argument vector is always kept terminated with a @code{NULL} arg pointer, so it can be passed to @code{freeargv} at any time, or returned, as appropriate. */ char **buildargv (const char *input); remake-4.1+dbg1.3~dfsg.1/circle.yml000066400000000000000000000003171317072305000167600ustar00rootroot00000000000000checkout: post: - sudo apt-get install -y automake autopoint libreadline-dev wget gettext texinfo texlive - bash -x ./autogen.sh - make test: override: - make check - make distcheck remake-4.1+dbg1.3~dfsg.1/commands.c000066400000000000000000000535171317072305000167530ustar00rootroot00000000000000/* Command processing for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "dep.h" #include "variable.h" #include "job.h" #include "commands.h" #include "expand.h" #ifdef WINDOWS32 #include #include "w32err.h" #endif #if VMS # define FILE_LIST_SEPARATOR ',' #else # define FILE_LIST_SEPARATOR ' ' #endif int remote_kill (int id, int sig); #ifndef HAVE_UNISTD_H int getpid (); #endif static unsigned long dep_hash_1 (const void *key) { const struct dep *d = key; return_STRING_HASH_1 (dep_name (d)); } static unsigned long dep_hash_2 (const void *key) { const struct dep *d = key; return_STRING_HASH_2 (dep_name (d)); } static int dep_hash_cmp (const void *x, const void *y) { const struct dep *dx = x; const struct dep *dy = y; return strcmp (dep_name (dx), dep_name (dy)); } /* Set FILE's automatic variables up. */ void set_file_variables (struct file *file) { struct dep *d; const char *at, *percent, *star, *less; #ifndef NO_ARCHIVES /* If the target is an archive member 'lib(member)', then $@ is 'lib' and $% is 'member'. */ if (ar_name (file->name)) { unsigned int len; const char *cp; char *p; cp = strchr (file->name, '('); p = alloca (cp - file->name + 1); memcpy (p, file->name, cp - file->name); p[cp - file->name] = '\0'; at = p; len = strlen (cp + 1); p = alloca (len); memcpy (p, cp + 1, len - 1); p[len - 1] = '\0'; percent = p; } else #endif /* NO_ARCHIVES. */ { at = file->name; percent = ""; } /* $* is the stem from an implicit or static pattern rule. */ if (file->stem == 0) { /* In Unix make, $* is set to the target name with any suffix in the .SUFFIXES list stripped off for explicit rules. We store this in the 'stem' member. */ const char *name; unsigned int len; #ifndef NO_ARCHIVES if (ar_name (file->name)) { name = strchr (file->name, '(') + 1; len = strlen (name) - 1; } else #endif { name = file->name; len = strlen (name); } for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next) { unsigned int slen = strlen (dep_name (d)); if (len > slen && strneq (dep_name (d), name + (len - slen), slen)) { file->stem = strcache_add_len (name, len - slen); break; } } if (d == 0) file->stem = ""; } star = file->stem; /* $< is the first not order-only dependency. */ less = ""; for (d = file->deps; d != 0; d = d->next) if (!d->ignore_mtime) { if (!d->need_2nd_expansion) less = dep_name (d); break; } if (file->cmds == default_file->cmds) /* This file got its commands from .DEFAULT. In this case $< is the same as $@. */ less = at; #define DEFINE_VARIABLE(name, len, value) \ (void) define_variable_for_file (name,len,value,o_automatic,0,file) /* Define the variables. */ DEFINE_VARIABLE ("<", 1, less); DEFINE_VARIABLE ("*", 1, star); DEFINE_VARIABLE ("@", 1, at); DEFINE_VARIABLE ("%", 1, percent); /* Compute the values for $^, $+, $?, and $|. */ { static char *plus_value=0, *bar_value=0, *qmark_value=0; static unsigned int plus_max=0, bar_max=0, qmark_max=0; unsigned int qmark_len, plus_len, bar_len; char *cp; char *caret_value; char *qp; char *bp; unsigned int len; struct hash_table dep_hash; void **slot; /* Compute first the value for $+, which is supposed to contain duplicate dependencies as they were listed in the makefile. */ plus_len = 0; bar_len = 0; for (d = file->deps; d != 0; d = d->next) { if (!d->need_2nd_expansion) { if (d->ignore_mtime) bar_len += strlen (dep_name (d)) + 1; else plus_len += strlen (dep_name (d)) + 1; } } if (bar_len == 0) bar_len++; if (plus_len == 0) plus_len++; if (plus_len > plus_max) plus_value = xrealloc (plus_value, plus_max = plus_len); cp = plus_value; qmark_len = plus_len + 1; /* Will be this or less. */ for (d = file->deps; d != 0; d = d->next) if (! d->ignore_mtime && ! d->need_2nd_expansion) { const char *c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; } else #endif len = strlen (c); memcpy (cp, c, len); cp += len; *cp++ = FILE_LIST_SEPARATOR; if (! (d->changed || always_make_flag)) qmark_len -= len + 1; /* Don't space in $? for this one. */ } /* Kill the last space and define the variable. */ cp[cp > plus_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("+", 1, plus_value); /* Compute the values for $^, $?, and $|. */ cp = caret_value = plus_value; /* Reuse the buffer; it's big enough. */ if (qmark_len > qmark_max) qmark_value = xrealloc (qmark_value, qmark_max = qmark_len); qp = qmark_value; if (bar_len > bar_max) bar_value = xrealloc (bar_value, bar_max = bar_len); bp = bar_value; /* Make sure that no dependencies are repeated in $^, $?, and $|. It would be natural to combine the next two loops but we can't do it because of a situation where we have two dep entries, the first is order-only and the second is normal (see below). */ hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp); for (d = file->deps; d != 0; d = d->next) { if (d->need_2nd_expansion) continue; slot = hash_find_slot (&dep_hash, d); if (HASH_VACANT (*slot)) hash_insert_at (&dep_hash, d, slot); else { /* Check if the two prerequisites have different ignore_mtime. If so then we need to "upgrade" one that is order-only. */ struct dep* hd = (struct dep*) *slot; if (d->ignore_mtime != hd->ignore_mtime) d->ignore_mtime = hd->ignore_mtime = 0; } } for (d = file->deps; d != 0; d = d->next) { const char *c; if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d) continue; c = dep_name (d); #ifndef NO_ARCHIVES if (ar_name (c)) { c = strchr (c, '(') + 1; len = strlen (c) - 1; } else #endif len = strlen (c); if (d->ignore_mtime) { memcpy (bp, c, len); bp += len; *bp++ = FILE_LIST_SEPARATOR; } else { memcpy (cp, c, len); cp += len; *cp++ = FILE_LIST_SEPARATOR; if (d->changed || always_make_flag) { memcpy (qp, c, len); qp += len; *qp++ = FILE_LIST_SEPARATOR; } } } hash_free (&dep_hash, 0); /* Kill the last spaces and define the variables. */ cp[cp > caret_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("^", 1, caret_value); qp[qp > qmark_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("?", 1, qmark_value); bp[bp > bar_value ? -1 : 0] = '\0'; DEFINE_VARIABLE ("|", 1, bar_value); } #undef DEFINE_VARIABLE } /* Chop CMDS up into individual command lines if necessary. Also set the 'lines_flags' and 'any_recurse' members. */ void chop_commands (struct commands *cmds) { unsigned int nlines, idx; char **lines; /* If we don't have any commands, or we already parsed them, never mind. */ if (!cmds || cmds->command_lines != 0) return; /* Chop CMDS->commands up into lines in CMDS->command_lines. */ if (one_shell) { int l = strlen (cmds->commands); nlines = 1; lines = xmalloc (nlines * sizeof (char *)); lines[0] = xstrdup (cmds->commands); /* Strip the trailing newline. */ if (l > 0 && lines[0][l-1] == '\n') lines[0][l-1] = '\0'; } else { const char *p; nlines = 5; lines = xmalloc (nlines * sizeof (char *)); idx = 0; p = cmds->commands; while (*p != '\0') { const char *end = p; find_end:; end = strchr (end, '\n'); if (end == 0) end = p + strlen (p); else if (end > p && end[-1] == '\\') { int backslash = 1; const char *b; for (b = end - 2; b >= p && *b == '\\'; --b) backslash = !backslash; if (backslash) { ++end; goto find_end; } } if (idx == nlines) { nlines += 2; lines = xrealloc (lines, nlines * sizeof (char *)); } lines[idx++] = xstrndup (p, end - p); p = end; if (*p != '\0') ++p; } if (idx != nlines) { nlines = idx; lines = xrealloc (lines, nlines * sizeof (char *)); } } /* Finally, set the corresponding CMDS->lines_flags elements and the CMDS->any_recurse flag. */ if (nlines > USHRT_MAX) ON (fatal, &cmds->fileinfo, _("Recipe has too many lines (%ud)"), nlines); cmds->ncommand_lines = nlines; cmds->command_lines = lines; cmds->any_recurse = 0; cmds->lines_flags = xmalloc (nlines); for (idx = 0; idx < nlines; ++idx) { int flags = 0; const char *p = lines[idx]; while (isblank (*p) || *p == '-' || *p == '@' || *p == '+') switch (*(p++)) { case '+': flags |= COMMANDS_RECURSE; break; case '@': flags |= COMMANDS_SILENT; break; case '-': flags |= COMMANDS_NOERROR; break; } /* If no explicit '+' was given, look for MAKE variable references. */ if (!(flags & COMMANDS_RECURSE) && (strstr (p, "$(MAKE)") != 0 || strstr (p, "${MAKE}") != 0)) flags |= COMMANDS_RECURSE; cmds->lines_flags[idx] = flags; cmds->any_recurse |= flags & COMMANDS_RECURSE ? 1 : 0; } } /* Expand the command lines and store the results in LINES. */ void expand_command_lines(struct commands *cmds, /*out*/ char **lines, struct file *file) { unsigned int i; for (i = 0; i < cmds->ncommand_lines; ++i) { /* Collapse backslash-newline combinations that are inside variable or function references. These are left alone by the parser so that they will appear in the echoing of commands (where they look nice); and collapsed by construct_command_argv when it tokenizes. But letting them survive inside function invocations loses because we don't want the functions to see them as part of the text. */ char *in, *out, *ref; /* IN points to where in the line we are scanning. OUT points to where in the line we are writing. When we collapse a backslash-newline combination, IN gets ahead of OUT. */ in = out = cmds->command_lines[i]; while ((ref = strchr (in, '$')) != 0) { ++ref; /* Move past the $. */ if (out != in) /* Copy the text between the end of the last chunk we processed (where IN points) and the new chunk we are about to process (where REF points). */ memmove (out, in, ref - in); /* Move both pointers past the boring stuff. */ out += ref - in; in = ref; if (*ref == '(' || *ref == '{') { char openparen = *ref; char closeparen = openparen == '(' ? ')' : '}'; int count; char *p; *out++ = *in++; /* Copy OPENPAREN. */ /* IN now points past the opening paren or brace. Count parens or braces until it is matched. */ count = 0; while (*in != '\0') { if (*in == closeparen && --count < 0) break; else if (*in == '\\' && in[1] == '\n') { /* We have found a backslash-newline inside a variable or function reference. Eat it and any following whitespace. */ int quoted = 0; for (p = in - 1; p > ref && *p == '\\'; --p) quoted = !quoted; if (quoted) /* There were two or more backslashes, so this is not really a continuation line. We don't collapse the quoting backslashes here as is done in collapse_continuations, because the line will be collapsed again after expansion. */ *out++ = *in++; else { /* Skip the backslash, newline and any following whitespace. */ in = next_token (in + 2); /* Discard any preceding whitespace that has already been written to the output. */ while (out > ref && isblank ((unsigned char)out[-1])) --out; /* Replace it all with a single space. */ *out++ = ' '; } } else { if (*in == openparen) ++count; *out++ = *in++; } } } } /* There are no more references in this line to worry about. Copy the remaining uninteresting text to the output. */ if (out != in) memmove (out, in, strlen (in) + 1); /* Finally, expand the line. */ lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], file); } } /* Execute the commands to remake FILE. If they are currently executing, return or have already finished executing, just return. Otherwise, fork off a child process to run the first command line in the sequence. */ void execute_file_commands (file_t *file, target_stack_node_t *p_call_stack) { const char *p; /* Don't go through all the preparations if the commands are nothing but whitespace. */ for (p = file->cmds->commands; *p != '\0'; ++p) if (!isspace ((unsigned char)*p) && *p != '-' && *p != '@') break; if (*p == '\0') { /* If there are no commands, assume everything worked. */ set_command_state (file, cs_running); file->update_status = us_success; notice_finished_file (file); return; } /* First set the automatic variables according to this file. */ initialize_file_variables (file, 0); set_file_variables (file); /* If this is a loaded dynamic object, unload it before remaking. Some systems don't support overwriting a loaded object. */ if (file->loaded) unload_file (file->name); /* Start the commands running. */ new_job (file, p_call_stack); } /* This is set while we are inside fatal_error_signal, so things can avoid nonreentrant operations. */ int handling_fatal_signal = 0; /* Handle fatal signals. */ RETSIGTYPE fatal_error_signal (int sig) { #ifdef __MSDOS__ extern int dos_status, dos_command_running; if (dos_command_running) { /* That was the child who got the signal, not us. */ dos_status |= (sig << 8); return; } remove_intermediates (1); exit (EXIT_FAILURE); #else /* not __MSDOS__ */ #ifdef _AMIGA remove_intermediates (1); if (sig == SIGINT) fputs (_("*** Break.\n"), stderr); exit (10); #else /* not Amiga */ #ifdef WINDOWS32 extern HANDLE main_thread; /* Windows creates a sperate thread for handling Ctrl+C, so we need to suspend the main thread, or else we will have race conditions when both threads call reap_children. */ if (main_thread) { DWORD susp_count = SuspendThread (main_thread); if (susp_count != 0) fprintf (stderr, "SuspendThread: suspend count = %ld\n", susp_count); else if (susp_count == (DWORD)-1) { DWORD ierr = GetLastError (); fprintf (stderr, "SuspendThread: error %ld: %s\n", ierr, map_windows32_error_to_string (ierr)); } } #endif handling_fatal_signal = 1; /* Set the handling for this signal to the default. It is blocked now while we run this handler. */ signal (sig, SIG_DFL); /* A termination signal won't be sent to the entire process group, but it means we want to kill the children. */ if (sig == SIGTERM) { struct child *c; for (c = children; c != 0; c = c->next) if (!c->remote) (void) kill (c->pid, SIGTERM); } /* If we got a signal that means the user wanted to kill make, remove pending targets. */ if (sig == SIGTERM || sig == SIGINT #ifdef SIGHUP || sig == SIGHUP #endif #ifdef SIGQUIT || sig == SIGQUIT #endif ) { struct child *c; /* Remote children won't automatically get signals sent to the process group, so we must send them. */ for (c = children; c != 0; c = c->next) if (c->remote) (void) remote_kill (c->pid, sig); for (c = children; c != 0; c = c->next) delete_child_targets (c); /* Clean up the children. We don't just use the call below because we don't want to print the "Waiting for children" message. */ while (job_slots_used > 0) reap_children (1, 0, NULL); } else /* Wait for our children to die. */ while (job_slots_used > 0) reap_children (1, 1, NULL); /* Delete any non-precious intermediate files that were made. */ remove_intermediates (1); #ifdef SIGQUIT if (sig == SIGQUIT) /* We don't want to send ourselves SIGQUIT, because it will cause a core dump. Just exit instead. */ exit (MAKE_TROUBLE); #endif #ifdef WINDOWS32 if (main_thread) CloseHandle (main_thread); /* Cannot call W32_kill with a pid (it needs a handle). The exit status of 130 emulates what happens in Bash. */ exit (130); #else /* Signal the same code; this time it will really be fatal. The signal will be unblocked when we return and arrive then to kill us. */ if (kill (getpid (), sig) < 0) pfatal_with_name ("kill"); #endif /* not WINDOWS32 */ #endif /* not Amiga */ #endif /* not __MSDOS__ */ } /* Delete FILE unless it's precious or not actually a file (phony), and it has changed on disk since we last stat'd it. */ static void delete_target (struct file *file, const char *on_behalf_of) { struct stat st; int e; if (file->precious || file->phony) return; #ifndef NO_ARCHIVES if (ar_name (file->name)) { time_t file_date = (file->last_mtime == NONEXISTENT_MTIME ? (time_t) -1 : (time_t) FILE_TIMESTAMP_S (file->last_mtime)); time_t member_date = NONEXISTENT_MTIME; int found; found = ar_member_date (file->name, &member_date); if (found && member_date != file_date) { if (on_behalf_of) OSS (error, NILF, _("*** [%s] Archive member '%s' may be bogus; not deleted"), on_behalf_of, file->name); else OS (error, NILF, _("*** Archive member '%s' may be bogus; not deleted"), file->name); } return; } #endif EINTRLOOP (e, stat (file->name, &st)); if (e == 0 && S_ISREG (st.st_mode) && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime) { if (on_behalf_of) OSS (error, NILF, _("*** [%s] Deleting file '%s'"), on_behalf_of, file->name); else OS (error, NILF, _("*** Deleting file '%s'"), file->name); if (unlink (file->name) < 0 && errno != ENOENT) /* It disappeared; so what. */ perror_with_name ("unlink: ", file->name); } } /* Delete all non-precious targets of CHILD unless they were already deleted. Set the flag in CHILD to say they've been deleted. */ void delete_child_targets (struct child *child) { struct dep *d; if (child->deleted) return; /* Delete the target file if it changed. */ delete_target (child->file, NULL); /* Also remove any non-precious targets listed in the 'also_make' member. */ for (d = child->file->also_make; d != 0; d = d->next) delete_target (d->file, child->file->name); child->deleted = 1; } /* Print out the commands in CMDS. */ /*! Print out the commands. @param p_cmds location of commands to print out. @param p_target used to set automatic variables if it is non-null. @param b_expand if true, expand the commands to remove MAKE variables. */ void print_commands (file_t *p_target, commands_t *p_cmds, bool b_expand) { const char *s; fputs (_("# recipe to execute"), stdout); if (p_cmds->fileinfo.filenm == 0) puts (_(" (built-in):")); else printf (_(" (from '%s', line %lu):\n"), p_cmds->fileinfo.filenm, p_cmds->fileinfo.lineno); if (b_expand && p_target) { variable_set_list_t *p_file_vars = NULL; initialize_file_variables (p_target, 0); set_file_variables (p_target); p_file_vars = p_target->variables; s = variable_expand_set(p_cmds->commands, p_file_vars); } else { s = p_cmds->commands; } while (*s != '\0') { const char *end; int bs; /* Print one full logical recipe line: find a non-escaped newline. */ for (end = s, bs = 0; *end != '\0'; ++end) { if (*end == '\n' && !bs) break; bs = *end == '\\' ? !bs : 0; } printf ("%c%.*s\n", cmd_prefix, (int) (end - s), s); s = end + (end[0] == '\n'); } } remake-4.1+dbg1.3~dfsg.1/commands.h000066400000000000000000000052601317072305000167500ustar00rootroot00000000000000/* Definition of data structures describing shell commands for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* Structure that gives the commands to make a file and information about where these commands came from. */ #ifndef REMAKE_COMMANDS_H #define REMAKE_COMMANDS_H #include "makeint.h" #include "filedef.h" #include "trace.h" struct commands { gmk_floc fileinfo; /* Where commands were defined. */ char *commands; /* Commands text. */ char **command_lines; /* Commands chopped up into lines. */ char *lines_flags; /* One set of flag bits for each line. */ unsigned short ncommand_lines;/* Number of command lines. */ char recipe_prefix; /* Recipe prefix for this command set. */ unsigned int any_recurse:1; /* Nonzero if any 'lines_flags' elt has */ /* the COMMANDS_RECURSE bit set. */ }; /* Bits in 'lines_flags'. */ #define COMMANDS_RECURSE 1 /* Recurses: + or $(MAKE). */ #define COMMANDS_SILENT 2 /* Silent: @. */ #define COMMANDS_NOERROR 4 /* No errors: -. */ /*! Execute the commands to remake P_FILE. If they are currently executing, return or have already finished executing, just return. Otherwise, fork off a child process to run the first command line in the sequence. @param p_file pointer to file to remake. @param p_call_stack pointer to current target call stack. This is passed down for information reporting. */ extern void execute_file_commands (file_t *p_file, target_stack_node_t *p_call_stack); /*! Print out the commands. @param p_cmds location of commands to print out. @param p_target used to set automatic variables if it is non-null. @param b_expand if true, expand the commands to remove MAKE variables. */ extern void print_commands (file_t *p_target, commands_t *p_cmds, bool b_expand); void delete_child_targets (struct child *child); void chop_commands (struct commands *cmds); void set_file_variables (struct file *file); #endif /*REMAKE_COMMANDS_H*/ remake-4.1+dbg1.3~dfsg.1/config/000077500000000000000000000000001317072305000162405ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/config/.cvsignore000066400000000000000000000001521317072305000202360ustar00rootroot00000000000000*.m4 config.* mkinstalldirs texinfo.tex mdate-sh compile depcomp install-sh missing Makefile Makefile.in remake-4.1+dbg1.3~dfsg.1/config/.gitignore000066400000000000000000000007741317072305000202400ustar00rootroot00000000000000/*~ /Makefile /Makefile.in /codeset.m4 /compile /config.guess /config.rpath /config.sub /depcomp /elisp-comp /gettext.m4 /glibc21.m4 /iconv.m4 /install-sh /intdiv0.m4 /intmax.m4 /inttypes-pri.m4 /inttypes.m4 /inttypes_h.m4 /isc-posix.m4 /lcmessage.m4 /lib-ld.m4 /lib-link.m4 /lib-prefix.m4 /longdouble.m4 /longlong.m4 /mdate-sh /missing /mkinstalldirs /nls.m4 /po.m4 /printf-posix.m4 /progtest.m4 /signed.m4 /size_max.m4 /stdint_h.m4 /texinfo.tex /uintmax_t.m4 /ulonglong.m4 /wchar_t.m4 /wint_t.m4 /xsize.m4 remake-4.1+dbg1.3~dfsg.1/config/ChangeLog000066400000000000000000000033171317072305000200160ustar00rootroot000000000000002006-03-09 Paul Smith * dospaths.m4: Add MSYS to the list of targets allowing DOS-style pathnames. Reported by David Ergo . 2005-07-01 Paul D. Smith * Makefile.am (EXTRA_DIST): Added more M4 files to EXTRA_DIST, so users can re-run aclocal. 2003-04-30 Paul D. Smith * dospaths.m4: New macro to test for DOS-style pathnames, based on coreutils 5.0 "dos.m4" by Jim Meyering. 2002-04-21 gettextize * codeset.m4: New file, from gettext-0.11.1. * gettext.m4: New file, from gettext-0.11.1. * glibc21.m4: New file, from gettext-0.11.1. * iconv.m4: New file, from gettext-0.11.1. * isc-posix.m4: New file, from gettext-0.11.1. * lcmessage.m4: New file, from gettext-0.11.1. * lib-ld.m4: New file, from gettext-0.11.1. * lib-link.m4: New file, from gettext-0.11.1. * lib-prefix.m4: New file, from gettext-0.11.1. * progtest.m4: New file, from gettext-0.11.1. * Makefile.am: New file. Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/config/Makefile.am000066400000000000000000000014521317072305000202760ustar00rootroot00000000000000# -*-Makefile-*-, or close enough # Copyright (C) 2002-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # Autoconf / automake know how to handle this directory. remake-4.1+dbg1.3~dfsg.1/config/ar-lib000077500000000000000000000133021317072305000173330ustar00rootroot00000000000000#! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2012-03-01.08; # UTC # Copyright (C) 2010-2014 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat <. Based on dos.m4 by Jim Meyering. # # Copyright (C) 1993-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . AC_DEFUN([pds_AC_DOS_PATHS], [ AC_CACHE_CHECK([whether system uses MSDOS-style paths], [ac_cv_dos_paths], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if !defined _WIN32 && !defined __WIN32__ && !defined __MSDOS__ && !defined __EMX__ && !defined __MSYS__ && !defined __CYGWIN__ neither MSDOS nor Windows nor OS2 #endif ]])], [ac_cv_dos_paths=yes], [ac_cv_dos_paths=no])]) AS_IF([test x"$ac_cv_dos_paths" = xyes], [ AC_DEFINE_UNQUOTED([HAVE_DOS_PATHS], 1, [Define if the system uses DOS-style pathnames.])]) ]) remake-4.1+dbg1.3~dfsg.1/config/intlmacosx.m4000066400000000000000000000045751317072305000206760ustar00rootroot00000000000000# intlmacosx.m4 serial 3 (gettext-0.18) dnl Copyright (C) 2004-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Checks for special options needed on MacOS X. dnl Defines INTL_MACOSX_LIBS. AC_DEFUN([gt_INTL_MACOSX], [ dnl Check for API introduced in MacOS X 10.2. AC_CACHE_CHECK([for CFPreferencesCopyAppValue], [gt_cv_func_CFPreferencesCopyAppValue], [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) remake-4.1+dbg1.3~dfsg.1/config/readline.h000066400000000000000000000015651317072305000202030ustar00rootroot00000000000000/* * Lifted from http://autoconf-archive.cryp.to/vl_lib/readline.html * with thanks to Ville Laurikari * * Modified to exclude libhistory if there is no libreadline. */ #ifdef HAVE_LIBREADLINE # if defined(HAVE_READLINE_READLINE_H) # include # elif defined(HAVE_READLINE_H) # include # else /* !defined(HAVE_READLINE_H) */ extern char *readline (); # endif /* !defined(HAVE_READLINE_H) */ char *cmdline = NULL; #ifdef HAVE_READLINE_HISTORY # if defined(HAVE_READLINE_HISTORY_H) # include # elif defined(HAVE_HISTORY_H) # include # else /* !defined(HAVE_HISTORY_H) */ extern void add_history (); extern int write_history (); extern int read_history (); # endif /* defined(HAVE_READLINE_HISTORY_H) */ /* no history */ #endif /* HAVE_READLINE_HISTORY */ #endif /* HAVE_LIBREADLINE */ remake-4.1+dbg1.3~dfsg.1/config/readline.m4000066400000000000000000000030161317072305000202650ustar00rootroot00000000000000dnl dnl Lifted from http://autoconf-archive.cryp.to/vl_lib/readline.html dnl with thanks to Ville Laurikari dnl AC_DEFUN([VL_LIB_READLINE], [ AC_CACHE_CHECK([for a readline compatible library], vl_cv_lib_readline, [ ORIG_LIBS="$LIBS" for readline_lib in readline edit editline; do for termcap_lib in "" termcap curses ncurses; do if test -z "$termcap_lib"; then TRY_LIB="-l$readline_lib" else TRY_LIB="-l$readline_lib -l$termcap_lib" fi LIBS="$ORIG_LIBS $TRY_LIB" AC_TRY_LINK_FUNC(readline, vl_cv_lib_readline="$TRY_LIB") if test -n "$vl_cv_lib_readline"; then break fi done if test -n "$vl_cv_lib_readline"; then break fi done if test -z "$vl_cv_lib_readline"; then vl_cv_lib_readline="no" LIBS="$ORIG_LIBS" fi ]) if test "$vl_cv_lib_readline" != "no"; then AC_DEFINE(HAVE_LIBREADLINE, 1, [Define if you have a readline compatible library]) AC_CHECK_HEADERS(readline.h readline/readline.h) AC_CACHE_CHECK([whether readline supports history], vl_cv_lib_readline_history, [ vl_cv_lib_readline_history="no" AC_TRY_LINK_FUNC(add_history, vl_cv_lib_readline_history="yes") ]) if test "$vl_cv_lib_readline_history" = "yes"; then AC_DEFINE(HAVE_READLINE_HISTORY, 1, [Define if your readline library has \`add_history']) AC_CHECK_HEADERS(history.h readline/history.h) fi fi ])dnl remake-4.1+dbg1.3~dfsg.1/configure.ac000066400000000000000000000522451317072305000172710ustar00rootroot00000000000000# Process this file with autoconf to produce a configure script. # # Copyright (C) 1993-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # Copyright (C) 2008, 2011, 2014, 2017 rocky@gnu.org # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . AC_INIT([remake],[4.1+dbg1.3],[https://github.com/rocky/remake/issues]) AC_PREREQ([2.62]) # Autoconf setup AC_CONFIG_AUX_DIR([config]) AC_CONFIG_SRCDIR([vpath.c]) AC_CONFIG_HEADERS([config.h]) # Automake setup # We have to enable "foreign" because ChangeLog is auto-generated # We cannot enable -Werror because gettext 0.18.1 has invalid content # When we update gettext to 0.18.3 or better we can add it again. AM_INIT_AUTOMAKE([subdir-objects 1.11.1 silent-rules foreign -Wall]) AM_MAINTAINER_MODE # Checks for programs. AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AC_PROG_INSTALL AC_PROG_RANLIB AC_PROG_CPP AC_PROG_LN_S AC_CHECK_PROG([AR], [ar], [ar], [ar]) # Perl is needed for the test suite (only) AC_CHECK_PROG([PERL], [perl], [perl], [perl]) # Ruby 1.9 and RSPec are needed for the debugger test suite (only) AC_CHECK_PROG(RUBY, ruby, ruby, none) AC_CHECK_PROG(RSPEC, rspec, rspec, none) # Needed for w32/Makefile.am AM_PROG_AR # Specialized system macros AC_CANONICAL_HOST AC_AIX AC_ISC_POSIX AC_MINIX AM_MISSING_PROG(GIT2CL, git2cl, $missing_dir) # Enable gettext, in "external" mode. AM_GNU_GETTEXT_VERSION([0.18.1]) AM_GNU_GETTEXT([external]) # This test must come as early as possible after the compiler configuration # tests, because the choice of the file model can (in principle) affect # whether functions and headers are available, whether they work, etc. AC_SYS_LARGEFILE # Checks for libraries. AC_SEARCH_LIBS([getpwnam], [sun]) # Checks for header files. AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_STAT AC_HEADER_TIME AC_CHECK_HEADERS([stdlib.h locale.h unistd.h limits.h fcntl.h string.h \ memory.h sys/param.h sys/resource.h sys/time.h sys/timeb.h \ sys/user.h linux/binfmts.h]) AM_PROG_CC_C_O AC_C_CONST AC_TYPE_SIGNAL AC_TYPE_UID_T AC_TYPE_PID_T # Find some definition for uintmax_t AC_CHECK_TYPE([uintmax_t],[], [ uintmax_t="unsigned long" AC_CHECK_TYPE([unsigned long long],[uintmax_t="unsigned long long"]) AC_DEFINE_UNQUOTED([uintmax_t], [$uintmax_t], [Define uintmax_t if not defined in or .]) ]) # Find out whether our struct stat returns nanosecond resolution timestamps. AC_STRUCT_ST_MTIM_NSEC AC_CACHE_CHECK([whether to use high resolution file timestamps], [make_cv_file_timestamp_hi_res], [ make_cv_file_timestamp_hi_res=no AS_IF([test "$ac_cv_struct_st_mtim_nsec" != no], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if HAVE_INTTYPES_H # include #endif]], [[char a[0x7fffffff < (uintmax_t)-1 >> 30 ? 1 : -1];]])], [make_cv_file_timestamp_hi_res=yes]) ])]) AS_IF([test "$make_cv_file_timestamp_hi_res" = yes], [val=1], [val=0]) AC_DEFINE_UNQUOTED([FILE_TIMESTAMP_HI_RES], [$val], [Use high resolution file timestamps if nonzero.]) AS_IF([test "$make_cv_file_timestamp_hi_res" = yes], [ # Solaris 2.5.1 needs -lposix4 to get the clock_gettime function. # Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4. AC_SEARCH_LIBS([clock_gettime], [rt posix4]) AS_IF([test "$ac_cv_search_clock_gettime" != no], [ AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define to 1 if you have the clock_gettime function.]) ]) ]) # Check for DOS-style pathnames. pds_AC_DOS_PATHS # See if we have a standard version of gettimeofday(). Since actual # implementations can differ, just make sure we have the most common # one. AC_CACHE_CHECK([for standard gettimeofday], [ac_cv_func_gettimeofday], [ac_cv_func_gettimeofday=no AC_RUN_IFELSE([AC_LANG_SOURCE([[#include int main () { struct timeval t; t.tv_sec = -1; t.tv_usec = -1; exit (gettimeofday (&t, 0) != 0 || t.tv_sec < 0 || t.tv_usec < 0); }]])], [ac_cv_func_gettimeofday=yes], [ac_cv_func_gettimeofday=no], [ac_cv_func_gettimeofday="no (cross-compiling)"])]) AS_IF([test "$ac_cv_func_gettimeofday" = yes], [ AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [Define to 1 if you have a standard gettimeofday function]) ]) AC_CHECK_FUNCS([strdup strndup mkstemp mktemp fdopen fileno \ dup dup2 getcwd realpath sigsetmask sigaction \ getgroups seteuid setegid setlinebuf setreuid setregid \ getrlimit setrlimit setvbuf pipe strerror strsignal \ lstat readlink atexit isatty ttyname]) # We need to check declarations, not just existence, because on Tru64 this # function is not declared without special flags, which themselves cause # other problems. We'll just use our own. AC_CHECK_DECLS([bsd_signal], [], [], [[#define _GNU_SOURCE 1 #include ]]) AC_FUNC_SETVBUF_REVERSED # Rumor has it that strcasecmp lives in -lresolv on some odd systems. # It doesn't hurt much to use our own if we can't find it so I don't # make the effort here. AC_CHECK_FUNCS([strcasecmp strncasecmp strcmpi strncmpi stricmp strnicmp]) # strcoll() is used by the GNU glob library AC_FUNC_STRCOLL AC_FUNC_ALLOCA AC_FUNC_VPRINTF AC_FUNC_CLOSEDIR_VOID # See if the user wants to add (or not) GNU Guile support PKG_PROG_PKG_CONFIG AC_ARG_WITH([guile], [AS_HELP_STRING([--with-guile], [Support GNU Guile for embedded scripting])]) # For some strange reason, at least on Ubuntu, each version of Guile # comes with it's own PC file so we have to specify them as individual # packages. Ugh. AS_IF([test "x$with_guile" != xno], [ PKG_CHECK_MODULES([GUILE], [guile-2.0], [have_guile=yes], [PKG_CHECK_MODULES([GUILE], [guile-1.8], [have_guile=yes], [have_guile=no])]) ]) AS_IF([test "$have_guile" = yes], [AC_DEFINE([HAVE_GUILE], [1], [Embed GNU Guile support])]) AM_CONDITIONAL([HAVE_GUILE], [test "$have_guile" = yes]) AC_FUNC_GETLOADAVG # AC_FUNC_GETLOADAVG is documented to set the NLIST_STRUCT value, but it # doesn't. So, we will. AS_IF([test "$ac_cv_header_nlist_h" = yes], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct nlist nl; nl.n_name = "string"; return 0;]])], [make_cv_nlist_struct=yes], [make_cv_nlist_struct=no]) AS_IF([test "$make_cv_nlist_struct" = yes], [ AC_DEFINE([NLIST_STRUCT], [1], [Define to 1 if struct nlist.n_name is a pointer rather than an array.]) ]) ]) AC_CHECK_DECLS([sys_siglist, _sys_siglist, __sys_siglist], , , [AC_INCLUDES_DEFAULT #include /* NetBSD declares sys_siglist in unistd.h. */ #if HAVE_UNISTD_H # include #endif ]) # Check out the wait reality. AC_CHECK_HEADERS([sys/wait.h],[],[],[[#include ]]) AC_CHECK_FUNCS([waitpid wait3]) AC_CACHE_CHECK([for union wait], [make_cv_union_wait], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[union wait status; int pid; pid = wait (&status); #ifdef WEXITSTATUS /* Some POSIXoid systems have both the new-style macros and the old union wait type, and they do not work together. If union wait conflicts with WEXITSTATUS et al, we don't want to use it at all. */ if (WEXITSTATUS (status) != 0) pid = -1; #ifdef WTERMSIG /* If we have WEXITSTATUS and WTERMSIG, just use them on ints. */ -- blow chunks here -- #endif #endif #ifdef HAVE_WAITPID /* Make sure union wait works with waitpid. */ pid = waitpid (-1, &status, 0); #endif ]])], [make_cv_union_wait=yes], [make_cv_union_wait=no]) ]) AS_IF([test "$make_cv_union_wait" = yes], [ AC_DEFINE([HAVE_UNION_WAIT], [1], [Define to 1 if you have the 'union wait' type in .]) ]) AC_ARG_WITH(make_name, [ --with-make-name name to use as the program name (default remake)], make_name="${withval}", make_name="remake") MAKE_NAME="$make_name" AC_SUBST(MAKE_NAME) MAKE_NAME_UPPER=`echo $make_name | tr a-z A-Z` AC_SUBST(MAKE_NAME_UPPER) AC_ARG_WITH(default_shell, [ --with-default-shell program to use for SHELL], default_shell="${withval}", default_shell="/bin/sh") DEFAULT_SHELL="$default_shell" AC_ARG_WITH(shell_trace, [ --with-shell-trace option to pass to shell to have it trace commands (default -x)], shell_trace="${withval}", shell_trace="-x") ## Set OS-specific default shell. case $host_os in cygwin*|mingw*) ;; solaris*) ## The System V Release 4 /bin/sh can't handle ## -x -c in that order. for sh in /bin/bash /usr/xpg4/bin/sh; do if test -x "$sh" ; then default_shell=$sh break fi done ;; *) ;; esac AC_MSG_CHECKING(if $default_shell can be used to trace commands using $shell_trace) sh_is_ok=`$default_shell $shell_trace -c ':' 2>&1` if test "+ :" != "$sh_is_ok" ; then AC_MSG_RESULT(no) AC_MSG_WARN([Disabling shell tracing. Run again using --with-default_shell]) AC_MSG_WARN([or using --with-shell_trace if you know of a shell that]) AC_MSG_WARN([supports tracing with *sh* *shell_option* -c (in that order)"]) else AC_MSG_RESULT(yes) fi AC_DEFINE_UNQUOTED(SHELL_TRACE, ["$shell_trace"], [Define this to be what you need to add to turn on shell tracing]) AC_DEFINE_UNQUOTED(DEFAULT_SHELL, ["$default_shell"], [Define this to the default to be used $(SHELL)]) # # Check for readline to see if we can add debugging support. # AC_CHECK_HEADER(readline/readline.h, [have_readline=yes], [have_readline=no]) if test "$have_readline" != yes; then AC_MSG_ERROR([GNU Readline and its headers files are needed. See http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html]) fi VL_LIB_READLINE AC_MSG_CHECKING(for tilde_expand() in ) AC_TRY_RUN([ #include #include int main(int argc, char **argv) { char *s = tilde_expand ("~"); return 0; }], [AC_MSG_RESULT(yes); ac_have_tilde_expand=yes; AC_DEFINE(HAVE_TILDE_EXPAND, [], [Define this defines tilde_expand()])], [AC_MSG_RESULT(no); ac_have_tilde_expand=no], [AC_MSG_RESULT(no); ac_have_tilde_expand=no]) AC_CHECK_LIB(readline, readline) AC_MSG_CHECKING(for history_list() in ) AC_TRY_RUN([ #include #include #include int main(int argc, char **argv) { HIST_ENTRY **hist_list; rl_initialize (); hist_list = history_list(); return 0; }], [AC_MSG_RESULT(yes); ac_have_history_list=yes; AC_DEFINE(HAVE_HISTORY_LIST, [], [Define this defines history_list()])], [AC_MSG_RESULT(no); ac_have_history_list=no], [AC_MSG_RESULT(no); ac_have_history_list=no]) AC_SUBST(HAVE_READLINE) REMAKE_SOURCE_PATH="`pwd`" AC_DEFINE_UNQUOTED(REMAKE_SOURCE_PATH, "$REMAKE_SOURCE_PATH", [Full path to remake top_sourcedir.]) AC_SUBST(REMAKE_SOURCE_PATH) # If we're building on Windows/DOS/OS/2, add some support for DOS drive specs. AS_IF([test "$PATH_SEPARATOR" = ';'], [ AC_DEFINE([HAVE_DOS_PATHS], [1], [Define to 1 if your system requires backslashes or drive specs in pathnames.]) ]) # See if the user wants to use pmake's "customs" distributed build capability AC_SUBST([REMOTE]) REMOTE=stub use_customs=false AC_ARG_WITH([customs], [AC_HELP_STRING([--with-customs=DIR], [enable remote jobs via Customs--see README.customs])], [ AS_CASE([$withval], [n|no], [:], [make_cppflags="$CPPFLAGS" AS_CASE([$withval], [y|ye|yes], [:], [CPPFLAGS="$CPPFLAGS -I$with_customs/include/customs" make_ldflags="$LDFLAGS -L$with_customs/lib"]) CF_NETLIBS AC_CHECK_HEADER([customs.h], [use_customs=true REMOTE=cstms LIBS="$LIBS -lcustoms" LDFLAGS="$make_ldflags"], [with_customs=no CPPFLAGS="$make_cppflags" make_badcust=yes]) ]) ]) # Tell automake about this, so it can include the right .c files. AM_CONDITIONAL([USE_CUSTOMS], [test "$use_customs" = true]) # See if the user asked to handle case insensitive file systems. AH_TEMPLATE([HAVE_CASE_INSENSITIVE_FS], [Use case insensitive file names]) AC_ARG_ENABLE([case-insensitive-file-system], AC_HELP_STRING([--enable-case-insensitive-file-system], [assume file systems are case insensitive]), [AS_IF([test "$enableval" = yes], [AC_DEFINE([HAVE_CASE_INSENSITIVE_FS])])]) # See if we can handle the job server feature, and if the user wants it. AC_ARG_ENABLE([job-server], AC_HELP_STRING([--disable-job-server], [disallow recursive make communication during -jN]), [make_cv_job_server="$enableval" user_job_server="$enableval"], [make_cv_job_server="yes"]) AS_IF([test "$ac_cv_func_waitpid" = no && test "$ac_cv_func_wait3" = no], [has_wait_nohang=no], [has_wait_nohang=yes]) AC_CACHE_CHECK([for SA_RESTART], [make_cv_sa_restart], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[return SA_RESTART;]])], [make_cv_sa_restart=yes], [make_cv_sa_restart=no])]) AS_IF([test "$make_cv_sa_restart" != no], [ AC_DEFINE([HAVE_SA_RESTART], [1], [Define to 1 if defines the SA_RESTART constant.]) ]) # Only allow jobserver on systems that support it AS_CASE([/$ac_cv_func_pipe/$ac_cv_func_sigaction/$make_cv_sa_restart/$has_wait_nohang/], [*/no/*], [make_cv_job_server=no]) # Also supported on OS2 and MinGW AS_CASE([$host_os], [os2*|mingw*], [make_cv_job_server=yes]) # If we support it and the user didn't disable it, build with jobserver AS_CASE([/$make_cv_job_server/$user_job_server/], [*/no/*], [: no jobserver], [AC_DEFINE(MAKE_JOBSERVER, 1, [Define to 1 to enable job server support in GNU make.]) ]) # If dl*() functions are supported we can enable the load operation AC_CHECK_DECLS([dlopen, dlsym, dlerror], [], [], [[#include ]]) AC_ARG_ENABLE([load], AC_HELP_STRING([--disable-load], [disable support for the 'load' operation]), [make_cv_load="$enableval" user_load="$enableval"], [make_cv_load="yes"]) AS_CASE([/$ac_cv_have_decl_dlopen/$ac_cv_have_decl_dlsym/$ac_cv_have_decl_dlerror/], [*/no/*], [make_cv_load=no]) # We might need -ldl AS_IF([test "$make_cv_load" = yes], [ AC_SEARCH_LIBS([dlopen], [dl], [], [make_cv_load=]) ]) AS_CASE([/$make_cv_load/$user_load/], [*/no/*], [make_cv_load=no], [AC_DEFINE(MAKE_LOAD, 1, [Define to 1 to enable 'load' support in GNU make.]) ]) # If we want load support, we might need to link with export-dynamic. # See if we can figure it out. Unfortunately this is very difficult. # For example passing -rdynamic to the SunPRO linker gives a warning # but succeeds and creates a shared object, not an executable! AS_IF([test "$make_cv_load" = yes], [ AC_MSG_CHECKING([If the linker accepts -Wl,--export-dynamic]) old_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], [AC_MSG_RESULT([yes]) AC_SUBST([AM_LDFLAGS], [-Wl,--export-dynamic])], [AC_MSG_RESULT([no]) AC_MSG_CHECKING([If the linker accepts -rdynamic]) LDFLAGS="$old_LDFLAGS -rdynamic" AC_LINK_IFELSE([AC_LANG_SOURCE([int main(){}])], [AC_MSG_RESULT([yes]) AC_SUBST([AM_LDFLAGS], [-rdynamic])], [AC_MSG_RESULT([no])]) ]) LDFLAGS="$old_LDFLAGS" ]) # if we have both lstat() and readlink() then we can support symlink # timechecks. AS_IF([test "$ac_cv_func_lstat" = yes && test "$ac_cv_func_readlink" = yes], [ AC_DEFINE([MAKE_SYMLINKS], [1], [Define to 1 to enable symbolic link timestamp checking.]) ]) # Find the SCCS commands, so we can include them in our default rules. AC_CACHE_CHECK([for location of SCCS get command], [make_cv_path_sccs_get], [ AS_IF([test -f /usr/sccs/get], [make_cv_path_sccs_get=/usr/sccs/get], [make_cv_path_sccs_get=get]) ]) AC_DEFINE_UNQUOTED([SCCS_GET], ["$make_cv_path_sccs_get"], [Define to the name of the SCCS 'get' command.]) ac_clean_files="$ac_clean_files s.conftest conftoast" # Remove these later. AS_IF([(/usr/sccs/admin -n s.conftest || admin -n s.conftest) >/dev/null 2>&1 && test -f s.conftest], [ # We successfully created an SCCS file. AC_CACHE_CHECK([if SCCS get command understands -G], [make_cv_sys_get_minus_G], [AS_IF([$make_cv_path_sccs_get -Gconftoast s.conftest >/dev/null 2>&1 && test -f conftoast], [make_cv_sys_get_minus_G=yes], [make_cv_sys_get_minus_G=no]) ]) AS_IF([test "$make_cv_sys_get_minus_G" = yes], [AC_DEFINE([SCCS_GET_MINUS_G], [1], [Define to 1 if the SCCS 'get' command understands the '-G' option.]) ]) ]) rm -f s.conftest conftoast # Check the system to see if it provides GNU glob. If not, use our # local version. AC_CACHE_CHECK([if system libc has GNU glob], [make_cv_sys_gnu_glob], [ AC_EGREP_CPP([gnu glob],[ #include #include #include #define GLOB_INTERFACE_VERSION 1 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 # include # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION gnu glob # endif #endif], [make_cv_sys_gnu_glob=yes], [make_cv_sys_gnu_glob=no])]) AS_IF([test "$make_cv_sys_gnu_glob" = no], [ GLOBINC='-I$(srcdir)/glob' GLOBLIB=glob/libglob.a ]) AC_SUBST([GLOBINC]) AC_SUBST([GLOBLIB]) # Tell automake about this, so it can build the right .c files. AM_CONDITIONAL([USE_LOCAL_GLOB], [test "$make_cv_sys_gnu_glob" = no]) # Let the makefile know what our build host is AC_DEFINE_UNQUOTED([MAKE_HOST],["$host"],[Build host information.]) MAKE_HOST="$host" AC_SUBST([MAKE_HOST]) w32_target_env=no AM_CONDITIONAL([WINDOWSENV], [false]) AS_CASE([$host], [*-*-mingw32], [AM_CONDITIONAL([WINDOWSENV], [true]) w32_target_env=yes AC_DEFINE([WINDOWS32], [1], [Use platform specific coding]) AC_DEFINE([HAVE_DOS_PATHS], [1], [Use platform specific coding]) ]) AC_DEFINE_UNQUOTED([PATH_SEPARATOR_CHAR],['$PATH_SEPARATOR'], [Define to the character that separates directories in PATH.]) # Include the Maintainer's Makefile section, if it's here. MAINT_MAKEFILE=/dev/null AS_IF([test -r "$srcdir/maintMakefile"], [ MAINT_MAKEFILE="$srcdir/maintMakefile" ]) AC_SUBST_FILE([MAINT_MAKEFILE]) # Allow building with dmalloc AM_WITH_DMALLOC # Forcibly disable SET_MAKE. If it's set it breaks things like the test # scripts, etc. SET_MAKE= # Sanity check and inform the user of what we found AS_IF([test "x$make_badcust" = xyes], [ echo echo "WARNING: --with-customs specified but no customs.h could be found;" echo " disabling Customs support." echo ]) AS_CASE([$with_customs], [""|n|no|y|ye|yes], [:], [AS_IF([test -f "$with_customs/lib/libcustoms.a"], [:], [ echo echo "WARNING: '$with_customs/lib' does not appear to contain the" echo " Customs library. You must build and install Customs" echo " before compiling GNU make." echo ])]) AS_IF([test "x$has_wait_nohang" = xno], [ echo echo "WARNING: Your system has neither waitpid() nor wait3()." echo " Without one of these, signal handling is unreliable." echo " You should be aware that running GNU make with -j" echo " could result in erratic behavior." echo ]) AS_IF([test "x$make_cv_job_server" = xno && test "x$user_job_server" = xyes], [ echo echo "WARNING: Make job server requires a POSIX-ish system that" echo " supports the pipe(), sigaction(), and either" echo " waitpid() or wait3() functions. Your system doesn't" echo " appear to provide one or more of those." echo " Disabling job server support." echo ]) AS_IF([test "x$make_cv_load" = xno && test "x$user_load" = xyes], [ echo echo "WARNING: 'load' support requires a POSIX-ish system that" echo " supports the dlopen(), dlsym(), and dlerror() functions." echo " Your system doesn't appear to provide one or more of these." echo " Disabling 'load' support." echo ]) # Specify what files are to be created. AC_CONFIG_FILES([ \ Makefile \ glob/Makefile \ po/Makefile.in \ config/Makefile \ doc/Makefile \ unittest/Makefile \ w32/Makefile \ tests/config-flags.pm ]) # OK, do it! AC_OUTPUT # We only generate the build.sh if we have a build.sh.in; we won't have # one before we've created a distribution. AS_IF([test -f "$srcdir/build.sh.in"], [ ./config.status --file build.sh chmod +x build.sh ]) AC_MSG_NOTICE([Will install the 'make' binary under the name: $make_name]) dnl Local Variables: dnl comment-start: "dnl " dnl comment-end: "" dnl comment-start-skip: "\\bdnl\\b\\s *" dnl compile-command: "make configure config.h.in" dnl End: remake-4.1+dbg1.3~dfsg.1/configure.bat000066400000000000000000000036541317072305000174540ustar00rootroot00000000000000@echo off rem Copyright (C) 1994-2014 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Configuring MAKE for DJGPP rem The SmallEnv trick protects against too small environment block, rem in which case the values will be truncated and the whole thing rem goes awry. COMMAND.COM will say "Out of environment space", but rem many people don't care, so we force them to care by refusing to go. rem Where is the srcdir? set XSRC=. if not "%XSRC%"=="." goto SmallEnv if "%1%"=="" goto SrcDone set XSRC=%1 if not "%XSRC%"=="%1" goto SmallEnv :SrcDone update %XSRC%/configh.dos ./config.h rem Do they have Make? redir -o junk.$$$ -eo make -n -f NUL rem REDIR will return 1 if it cannot run Make. rem If it can run Make, it will usually return 2, rem but 0 is also OK with us. if errorlevel 2 goto MakeOk if not errorlevel 1 goto MakeOk if exist junk.$$$ del junk.$$$ echo No Make program found--use DOSBUILD.BAT to build Make. goto End rem They do have Make. Generate the Makefile. :MakeOk del junk.$$$ update %XSRC%/Makefile.DOS ./Makefile echo Done. if not "%XSRC%"=="." echo Invoke Make thus: "make srcdir=%XSRC%" goto End :SmallEnv echo Your environment is too small. Please enlarge it and run me again. :End set XRSC= remake-4.1+dbg1.3~dfsg.1/debug.c000066400000000000000000000051451317072305000162320ustar00rootroot00000000000000/* Debugging macros and interface. Copyright (c) 2005, 2011 Rocky Bernstein GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "makeint.h" #include "make.h" #include "debug.h" #include "print.h" debug_level_mask_t debug_dummy_level_mask; debug_enter_debugger_t debug_dummy_enter_debugger_mask; int debug_flag = 0; /*! If true, enter the debugger before updating goal. */ bool b_debugger_goal = false; stringlist_t *db_flags; /** Toggle -d on receipt of SIGUSR1. */ #ifdef SIGUSR1 RETSIGTYPE debug_signal_handler (int sig) { UNUSED_ARGUMENT(sig); db_level = db_level ? DB_NONE : DB_BASIC; } #endif /*! Set the global db_level mask based on the command option list db_flags. */ void decode_debug_flags (int b_debug_flag, stringlist_t *ppsz_db_flags) { const char **pp; if (b_debug_flag) db_level = DB_ALL; if (!ppsz_db_flags) return; for (pp=ppsz_db_flags->list; *pp; ++pp) { const char *p = *pp; while (1) { switch (tolower (p[0])) { case 'a': db_level |= DB_ALL; break; case 'b': db_level |= DB_BASIC; break; case 'i': db_level |= DB_BASIC | DB_IMPLICIT; break; case 'j': db_level |= DB_JOBS; break; case 'm': db_level |= DB_BASIC | DB_MAKEFILES; break; case 'r': db_level |= DB_BASIC | DB_READ_MAKEFILES; break; case 'v': db_level |= DB_BASIC | DB_VERBOSE; break; default: OS ( fatal, NILF, _("unknown debug level specification `%s'"), p); } while (*(++p) != '\0') if (*p == ',' || *p == ' ') break; if (*p == '\0') break; ++p; } } } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debug.h000066400000000000000000000131071317072305000162340ustar00rootroot00000000000000/* Debugging macros and interface. Copyright (C) 1999-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 DEBUG_H #define DEBUG_H #include "types.h" /** \brief debug masks which control tracing output. Imagine the below enums values as define'd values rather than distinct values of an enum. The enum is more (gdb) debugger friendly in showing what's set (e.g. DB_NONE, DB_ALL, or a single value and in entering expressons (e.g print db_level & DB_BASIC). */ typedef enum { DB_NONE = 0x000, /**< Mask when none of the below are set. */ DB_BASIC = 0x001, /**< targets which need to be made and status; also set when tracing or debugging */ DB_VERBOSE = 0x002, /**< A more verbose trace */ DB_JOBS = 0x004, /**< Prints messages giving details on the invocation of specific subcommands. Can be set via --debug=jobs */ DB_IMPLICIT = 0x008, /**< Prints messages describing the implicit rule searches for each target. Can be set via --debug=implicit */ DB_TRACE = 0x010, /**< tracing */ DB_SHELL = 0x020, /**< add +x to SHELL invocations */ DB_MAKEFILES = 0x100, DB_READ_MAKEFILES = 0x200, /**< Reading makefiles */ DB_CALL = 0x400, /**< GNU Make function call and returns */ DB_UPDATE_GOAL = 0x800, /**< GNU Make function call and returns */ DB_ALL = 0xfff /**< Bitmask for all of the above. */ } debug_level_mask_t; typedef enum { DEBUGGER_ON_ERROR = 0x1, /**< Enter debugger on any error */ DEBUGGER_ON_FATAL = 0x2, /**< Enter debugger on a fatal error */ DEBUGGER_ON_SIG = 0x4 /**< Enter debugger on getting a signal */ } debug_enter_debugger_t; typedef enum { DEBUGGER_QUIT_RC = 77, /**< debugger issued a "quit" command. */ } debug_dummy_t; /** These variables are trickery to force the above enum symbol values to be recorded in debug symbol tables. It is used to allow one refer to above enumeration values in a debugger and debugger expressions */ extern debug_level_mask_t debug_dummy_level_mask; extern debug_enter_debugger_t debug_dummy_enter_debugger_mask; /** bitmask of debug_level_mask values. */ extern int db_level; /*! If 0 (or false) we are not in the debugger command read loop. If 1 (or true) we are in the debugger command read loop. If DEBUGGER_QUIT_RC we've requested to quit. */ extern int in_debugger; #include extern jmp_buf debugger_loop; /** \brief The structure used to hold the list of strings given in command switches of a type that takes string arguments. */ struct stringlist { const char **list; /**< Nil-terminated list of strings. */ unsigned int idx; /**< Index into above. */ unsigned int max; /**< Number of pointers allocated. */ }; extern int debug_flag; /*! If 1, we don't give additional error reporting information. */ extern int no_extended_errors; /*! If 1, we show variable definitions */ extern int show_variable_definitions; /*! If true, enter the debugger before updating goal target. */ extern bool b_debugger_goal; /*! If true, enter the debugger before reading any makefiles. */ extern bool b_debugger_preread; /*! If nonzero, we are debugging after each "step" for that many times. When we have a value 1, then we actually run the debugger read loop. Otherwise we decrement the step count. */ extern unsigned int i_debugger_stepping; /*! If nonzero, we are debugging after each "next" for that many times. When we have a value 1, then we actually run the debugger read loop. Otherwise we decrement the step count. */ extern unsigned int i_debugger_nexting; /*! If nonzero, enter the debugger if we hit a fatal error. */ extern unsigned int debugger_on_error; /*! If nonzero, we have requested some sort of debugging. */ extern unsigned int debugger_enabled; extern stringlist_t *db_flags; #define ISDB(_l) ((_l)&db_level) /*! Debugged print */ #define DBPRINT(_x) \ printf _x; fflush (stdout) /*! Debugged print indented a number of spaces given by "_depth" */ #define DBPRINTS(_x, _depth) \ print_spaces (_depth); \ DBPRINT(_x) /*! Debugged print if debug mask is set indented a number of spaces implied by global variable "depth" */ #define DBS(_l,_x) \ do { \ if(ISDB(_l)) { \ DBPRINTS(_x, depth); \ } \ } while(0) /*! Debugged print if debug mask is set indented a number of spaces given by "_depth" */ #define DBSD(_l,_x,_depth) \ do { \ if(ISDB(_l)) { \ DBPRINTS(_x, _depth); \ } \ } while(0) extern int db_level; #define ISDB(_l) ((_l)&db_level) #define DBF(_l,_x) do{ if(ISDB(_l)) {print_spaces (depth); \ printf (_x, file->name); \ fflush (stdout);} }while(0) #define DB(_l,_x) do{ if(ISDB(_l)) {printf _x; fflush (stdout);} }while(0) #endif /*DEBUG_H*/ remake-4.1+dbg1.3~dfsg.1/debugger.h000066400000000000000000000011171317072305000167300ustar00rootroot00000000000000#include "debug.h" #include "trace.h" /* Common debugger command function prototype */ typedef debug_return_t (*dbg_cmd_t) (char *psz_args); /* A structure which contains information on the commands this program can understand. */ typedef struct { dbg_cmd_t func; /* Function to call to do the job. */ const char *doc; /* Documentation for this function. */ const char *use; /* short command usage. */ } short_cmd_t; typedef struct { const char *long_name; /* long name of command. */ const char short_name; /* Index into short_cmd array. */ } long_cmd_t; remake-4.1+dbg1.3~dfsg.1/debugger/000077500000000000000000000000001317072305000165575ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/debugger/.gitignore000066400000000000000000000000171317072305000205450ustar00rootroot00000000000000/*~ /.dirstamp remake-4.1+dbg1.3~dfsg.1/debugger/Makefile000066400000000000000000000002711317072305000202170ustar00rootroot00000000000000# Whatever it is you want to do, it should be handled by the # by the main (parent) Makefile. So reissue make from there. .PHONY: all all: $(MAKE) -C .. $@ %: all $(MAKE) -C .. $@ remake-4.1+dbg1.3~dfsg.1/debugger/break.c000066400000000000000000000116041317072305000200110ustar00rootroot00000000000000/* Copyright (C) 2005, 2007-2008, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** debugger command stack routines. */ #include #include "break.h" #include "msg.h" #include "filedef.h" #include "print.h" /*! Node for an item in the target call stack */ struct breakpoint_node { file_t *p_target; unsigned int i_num; brkpt_mask_t brkpt_mask; breakpoint_node_t *p_next; }; /** Pointers to top/bottom of current breakpoint target stack */ breakpoint_node_t *p_breakpoint_top = NULL; breakpoint_node_t *p_breakpoint_bottom = NULL; brkpt_mask_t i_breakpoints = BRK_NONE; /*! Add "p_target" to the list of breakpoints. Return true if there were no errors */ bool add_breakpoint (file_t *p_target, const brkpt_mask_t brkpt_mask) { breakpoint_node_t *p_new = CALLOC (breakpoint_node_t, 1); if (!p_new) return false; /* Add breakpoint to list of breakpoints. */ if (!p_breakpoint_top) { assert(!p_breakpoint_bottom); p_breakpoint_top = p_breakpoint_bottom = p_new; } else { p_breakpoint_bottom->p_next = p_new; } p_breakpoint_bottom = p_new; p_new->p_target = p_target; p_new->i_num = ++i_breakpoints; p_new->brkpt_mask = brkpt_mask; /* Finally, note that we are tracing this target. */ if (p_target->tracing & (BRK_BEFORE_PREREQ & brkpt_mask)) { dbg_msg(_("Note: prerequisite breakpoint already set at target %s."), p_target->name); } if (p_target->tracing & (BRK_AFTER_PREREQ & brkpt_mask)) { dbg_msg(_("Note: command breakpoint already set at target %s."), p_target->name); } if (p_target->tracing & (BRK_AFTER_CMD & brkpt_mask)) { dbg_msg(_("Note: target end breakpont set at target %s."), p_target->name); } p_target->tracing = brkpt_mask; printf(_("Breakpoint %d on target %s, mask 0x%02x"), i_breakpoints, p_target->name, brkpt_mask); if (p_target->floc.filenm) dbg_msg(": file %s, line %lu.", p_target->floc.filenm, p_target->floc.lineno); else printf(".\n"); if (p_target->updated) dbg_msg("Warning: target is already updated; so it might not get stopped at again."); else if (p_target->updating && (brkpt_mask & (BRK_BEFORE_PREREQ | BRK_AFTER_PREREQ))) { dbg_msg("Warning: target is in the process of being updated;"); dbg_msg("so it might not get stopped at again."); } return true; } /*! Remove breakpoint i from the list of breakpoints. Return true if there were no errors */ bool remove_breakpoint (unsigned int i) { if (!i) { dbg_msg(_("Invalid Breakpoint number 0.")); return false; } if (i > i_breakpoints) { dbg_msg(_("Breakpoint number %d is too high. " "%d is the highest breakpoint number."), i, i_breakpoints); return false; } else { /* Find breakpoint i */ breakpoint_node_t *p_prev = NULL; breakpoint_node_t *p; for (p = p_breakpoint_top; p && p->i_num != i; p = p->p_next) { p_prev = p; } if (p && p->i_num == i) { /* Delete breakpoint */ if (!p->p_next) p_breakpoint_bottom = p_prev; if (p == p_breakpoint_top) p_breakpoint_top = p->p_next; if (p_prev) p_prev->p_next = p->p_next; if (p->p_target->tracing) { p->p_target->tracing = BRK_NONE; dbg_msg(_("Breakpoint %d on target %s cleared"), i, p->p_target->name); free(p); return true; } else { dbg_msg(_("No breakpoint at target %s; nothing cleared."), p->p_target->name); free(p); return false; } } else { dbg_msg(_("No Breakpoint number %d set."), i); return false; } } } /*! List breakpoints.*/ void list_breakpoints (void) { breakpoint_node_t *p; if (!p_breakpoint_top) { dbg_msg(_("No breakpoints.")); return; } dbg_msg( "Num Type Disp Enb Mask Target Location"); for (p = p_breakpoint_top; p; p = p->p_next) { printf("%3d breakpoint keep y 0x%02x %s", p->i_num, p->brkpt_mask, p->p_target->name); if (p->p_target->floc.filenm) { printf(" at "); print_floc_prefix(&(p->p_target->floc)); } printf("\n"); } } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/break.h000066400000000000000000000034021317072305000200130ustar00rootroot00000000000000/* Copyright (C) 2005, 2008, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file dbg_break.h * * \brief debugger command beakpoint routines. */ #ifndef DBG_BREAK_H #define DBG_BREAK_H #include "types.h" /*! Opaque type definition for an item in the breakpoint list. */ typedef struct breakpoint_node breakpoint_node_t; /** Pointers to top of current breakpoint list. */ extern breakpoint_node_t *p_breakpoint_top; /** Pointers to bottom of current breakpoint list. */ extern breakpoint_node_t *p_breakpoint_bottom; /** The largest breakpoint number previously given. When a new breakpoint is set it will be i_breakpoints+1. */ extern unsigned int i_breakpoints; /*! Add "p_target" to the list of breakpoints. Return true if there were no errors */ extern bool add_breakpoint (file_t *p_target, unsigned int brkp_mask); /*! Remove breakpoint i from the list of breakpoints. Return true if there were no errors */ extern bool remove_breakpoint (unsigned int i); /*! List breakpoints.*/ extern void list_breakpoints (void); #endif /* DBG_BREAK_H */ remake-4.1+dbg1.3~dfsg.1/debugger/cmd.c000066400000000000000000000323131317072305000174700ustar00rootroot00000000000000/* Copyright (C) 2004-2005, 2007-2009, 2011, 2014-2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* debugger command interface. */ #include "makeint.h" #include "msg.h" #include "debug.h" #include "debugger.h" #include "file.h" #include "print.h" #include "break.h" #include "cmd.h" #include "fns.h" #include "function.h" #include "info.h" #include "stack.h" #include "commands.h" #include "expand.h" #include "debug.h" #include "file2line.h" #ifdef HAVE_READLINE_READLINE_H #include #endif #ifdef HAVE_HISTORY_LIST #include #endif /** Think of the below not as an enumeration but as #defines done in a way that we'll be able to use the value in a gdb. **/ enum { MAX_FILE_LENGTH = 1000, } debugger_enum1; /** Command-line args after the command-name part. For example in: break foo the below will be "foo". **/ char *psz_debugger_args; debug_enter_reason_t last_stop_reason; #ifdef HAVE_LIBREADLINE #include #include /* The following line makes Solaris' gcc/cpp not puke. */ #undef HAVE_READLINE_READLINE_H #include /* From readline. ?? Should this be in configure? */ #ifndef whitespace #define whitespace(c) (((c) == ' ') || ((c) == '\t')) #endif /* A structure which contains information on the commands this program can understand. */ static debug_return_t dbg_cmd_set_var (char *psz_arg, int expand); /* Should be in alphabetic order by command name. */ long_cmd_t commands[] = { { "break", 'b' }, { "cd", 'C' }, { "comment", '#' }, { "continue", 'c' }, { "delete", 'd' }, { "down", 'D' }, { "edit" , 'e' }, { "eval" , 'E' }, { "expand" , 'x' }, { "finish" , 'F' }, { "frame" , 'f' }, { "help" , 'h' }, { "info" , 'i' }, { "list" , 'l' }, { "next" , 'n' }, { "print" , 'p' }, { "pwd" , 'P' }, { "quit" , 'q' }, { "run" , 'R' }, { "set" , '=' }, { "setq" , '"' }, { "setqx" , '`' }, { "shell" , '!' }, { "show" , 'S' }, { "source" , '<' }, { "skip" , 'k' }, { "step" , 's' }, { "target" , 't' }, { "up" , 'u' }, { "where" , 'T' }, { "write" , 'w' }, { (char *)NULL, ' '} }; typedef struct { const char *command; /* real command name. */ const char *alias; /* alias for command. */ } alias_cmd_t; /* Should be in alphabetic order by ALIAS name. */ alias_cmd_t aliases[] = { { "shell", "!!" }, { "help", "?" }, { "help", "??" }, { "break", "L" }, { "where", "backtrace" }, { "where", "bt" }, { "quit", "exit" }, { "run", "restart" }, { "quit", "return" }, { (char *)NULL, (char *) NULL} }; short_cmd_t short_command[256] = { { NULL, '\0', '\0' }, }; /* Look up NAME as the name of a command, and return a pointer to that command. Return a NULL pointer if NAME isn't a command name. */ static short_cmd_t * find_command (const char *psz_name) { unsigned int i; for (i = 0; aliases[i].alias; i++) { const int cmp = strcmp (psz_name, aliases[i].alias); if ( 0 == cmp ) { psz_name = aliases[i].command; break; } else /* Words should be in alphabetic order by alias name. Have we gone too far? */ if (cmp < 0) break; } for (i = 0; commands[i].long_name; i++) { const int cmp = strcmp (psz_name, commands[i].long_name); if ( 0 == cmp ) { return (&short_command[(uint8_t) commands[i].short_name]); } else /* Words should be in alphabetic order by command name. Have we gone too far? */ if (cmp < 0) break; } return ((short_cmd_t *)NULL); } #include "command/break.h" #include "command/chdir.h" #include "command/comment.h" #include "command/continue.h" #include "command/delete.h" #include "command/down.h" #include "command/edit.h" #include "command/eval.h" #include "command/expand.h" #include "command/finish.h" #include "command/frame.h" #include "command/info.h" #include "command/next.h" #include "command/list.h" #include "command/print.h" #include "command/pwd.h" #include "command/quit.h" #include "command/run.h" #include "command/set.h" #include "command/setq.h" #include "command/setqx.h" #include "command/shell.h" #include "command/show.h" #include "command/skip.h" #include "command/source.h" #include "command/step.h" #include "command/target.h" #include "command/up.h" #include "command/where.h" #include "command/write.h" /* Needs to come after dbg_cmd_show */ #include "command/help.h" static void cmd_initialize(void) { dbg_cmd_break_init ('b'); dbg_cmd_chdir_init ('C'); dbg_cmd_continue_init('c'); dbg_cmd_delete_init ('d'); dbg_cmd_down_init ('D'); dbg_cmd_edit_init ('e'); dbg_cmd_eval_init ('E'); dbg_cmd_finish_init ('F'); dbg_cmd_frame_init ('f'); dbg_cmd_help_init ('h'); dbg_cmd_info_init ('i'); dbg_cmd_skip_init ('k'); dbg_cmd_list_init ('l'); dbg_cmd_next_init ('n'); dbg_cmd_print_init ('p'); dbg_cmd_pwd_init ('P'); dbg_cmd_quit_init ('q'); dbg_cmd_run_init ('R'); dbg_cmd_source_init ('<'); dbg_cmd_show_init ('S'); dbg_cmd_step_init ('s'); dbg_cmd_target_init ('t'); dbg_cmd_up_init ('u'); dbg_cmd_where_init ('T'); dbg_cmd_write_init ('w'); dbg_cmd_expand_init ('x'); dbg_cmd_comment_init ('#'); dbg_cmd_set_init ('='); dbg_cmd_setq_init ('"'); dbg_cmd_setqx_init ('`'); dbg_cmd_shell_init ('!'); } /* Execute a command line. */ extern debug_return_t execute_line (char *psz_line) { unsigned int i = 0; short_cmd_t *command; char *psz_word = get_word(&psz_line); if (1 == strlen(psz_word)) { if ( NULL != short_command[(uint8_t) psz_word[0]].func ) command = &short_command[(uint8_t) psz_word[0]]; else command = NULL; } else { command = find_command (psz_word); } if (!command) { dbg_errmsg(_("No such debugger command: %s."), psz_word); return debug_readloop; } /* Get argument to command, if any. */ while (whitespace (psz_line[i])) i++; psz_debugger_args = psz_line + i; /* Call the function. */ return ((*(command->func)) (psz_debugger_args)); } /* Show history. */ debug_return_t dbg_cmd_show_command (const char *psz_args) { /* if (!psz_arg || *psz_arg) { ; } */ #ifdef HAVE_HISTORY_LIST HIST_ENTRY **hist_list = history_list(); unsigned int i; UNUSED_ARGUMENT(psz_args); if (!hist_list) return debug_readloop; for (i=0; hist_list[i]; i++) { dbg_msg("%5d %s", i, hist_list[i]->line); } #endif return debug_readloop; } /* Set a variable. Set "expand' to 1 if you want variable definitions inside the value getting passed in to be expanded before assigment. */ static debug_return_t dbg_cmd_set_var (char *psz_args, int expand) { if (!psz_args || 0==strlen(psz_args)) { dbg_msg(_("You need to supply a variable name.")); } else { variable_t *p_v; char *psz_varname = get_word(&psz_args); unsigned int u_len = strlen(psz_varname); while (*psz_args && whitespace (*psz_args)) *psz_args +=1; p_v = lookup_variable (psz_varname, u_len); if (p_v) { char *psz_value = expand ? variable_expand(psz_args) : psz_args; define_variable_in_set(p_v->name, u_len, psz_value, o_debugger, 0, NULL, &(p_v->fileinfo)); dbg_msg(_("Variable %s now has value '%s'"), psz_varname, psz_value); } else { p_v = try_without_dollar(psz_varname); if (p_v) { char *psz_value = expand ? variable_expand(psz_args) : psz_args; define_variable_in_set(p_v->name, u_len, psz_value, o_debugger, 0, NULL, &(p_v->fileinfo)); dbg_msg(_("Variable %s now has value '%s'"), psz_varname, psz_value); } } } return debug_readloop; } #endif /* HAVE_LIBREADLINE */ #define PROMPT_LENGTH 300 #include jmp_buf debugger_loop; /* Should be less that PROMPT_LENGTH / 2 - strlen("remake ") + log(history) We will make it much less that since people can't count more than 10 or so nested <<<<>>>>'s easily. */ #define MAX_NEST_DEPTH 10 debug_return_t enter_debugger (target_stack_node_t *p, file_t *p_target, int errcode, debug_enter_reason_t reason) { volatile debug_return_t debug_return = debug_readloop; static bool b_init = false; static bool b_readline_init = false; char open_depth[MAX_NEST_DEPTH]; char close_depth[MAX_NEST_DEPTH]; unsigned int i = 0; last_stop_reason = reason; if ( in_debugger == DEBUGGER_QUIT_RC ) { return continue_execution; } if ( i_debugger_stepping > 1 || i_debugger_nexting > 1 ) { /* Don't stop unless we are here from a breakpoint. But do decrement the step count. */ if (i_debugger_stepping) i_debugger_stepping--; if (i_debugger_nexting) i_debugger_nexting--; if (!p_target->tracing) return continue_execution; } else if ( !debugger_on_error && !(i_debugger_stepping || i_debugger_nexting) && p_target && !p_target->tracing && -2 != errcode ) return continue_execution; /* Clear temporary breakpoints. */ if (p_target && p_target->tracing & BRK_TEMP) switch(last_stop_reason) { case DEBUG_BRKPT_AFTER_CMD: case DEBUG_BRKPT_BEFORE_PREREQ: case DEBUG_BRKPT_AFTER_PREREQ: p_target->tracing = BRK_NONE; default: ; } #ifdef HAVE_LIBREADLINE if (use_readline_flag && !b_readline_init) { rl_initialize (); using_history (); add_history (""); b_readline_init = true; } #endif if (!b_init) { cmd_initialize(); file2lines.ht_size = 0; b_init = true; } /* Set initial frame position reporting area: 0 is bottom. */ p_target_loc = NULL; psz_target_name = ""; i_stack_pos = 0; p_stack = p_stack_top = p; p_floc_stack = p_stack_floc_top; /* Get the target name either from the stack top (preferred) or the passed in target. */ if (p && p->p_target) { p_target_loc = &(p->p_target->floc); psz_target_name = (char *) p->p_target->name; } else if (p_target) { p_target_loc = &(p_target->floc); psz_target_name = (char *) p_target->name; } for (i=0; i<=makelevel && i < MAX_NEST_DEPTH-5; i++) { open_depth[i] = '<'; close_depth[i] = '>'; } if ( MAX_NEST_DEPTH - 5 == i ) { close_depth[i] = open_depth[i] = '.'; i++; close_depth[i] = open_depth[i] = '.'; i++; close_depth[i] = open_depth[i] = '.'; i++; } open_depth[i] = close_depth[i] = '\0'; in_debugger = true; if (errcode) { if (-1 == errcode) { printf("\n***Entering debugger because we encountered an error.\n"); } else if (-2 == errcode) { if (0 == makelevel) { printf("\nMakefile terminated.\n"); dbg_msg("Use q to quit or R to restart"); } else { printf("\nMakefile finished at level %d. Use R to restart\n", makelevel); dbg_msg("the makefile at this level or 's', 'n', or 'F' to continue " "in parent"); in_debugger = DEBUGGER_QUIT_RC; } } else { printf("\n***Entering debugger because we encountered a fatal error.\n"); dbg_errmsg("Exiting the debugger will exit make with exit code %d.", errcode); } } print_debugger_location(p_target, reason, NULL); /* Loop reading and executing lines until the user quits. */ for ( debug_return = debug_readloop; debug_return == debug_readloop || debug_return == debug_cmd_error; ) { char prompt[PROMPT_LENGTH]; char *line=NULL; char *s; if (setjmp(debugger_loop)) dbg_errmsg("Internal error jumped back to debugger loop"); else { #ifdef HAVE_LIBREADLINE if (use_readline_flag) { snprintf(prompt, PROMPT_LENGTH, "remake%s%d%s ", open_depth, where_history(), close_depth); line = readline (prompt); } else #endif { snprintf(prompt, PROMPT_LENGTH, "remake%s0%s ", open_depth, close_depth); printf("%s", prompt); if (line == NULL) line = calloc(1, 2048); line = fgets(line, 2048, stdin); if (NULL != line) chomp(line); } if ( line ) { if ( *(s=stripwhite(line)) ) { add_history (s); debug_return=execute_line(s); } else { add_history ("step"); debug_return=dbg_cmd_step(""); } free (line); } else { dbg_cmd_quit(NULL); } } } if (in_debugger != DEBUGGER_QUIT_RC) in_debugger=false; return debug_return; } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/cmd.h000066400000000000000000000031161317072305000174740ustar00rootroot00000000000000/* Copyright (C) 2005, 2008, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file dbg_cmd.h * * \brief GNU Make debugger interface */ #ifndef REMAKE_DBG_CMD_H #define REMAKE_DBG_CMD_H #include "../job.h" #include "../buildargv.h" #include "../trace.h" extern debug_return_t enter_debugger (target_stack_node_t *p, file_t *p_target, int errcode, debug_enter_reason_t reason); extern debug_return_t execute_line (char *psz_line); extern debug_return_t dbg_cmd_help(char *psz_args); extern debug_return_t dbg_cmd_info(char *psz_args); extern debug_return_t dbg_cmd_target(char *psz_args); extern debug_return_t dbg_cmd_show(char *psz_args); extern debug_return_t dbg_cmd_where(char *psz_args); extern debug_return_t dbg_cmd_show_command(const char *psz_args); #endif /* DBG_CMD_H*/ /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/000077500000000000000000000000001317072305000201755ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/debugger/command/.gitignore000066400000000000000000000000041317072305000221570ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/debugger/command/Makefile000066400000000000000000000002771317072305000216430ustar00rootroot00000000000000# Whatever it is you want to do, it should be handled by the # by the main (parent) Makefile. So reissue make from there. .PHONY: all all: $(MAKE) -C ../.. $@ %: all $(MAKE) -C ../.. $@ remake-4.1+dbg1.3~dfsg.1/debugger/command/break.h000066400000000000000000000070451317072305000214400ustar00rootroot00000000000000/* Set a breakpoint at a target. With a target name, set a break before running commands of that target. Without argument, list all breaks. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_break (char *psz_args) { if (!psz_args || !*psz_args) { list_breakpoints(); return debug_readloop; } else { char *psz_target = get_word(&psz_args); char *psz_break_type; file_t *p_target; unsigned int i_brkpt_mask = BRK_NONE; /** FIXME: DRY with code in continue.h **/ if (p_stack && p_stack->p_target) { unsigned int u_lineno=0; f2l_entry_t entry_type; if (get_uint(psz_target, &u_lineno, false)) { p_target = target_for_file_and_line(p_stack->p_target->floc.filenm, u_lineno, &entry_type); if (F2L_TARGET == entry_type) { if (!p_target) { dbg_errmsg("Can't find target or pattern on line %s.\n" "Use 'info lines' to get a list of breakpoint lines.", psz_target); return debug_cmd_error; } } else { dbg_errmsg("No support of breakpoints on target patterns yet."); return debug_cmd_error; } } else p_target = lookup_file(variable_expand_set(psz_target, p_stack->p_target->variables)); } else { p_target = lookup_file(psz_target); } if (!p_target) { dbg_errmsg("Can't find target %s; breakpoint not set.", psz_target); return debug_cmd_error; } /* FIXME: Combine with code in continue. */ if (!(psz_args && *psz_args)) i_brkpt_mask = BRK_ALL; else { while ((psz_break_type = get_word(&psz_args))) { if (!(psz_break_type && *psz_break_type)) break; i_brkpt_mask |= get_brkpt_option(psz_break_type) ; } } add_breakpoint(p_target, i_brkpt_mask); } return debug_readloop; }; static void dbg_cmd_break_init(unsigned int c) { short_command[c].func = &dbg_cmd_break; short_command[c].use = _("break [TARGET|LINENUM] [all|run|prereq|end]*"); short_command[c].doc = _("Set a breakpoint at a target.\n" "With a target name or a line number, set a break before running commands\n" "of that target or line number. Without argument, list all breakpoints.\n" "There are 3 place where one may want to stop at and that name can\n" "be given as a last option. The stopping points are:\n" " - before prerequisite checking (prereq)\n" " - after prerequisite checking but before running commands (run)\n" " - after target is complete (end)\n" "\n" "To see a list of targets run \"info targets\"\n" "See also \"continue\".\n"); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/chdir.h000066400000000000000000000027731317072305000214500ustar00rootroot00000000000000/* Write commands associated with a given target. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Comment line - ingore text on line. */ static debug_return_t dbg_cmd_chdir (char *psz_args) { if (!psz_args || 0==strlen(psz_args)) { printf(_("Argument required (new working directory).\n")); } else { if ( 0 != chdir(psz_args) ) { printf("%s: %s\n", psz_args, strerror(1)); } else { printf (_("Working directory %s.\n"), psz_args); } } return debug_readloop; } static void dbg_cmd_chdir_init(unsigned int c) { short_command[c].func = &dbg_cmd_chdir; short_command[c].use = _("cd DIR"); short_command[c].doc = _("Set the working directory to DIR."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/comment.h000066400000000000000000000023131317072305000220070ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Comment line - ingore text on line. */ static debug_return_t dbg_cmd_comment (char *psz_args) { UNUSED_ARGUMENT(psz_args); return debug_readloop; } static void dbg_cmd_comment_init(unsigned int c) { short_command[c].func = &dbg_cmd_comment; short_command[c].use = _("comment TEXT"); short_command[c].doc = _("Ignore this line."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/continue.h000066400000000000000000000054421317072305000221770ustar00rootroot00000000000000/* Copyright (C) 2011, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Continue running program. */ static debug_return_t dbg_cmd_continue (char *psz_args) { if (psz_args && *psz_args) { char *psz_target = get_word(&psz_args); file_t *p_target = NULL; brkpt_mask_t i_brkpt_mask; /** FIXME: DRY with code in break.h **/ if (p_stack && p_stack->p_target) { char *psz_expanded_target = variable_expand_set(psz_target, p_stack->p_target->variables); if (*psz_expanded_target) { p_target = lookup_file(psz_expanded_target); } } else p_target = lookup_file(psz_target); if (!p_target) { printf("Can't find target %s; breakpoint not set.\n", psz_target); return debug_cmd_error; } /* FIXME: Combine with code in continue. */ psz_args = get_word(&psz_args); if (!(psz_args && *psz_args)) i_brkpt_mask = BRK_ALL; else { char *psz_break_type; i_brkpt_mask = get_brkpt_option(psz_args); while ((psz_break_type = get_word(&psz_args))) { if (!(psz_break_type && *psz_break_type)) break; i_brkpt_mask |= get_brkpt_option(psz_break_type) ; } } if (!add_breakpoint(p_target, i_brkpt_mask|BRK_TEMP)) return debug_cmd_error; } else { db_level = 0; } i_debugger_stepping = 0; i_debugger_nexting = 0; define_variable_in_set("MAKEFLAGS", sizeof("MAKEFLAGS")-1, "", o_debugger, 0, NULL, NULL); return continue_execution; }; static void dbg_cmd_continue_init(unsigned int c) { short_command[c].func = &dbg_cmd_continue; short_command[c].use = _("continue [TARGET [all|run|prereq|end]*]"); short_command[c].doc = _("Continue executing debugged Makefile until another breakpoint or\n" "stopping point. If a target is given and valid we set a temporary\n" "breakpoint at that target before continuing.\n" "\n" "When a target name is given, breakpoint properties can be given after\n" "the target name\n" "\n" "See also \"break\" and \"finish\".\n" ); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/delete.h000066400000000000000000000033501317072305000216110ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Delete some breakpoints. Arguments are breakpoint numbers with spaces in between."To delete all breakpoints, give no argument. */ static debug_return_t dbg_cmd_delete(char *psz_args) { int i_brkpt; char *psz_word; if (!psz_args || !*psz_args) { while(i_breakpoints) remove_breakpoint(1); return debug_readloop; } psz_word = get_word(&psz_args); while ( psz_word && *psz_word ) { if (get_int(psz_word, &i_brkpt, true)) { remove_breakpoint(i_brkpt); } psz_word = get_word(&psz_args); } return debug_readloop; } static void dbg_cmd_delete_init(unsigned int c) { short_command[c].func = &dbg_cmd_delete; short_command[c].use = _("delete breakpoint numbers.."); short_command[c].doc = _("Delete some breakpoints\n." "Arguments are breakpoint numbers with spaces in between.\n" "To delete all breakpoints, give no argument."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/down.h000066400000000000000000000027331317072305000213220ustar00rootroot00000000000000/** Move reported target frame postition down by psz_amount. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ debug_return_t dbg_cmd_frame_down(char *psz_amount) { int i_amount = 1; if (!psz_amount || !*psz_amount) { i_amount = 1; } else if (!get_int(psz_amount, &i_amount, true)) { return debug_readloop; } return dbg_adjust_frame(-i_amount, false); } static void dbg_cmd_down_init(unsigned int c) { short_command[c].func = &dbg_cmd_frame_down; short_command[c].use = _("down [AMOUNT]"); short_command[c].doc = _("Select and print the target this one caused to be examined.\n" "\tAn argument says how many targets down to go."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/edit.h000066400000000000000000000043051317072305000212750ustar00rootroot00000000000000/* edit starting at current location. */ /* Print working directory. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_edit(char *psz_args) { char *editor; if ((editor = (char *) getenv ("EDITOR")) == NULL) editor = "/bin/ex"; if (!psz_args || 0==strlen(psz_args)) { const gmk_floc *p_floc = get_current_floc(); if (p_floc) { unsigned int cmd_size = strlen(editor) + strlen(p_floc->filenm) + 20; char *edit_cmd = calloc(1, cmd_size); int rc; /* Quote the file name, in case it has whitespace or other special characters. */ snprintf(edit_cmd, cmd_size, "%s +%lu \"%s\"", editor, p_floc->lineno, p_floc->filenm); printf(_("Running %s\n"), edit_cmd); rc = system (edit_cmd); shell_rc_status(rc); } else { printf (_("cannot get target file location\n")); } } else { printf(_("The \"edit\" command does not take an argument: %s\n"), psz_args); } return debug_readloop; } static void dbg_cmd_edit_init(unsigned int c) { short_command[c].func = &dbg_cmd_edit; short_command[c].use = _("edit"); short_command[c].doc = _("edit" "" "Enter an editor using the current location. " "Uses EDITOR environment variable contents as editor (or ex as default)." "Assumes the editor positions at a file using options +linenumber filename."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/eval.h000066400000000000000000000034031317072305000212750ustar00rootroot00000000000000/* Parse and evaluate buffer and return the results. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_eval(char *psz_evalstring) { #if 0 if ('\0' == *psz_evalstring) { file_t *p_target; if (p_stack && p_stack->p_target) { p_target = p_stack->p_target; } else { printf(_("Default target not found here. You must supply one\n")); } if (p_target->name) printf(_("Running commands for target %s\n"), p_target->name); else printf(_("Running commands\n"), p_target->name); target_environment (p_target); new_job(p_target, p_stack); } else #else { func_eval(NULL, &psz_evalstring, NULL); reading_file = 0; } #endif return debug_readloop; } static void dbg_cmd_eval_init(unsigned int c) { short_command[c].func = &dbg_cmd_eval; short_command[c].use = _("eval STRING"); short_command[c].doc = _("parse and evaluate a string."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/expand.h000066400000000000000000000033311317072305000216250ustar00rootroot00000000000000/* Show a string with variable references expanded. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_expand (char *psz_string) { static char *psz_last_string = NULL; if (!psz_string || !*psz_string) { /* Use last target value */ if (psz_last_string) psz_string = psz_last_string; else { printf("No current expand string - must supply something to print\n"); return debug_readloop; } } if (dbg_cmd_show_exp(psz_string, true)) { if (psz_last_string) free(psz_last_string); psz_last_string = strdup(psz_string); } return debug_readloop; } static void dbg_cmd_expand_init(unsigned int c) { short_command[c].func = &dbg_cmd_expand; short_command[c].use = _("expand STRING"); short_command[c].doc = _("Show string with internal variables references expanded. See also \n" "\t\"print\"."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/finish.h000066400000000000000000000041431317072305000216300ustar00rootroot00000000000000/* Terminate execution. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_finish(char *psz_amount) { target_stack_node_t *p=p_stack; unsigned int i_amount=0; unsigned int i=0; if ('\0' != *psz_debugger_args) { if (!get_uint(psz_amount, &i_amount, true)) return debug_readloop; if (p_stack_top) { /* We have a target stack */ for (i=0 ; p ; p = p->p_parent, i++ ) { if (i_amount == i) break; } } } if (p) { i_debugger_nexting = 0; i_debugger_stepping = 0; p->p_shared_target->tracing |= (BRK_AFTER_CMD); define_variable_in_set("MAKEFLAGS", sizeof("MAKEFLAGS")-1, "", o_debugger, 0, NULL, NULL); return continue_execution; } else { if (i > i_amount) printf("Target level %u not found\n", i_amount); else printf("Level %u is too large; maximum value is %u.\n", i_amount, i-1); } return debug_readloop; } static void dbg_cmd_finish_init(unsigned int c) { short_command[c].func = &dbg_cmd_finish; short_command[c].use = _("finish [AMOUNT]"); short_command[c].doc = _("Run (step out) until finishing AMOUNT target levels up.\n" "The default value is 0, or after commands have been run.\n" ); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/frame.h000066400000000000000000000027331317072305000214450ustar00rootroot00000000000000/** Move reported target frame position to absolute position psz_frame. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ debug_return_t dbg_cmd_frame(char *psz_frame) { int i_frame; if (!psz_frame || !*psz_frame) { return debug_readloop; } else { if (!get_int(psz_frame, &i_frame, true)) return debug_readloop; } return dbg_adjust_frame(i_frame, true); } static void dbg_cmd_frame_init(unsigned int c) { short_command[c].func = &dbg_cmd_frame; short_command[c].use = _("frame N"); short_command[c].doc = _("Move target frame to N; In contrast to \"up\" or \"down\",\n" "\tthis sets to an absolute position. 0 is the top."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/help.h000066400000000000000000000105111317072305000212740ustar00rootroot00000000000000/* Write commands associated with a given target. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Debugger help command. */ void dbg_help_subcmd_entry(const char *psz_subcmd_name, const char *psz_fmt, subcommand_var_info_t *p_subcmd, bool full_info) { if (full_info) { const char *doc = p_subcmd->doc ? p_subcmd->doc : p_subcmd->short_doc; printf("%s ", psz_subcmd_name); printf("%s%s", p_subcmd->name, doc); } else { printf("%s ", psz_subcmd_name); printf(psz_fmt, p_subcmd->name, p_subcmd->short_doc); if (p_subcmd->var) { if (p_subcmd->b_onoff) printf(" is %s.", var_to_on_off(* (int *) p_subcmd->var)); else printf(" is %d.", *(int *)(p_subcmd->var)); } } printf("\n"); } debug_return_t dbg_help_subcmd(const char *psz_subcmd_name, short_cmd_t *p_command, const char *psz_args, subcommand_var_info_t *subcommands) { unsigned int i; if (!psz_args || !*psz_args) { printf("%s\n\n%s\n", p_command->use, p_command->doc); } else { for (i = 0; subcommands[i].name; i++) { if (is_abbrev_of(psz_args, subcommands[i].name, subcommands[i].min_abbrev)) { dbg_help_subcmd_entry(psz_subcmd_name, "%s%s", &(subcommands[i]), true); return debug_readloop; } } printf("There is no \"%s %s\" command.\n", psz_subcmd_name, psz_args); } return debug_readloop; } debug_return_t dbg_cmd_help(char *psz_args) { unsigned int i; if (!psz_args || !*psz_args) { printf (" Command Short Name Aliases\n"); printf (" ---------------------- ---------- ---------\n"); for (i = 0; commands[i].long_name; i++) { unsigned int j; bool b_alias = false; uint8_t s=commands[i].short_name; printf(" %-31s (%c)", short_command[s].use, commands[i].short_name); for (j = 0; aliases[j].alias; j++) { if (strcmp (commands[i].long_name, aliases[j].command) == 0) { if (!b_alias) { printf(" %s", aliases[j].alias); b_alias = true; } else { printf(", %s", aliases[j].alias); } } } printf("\n"); } printf("\nReadline command line editing (emacs/vi mode) is available.\n" "For more detailed help, type 'help COMAMND-NAME' or consult\n" "the online-documentation.\n"); } else { short_cmd_t *p_command; const char *psz_command = ""; if (1 == strlen(psz_args)) { if ( NULL != short_command[(uint8_t)psz_args[0]].func ) p_command = &short_command[(uint8_t)psz_args[0]]; else p_command = NULL; } else { psz_command = get_word(&psz_args); p_command = find_command (psz_command); } if (p_command) { if ( p_command->func == &dbg_cmd_info ) { return dbg_help_subcmd("info", p_command, psz_args, info_subcommands); } else if ( p_command->func == &dbg_cmd_show ) { return dbg_help_subcmd("show", p_command, psz_args, show_subcommands); } else if ( p_command->func == &dbg_cmd_set ) { return dbg_help_subcmd("set", p_command, psz_args, set_subcommands); } else { printf("%s\n\n", p_command->use); printf("%s\n", p_command->doc); } } else { printf("Undefined command `%s'. Try help for a list of commands.\n", psz_command); } } return debug_readloop; } static void dbg_cmd_help_init(unsigned int c) { short_command[c].func = &dbg_cmd_help; short_command[c].use = _("help [COMMAND]"); short_command[c].doc = _("Display list of commands (i.e. this help text.)\n" \ "\twith an command name, give only the help for that command."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/info.h000066400000000000000000000310211317072305000212760ustar00rootroot00000000000000/* Copyright (C) 2008, 2011 R. Bernstein rocky@gnu.org This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../../file.h" #include "../../implicit.h" #include "../../print.h" #include "../../main.h" #include "../../rule.h" #include "../../debug.h" #include "../../vpath.h" #include "../info.h" #include "../msg.h" #include "../stack.h" #include "../file2line.h" const char *WARRANTY = " NO WARRANTY\n" "\n" " 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n" "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n" "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n" "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n" "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n" "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n" "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n" "REPAIR OR CORRECTION.\n" "\n" " 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n" "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n" "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n" "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n" "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n" "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n" "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n" "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n" "POSSIBILITY OF SUCH DAMAGES.\n"; #include "../subcmd.h" subcommand_var_info_t info_subcommands[] = { { "break", "Show list of target breakpoints", "\n\nShow list of target breakpoints.", NULL, false, 1}, { "line", "Show where we are currently stopped", "\n\nShow line and Makefile name of where we are currently stopped.", NULL, false, 2}, { "lines", "Show possible breakpoint lines for all targets", "\n\nShow possible breakpoint lines for all targets.", NULL, false, 2}, { "locals", "Show target local variables and their values", "\n\nShow target local variables and their values.", NULL, false, 2}, { "files", "Show read-in Makefiles", "\n\nShow read-in Makefiles. The last is the one initially named.", NULL, false, 2}, { "frame", "Show target-stack frame", "\n\nShow target-stack frame.", NULL, false, 2}, { "rules", "Show implicit or pattern rules", " [VERBOSE]\n\n" "Show implicit or pattern rules. Add VERBOSE if you want more info." , NULL, false, 1}, { "program", "Show program information and why we are stopped", "\n\nShow program information and why we are stopped.", NULL, false, 1}, { "target", "Same as 'target'", "\n\nShow specific target information. See 'help target'.", NULL, false, 1}, { "targets", "Show a list of target names and file locations", " [NAMES|POSITIONS|TASKS|ALL]\n\n" "Show the explicitly-named targets found in read Makefiles.\n" "Suboptions are as follows:\n" " NAMES -- shows target names,\n" " POSITIONS -- shows the location in the Makefile\n" " ALL -- shows names and location\n" " TASKS -- shows target name if it has commands associated with it\n" "\n" "The default is ALL.", NULL, false, 7}, { "variables", "Show all GNU Make variables", "\n\nShow all GNU Make variables.", NULL, false, 2}, { "warranty", "Various kinds of warranty you do not have", "\n\nVarious kinds of warranty you do not have.", NULL, false, 1}, { NULL, NULL, NULL, NULL, false, 0} }; /*! Show target information: location, name, and description. */ static void dbg_cmd_info_target_entry (const file_t *p_target, info_target_output_mask_t output_mask) { const gmk_floc *p_floc = &p_target->floc; if (p_floc) { if ((p_floc->filenm) && (output_mask & INFO_TARGET_POSITION)) { printf("%s:%lu", p_floc->filenm, p_floc->lineno); if (output_mask & INFO_TARGET_NAME) printf(":\n"); else printf("\n"); } } if (output_mask & INFO_TARGET_NAME) { printf("\t%s", p_target->name); if (p_target->description) printf("\t# %s", p_target->description); printf("\n"); } else if ( (output_mask & INFO_TARGET_TASKS && (p_target->cmds || p_target->phony) && p_floc->filenm) || (output_mask & INFO_TARGET_NAME) ) { if (p_target->description) { printf("%s", p_target->name); printf("\t# %s\n", p_target->description); } else if (!(output_mask & INFO_TARGET_TASK_COMMENT)) { printf("%s\n", p_target->name); } } } int dbg_target_compare(const void *p1, const void *p2) { const struct file *p_target1 = *(const file_t **) p1; const struct file *p_target2 = *(const file_t **) p2; return strcmp(p_target1->name, p_target2->name); } void dbg_cmd_info_targets(info_target_output_mask_t output_mask) { struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, dbg_target_compare); struct file **file_end = file_slot_0 + files.ht_fill; struct file **pp_file_slot; struct file *p_target; for (pp_file_slot = file_slot_0; pp_file_slot < file_end; pp_file_slot++) { if ((p_target = *pp_file_slot) != NULL) dbg_cmd_info_target_entry(p_target, output_mask); } } /* Show line information. We want output to be compatible with gdb output.*/ void dbg_cmd_info_line() { if (p_stack_top && p_stack_top->p_target && p_stack_top->p_target->floc.filenm) { const gmk_floc *p_floc = &p_stack_top->p_target->floc; if (!basename_filenames && strlen(p_floc->filenm) && p_floc->filenm[0] != '/') dbg_msg("Line %lu of \"%s/%s\"", p_floc->lineno, starting_directory, p_floc->filenm); else dbg_msg("Line %lu of \"%s\"", p_floc->lineno, p_floc->filenm); } else { dbg_msg("No line number info recorded.\n"); } } void dbg_cmd_info_program() { printf(_("Starting directory `%s'\n"), starting_directory); printf(_("Program invocation:\n")); printf("\t"); dbg_print_invocation(); printf(_("Recursion level: %d\n"), makelevel); dbg_cmd_info_line(); switch (last_stop_reason) { case DEBUG_BRKPT_AFTER_CMD: printf(_("Program is stopped after running rule command(s).\n")); break; case DEBUG_BRKPT_BEFORE_PREREQ: printf(_("Program stopped before rule-prequisite checking.\n")); break; case DEBUG_BRKPT_AFTER_PREREQ: printf(_("Program is stopped after rule-prequisite checking.\n")); break; case DEBUG_GOAL_UPDATED_HIT: printf(_("Program stopped for updating a goal.\n")); printf("\n"); break; case DEBUG_READ_HIT: printf(_("Program stopped for reading a file.\n")); printf("\n"); break; case DEBUG_ERROR_HIT: printf(_("Program stopped after an error encountered.\n")); printf("\n"); break; case DEBUG_STEP_HIT: printf(_("Program stopped in stepping.\n")); printf("\n"); break; case DEBUG_STEP_COMMAND: printf(_("Program stopped in stepping before running rule command(s).\n")); printf("\n"); break; case DEBUG_EXPLICIT_CALL: printf(_("Program stopped from explicit debugger function call.\n")); printf("\n"); break; case DEBUG_NOT_GIVEN: printf(_("Reason not given.\n")); break; case DEBUG_STACK_CHANGING: /* Should not happen? */ break; } } /* Give some info regarding the running program. */ debug_return_t dbg_cmd_info(char *psz_args) { if (!psz_args || 0==strlen(psz_args)) { unsigned int i; for (i = 0; info_subcommands[i].name; i++) { dbg_help_subcmd_entry("info", "%-10s -- %s", &(info_subcommands[i]), false); } return debug_readloop; } else { char *psz_subcmd = get_word(&psz_args); if (0 == strcmp(psz_subcmd, "lines")) { file2lines_dump(); } else if (is_abbrev_of (psz_subcmd, "line", 2)) { dbg_cmd_info_line(); } else if (is_abbrev_of (psz_subcmd, "locals", 2)) { const char *psz_target = NULL; char *psz_subcmds = NULL; file_t *p_target = get_target(&psz_subcmds, &psz_target); if (p_target) { if (!p_target->variables) { initialize_file_variables (p_target, 0); set_file_variables (p_target); if (!p_target->variables) { printf("Can't get variable information for target %s\n", psz_target); return debug_readloop; } } } else { dbg_errmsg("No target information for %s.", psz_target); return debug_cmd_error; } hash_map_arg (&p_target->variables->set->table, print_variable_info, NULL); } else if (is_abbrev_of (psz_subcmd, "breakpoints", 1)) { list_breakpoints(); } else if (is_abbrev_of (psz_subcmd, "makefiles", 1) || is_abbrev_of (psz_subcmd, "files", 2)) { if (0 == strlen(psz_args)) print_read_makefiles(NULL); else { if (!print_read_makefiles(psz_args)) dbg_errmsg("File %s not in list of read-in files.", psz_args); } } else if (is_abbrev_of (psz_subcmd, "frame", 2)) { dbg_cmd_where(psz_args); } else if (is_abbrev_of (psz_subcmd, "program", 1)) { dbg_cmd_info_program(); } else if (is_abbrev_of (psz_subcmd, "rules", 1)) { if (0 == strlen(psz_args)) print_rule_data_base (false); else if (0 == strcmp(psz_args, "verbose")) print_rule_data_base (true); else { rule_t *r = find_rule(psz_args); if (r) print_rule(r, true); else dbg_errmsg(_("Rule %s not found.\n"), psz_args); } } else if (is_abbrev_of (psz_subcmd, "stack", 1)) { print_target_stack(p_stack_top, i_stack_pos, MAX_STACK_SHOW); } else if (0 == strcmp(psz_subcmd, "targets")) { /* Note: "targets" has to come before "target" */ info_target_output_mask_t output_type; if (0 == strlen(psz_args)) output_type = INFO_TARGET_POSITION_AND_NAME; else if (is_abbrev_of (psz_args, "all", 1)) output_type = INFO_TARGET_POSITION_AND_NAME; else if (is_abbrev_of (psz_args, "positions", 1)) output_type = INFO_TARGET_POSITION; else if (is_abbrev_of (psz_args, "names", 1)) output_type = INFO_TARGET_NAME; else if (is_abbrev_of (psz_args, "tasks", 1)) output_type = INFO_TARGET_TASKS; else { printf("Expecting 'all', 'positions', 'names', 'tasks', or nothing; got %s.\n", psz_args); return debug_cmd_error; } dbg_cmd_info_targets(output_type); } else if (is_abbrev_of (psz_subcmd, "target", 1)) { if (0 == strlen(psz_args)) { if (p_stack_top && p_stack_top->p_target && p_stack_top->p_target->name) printf("target: %s\n", p_stack_top->p_target->name); else { printf("target unknown\n"); } } else dbg_cmd_target(psz_args); } else if (is_abbrev_of (psz_subcmd, "variables", 1)) { print_variable_data_base(); } else if (is_abbrev_of (psz_subcmd, "vpath", 1)) { print_vpath_data_base (); } else if (is_abbrev_of (psz_subcmd, "warranty", 1)) { printf("%s", WARRANTY); } else { dbg_errmsg(_("Undefined command \"%s\". Try \"help info\"."), psz_subcmd); } } return debug_readloop; } static void dbg_cmd_info_init(unsigned int c) { short_command[c].func = &dbg_cmd_info; short_command[c].use = _("info [SUBCOMMAND]"); short_command[c].doc = _("Show program information regarding SUBCOMMAND.\n" "If SUBCOMMAND is not specified, give list of \"info\" subcommands."); } /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/list.h000066400000000000000000000046021317072305000213230ustar00rootroot00000000000000/* Continue until the next command to be executed. */ #define DEPENDS_COMMANDS " depends commands" static debug_return_t dbg_cmd_list(char *psz_arg) { const char *psz_target = NULL; char *target_cmd = NULL; file_t *p_target; if (psz_arg && 0 == strcmp(psz_arg, "-")) { /* Show info for parent target. */ if (p_stack_top) { /* We have a target stack */ target_stack_node_t *p=p_stack; if (!p) { dbg_errmsg(_("We don't seem to have a target to get parent of.")); return debug_cmd_error; } p = p->p_parent; if (!p) { dbg_errmsg(_("We don't seem to have a parent target.")); return debug_cmd_error; } p_target = p->p_target; psz_target = p_target->name; } else { dbg_errmsg(_("We don't seem to have a target stack to get parent of.")); return debug_cmd_error; } } else { unsigned int u_lineno=0; f2l_entry_t entry_type; if (get_uint(psz_arg, &u_lineno, false)) { if (p_stack) { p_target = target_for_file_and_line(p_stack->p_target->floc.filenm, u_lineno, &entry_type); if (!p_target) { dbg_errmsg("Can't find target or pattern on line %s.\n" "Use 'info lines' to get a list of and pattern lines.", psz_arg); return debug_cmd_error; } psz_target = p_target->name; } else { dbg_errmsg(_("We don't seem to have a target stack to get parent of.")); return debug_cmd_error; } } else p_target = get_target(&psz_arg, &psz_target); } if (!p_target) { dbg_errmsg(_("Trouble getting a target name for %s."), psz_target); return debug_cmd_error; } print_floc_prefix(&p_target->floc); target_cmd = CALLOC(char, strlen(psz_target) + 1 + strlen(DEPENDS_COMMANDS)); sprintf(target_cmd, "%s%s", psz_target, DEPENDS_COMMANDS); return dbg_cmd_target(target_cmd); } static void dbg_cmd_list_init(unsigned int c) { short_command[c].func = &dbg_cmd_list; short_command[c].use = _("list [TARGET|LINE-NUMBER]"); short_command[c].doc = _("List target dependencies and commands for TARGET or LINE NUMBER.\n" "Without a target name or line number, use the current target.\n" "A target name of '-' will use the parent target on the target stack.\n" ); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/next.h000066400000000000000000000033001317072305000213200ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Continue until the next command to be executed. */ static debug_return_t dbg_cmd_next(char *psz_arg) { if (!psz_arg || !*psz_arg) { i_debugger_nexting = 1; i_debugger_stepping = 0; define_variable_in_set("MAKEFLAGS", sizeof("MAKEFLAGS")-1, "", o_debugger, 0, NULL, NULL); return continue_execution; } if (get_uint(psz_arg, &i_debugger_nexting, true)) return continue_execution; else return continue_execution; return debug_readloop; } static void dbg_cmd_next_init(unsigned int c) { short_command[c].func = &dbg_cmd_next; short_command[c].use = _("next [AMOUNT]"); short_command[c].doc = _("Continue until the next command to be executed.\n" "Argument AMOUNT means do this AMOUNT times (or until there's another\n" "reason to stop."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/print.h000066400000000000000000000036551317072305000215130ustar00rootroot00000000000000/* Show a variable definition. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_print(char *psz_args) { char *psz_name; static char *psz_last_name = NULL; if (!psz_args || 0==strlen(psz_args)) { /* Use last value */ if (psz_last_name) psz_name = psz_last_name; else { printf("No current variable - must supply something to print\n"); return debug_readloop; } } else { psz_name = get_word(&psz_args); } if (dbg_cmd_show_exp(psz_name, false)) { if (psz_last_name) free(psz_last_name); psz_last_name = strdup(psz_name); } return debug_readloop; } static void dbg_cmd_print_init(unsigned int c) { short_command[c].func = &dbg_cmd_print; short_command[c].use = _("print {VARIABLE [attrs...]}"); short_command[c].doc = _("Show a variable definition.\n" "The value is shown with embedded\n" "variable-references unexpanded. Don't include $ before a variable\n" "name. See also \"examine\".\n\n" "If no variable is supplied, we try to use the\n" "last value given." ); } /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/pwd.h000066400000000000000000000030511317072305000211370ustar00rootroot00000000000000/* Print working directory. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static debug_return_t dbg_cmd_pwd(char *psz_args) { if (!psz_args || 0==strlen(psz_args)) { char wd[300]; if (NULL == getcwd (wd, sizeof(wd))) { printf (_("cannot get current directory %s\n"), strerror(errno)); } else { printf (_("Working directory %s.\n"), wd); } } else { printf(_("The \"pwd\" command does not take an argument: %s\n"), psz_args); } return debug_readloop; } static void dbg_cmd_pwd_init(unsigned int c) { short_command[c].func = &dbg_cmd_pwd; short_command[c].use = _("pwd"); short_command[c].doc = _("Print working directory. This is used for your program as well."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/quit.h000066400000000000000000000033241317072305000213320ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Terminate execution. */ static debug_return_t dbg_cmd_quit(char *psz_arg) { if (!psz_arg || !*psz_arg) { in_debugger = DEBUGGER_QUIT_RC; dbg_msg("remake: That's all, folks..."); die(DEBUGGER_QUIT_RC); } else { int rc=0; if (get_int(psz_arg, &rc, true)) { dbg_msg("remake: That's all, folks..."); die(rc); } } return debug_readloop; } static void dbg_cmd_quit_init(unsigned int c) { short_command[c].func = &dbg_cmd_quit; short_command[c].use = _("quit [exit-status]"); short_command[c].doc = _("Exit make. If a numeric argument is given, it will be the exit\n" "status reported back. A status of 77 in a nested make will signals\n" "termination in the parent. So if no numeric argument is given and\n" "MAKELEVEL is 0, then status 0 is set; otherwise it is 77." ); } /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/run.h000066400000000000000000000022251317072305000211530ustar00rootroot00000000000000/* Restart/run program. */ static debug_return_t dbg_cmd_run(char *psz_arg) { char * const *ppsz_argv = (char * const *)global_argv; const char *psz_make_cmd = global_argv[0]; printf("Changing directory to %s and restarting...\n", directory_before_chdir); if (chdir(directory_before_chdir) == -1) fprintf(stderr, "changing working directory; %s\n", strerror(errno)); if (psz_arg && strlen(psz_arg)) { unsigned int len = strlen(global_argv[0]) + strlen(psz_arg) + 2; char *psz_full_args = CALLOC(char, len); snprintf(psz_full_args, len, "%s %s", global_argv[0], psz_arg); ppsz_argv = buildargv(psz_full_args); free(psz_full_args); } execvp (psz_make_cmd, ppsz_argv); /* NOT USED: */ return debug_readloop; } static void dbg_cmd_run_init(unsigned int c) { short_command[c].func = &dbg_cmd_run; short_command[c].use = _("run [ARGS]"); short_command[c].doc = _("Run Makefile from the beginning.\n" "You may specify arguments to give it.\n" "With no arguments, uses arguments last specified (with \"run\")"); } /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/set.h000066400000000000000000000113511317072305000211420ustar00rootroot00000000000000/* Set a variable definition with all variable references in the value part of psz_string expanded. */ /* Copyright (C) 2011, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Documentation for help set, and help set xxx. Note the format has been customized to make ddd work. In particular for "basename" it should be set basename -- Set if were are to show shor or long filenames is off. (or "is on"). */ #include "../subcmd.h" subcommand_var_info_t set_subcommands[] = { { "basename", "Set if we are to show short or long filenames", " {on|off|toggle} \n\nSet if we are to show short or long filenames.", &basename_filenames, true, 1}, { "debug", "Set GNU Make debug mask (set via --debug or -d)", " VALUE \n\nSet GNU Make debug mask (set via --debug or -d).", &db_level, false, 3}, { "ignore-errors", "Set value of GNU Make --ignore-errors (or -i) flag", " {on|off|toggle} \n\nSet value of GNU Make --ignore-errors (or -i) flag.", &ignore_errors_flag, true, 3}, { "keep-going", "Set value of GNU Make --keep-going (or -k) flag", " {on|off|toggle}\n\nSet value of GNU Make --keep-going (or -k) flag.", &keep_going_flag, true, 1}, { "silent", "Set value of GNU Make --silent (or -s) flags.", " {on|off|toggle} \n\nSet value of GNU Make --silent (or -s) flags.", &silent_flag, true, 1}, #ifdef FIXED { "trace", "Set value of shell_tracing.", NULL, &no_shell_trace, false, 3}, #endif { "variable", "Change a debugger setting", " OPTION is one of: basename, debug, ignore-errors, keep-going, or silent\n\n" "\n" "See also 'setq' and 'setqx' for setting a GNU Make variable.", NULL, false, 0}, { NULL, NULL, NULL, NULL, false, 0} }; static bool dbg_cmd_set_bool(const char *psz_varname, const char *psz_flag_name, const char *psz_flag_value, unsigned int min, int *p_bool_flag) { if (is_abbrev_of (psz_varname, psz_flag_name, min)) { if (!psz_flag_value || 0==strlen(psz_flag_value)) on_off_toggle(psz_flag_value, p_bool_flag); else on_off_toggle(psz_flag_value, p_bool_flag); dbg_cmd_show((char *) psz_flag_name); return true; } return false; } static debug_return_t dbg_cmd_set(char *psz_args) { if (!psz_args || 0==strlen(psz_args)) { unsigned int i; for (i = 0; set_subcommands[i].name; i++) { dbg_help_subcmd_entry("set", "%-10s -- %s", &(set_subcommands[i]), false); } return debug_readloop; } else { char *psz_varname = get_word(&psz_args); subcommand_var_info_t *p_subcmd_info; while (*psz_args && whitespace (*psz_args)) *psz_args +=1; /* FIXME, add min to above table and DRY below code. */ if (is_abbrev_of (psz_varname, "debug", 3)) { int dbg_mask; if (get_int(psz_args, &dbg_mask, true)) { db_level = dbg_mask; } dbg_cmd_show(psz_varname); return debug_readloop; } else if (is_abbrev_of (psz_varname, "variable", 3)) { /* Treat as set variable */ return dbg_cmd_set_var(psz_args, 1); #if FIXME_SET_ARGS } else if (is_abbrev_of (psz_varname, "args", 3)) { ... #endif } else for (p_subcmd_info = set_subcommands; p_subcmd_info && p_subcmd_info->name; p_subcmd_info++) { if (dbg_cmd_set_bool(psz_varname, p_subcmd_info->name, psz_args, p_subcmd_info->min_abbrev, p_subcmd_info->var)) return debug_readloop; } dbg_errmsg("Unknown set option %s\nSee 'help set' for options. Or did you mean setq?\n", psz_varname); return debug_cmd_error; } } static void dbg_cmd_set_init(unsigned int c) { short_command[c].func = &dbg_cmd_set; short_command[c].use = _("set OPTION {on|off|toggle}"); short_command[c].doc = _("Set debugger boolean value for OPTION.\n" "Run `set' for a list of options and current values\n" "\n" "See also 'setq'." ); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/setq.h000066400000000000000000000026441317072305000213300ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Set a variable definition without variable references but don't expand variable references in the value part of psz_string. */ static debug_return_t dbg_cmd_setq(char *psz_string) { dbg_cmd_set_var(psz_string, 0); return debug_readloop; } static void dbg_cmd_setq_init(unsigned int c) { short_command[c].func = &dbg_cmd_setq; short_command[c].use = _("setq VARIABLE VALUE"); short_command[c].doc = _("Set MAKE variable VARIABLE to VALUE. Variable definitions\n" "\tinside VALUE is expanded before assignment occurs." "\nSee also 'setqx'."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/setqx.h000066400000000000000000000026551317072305000215220ustar00rootroot00000000000000/* Copyright (C) 2011, 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Set a variable definition without variable references but don't expand variable references in the value part of psz_string. */ static debug_return_t dbg_cmd_setqx(char *psz_string) { dbg_cmd_set_var(psz_string, 1); return debug_readloop; } static void dbg_cmd_setqx_init(unsigned int c) { short_command[c].func = &dbg_cmd_setqx; short_command[c].use = _("setqx VARIABLE VALUE"); short_command[c].doc = _("Set MAKE variable VARIABLE to VALUE. Variable definitions\n" "\tinside VALUE is expanded before assignment occurs." "\nSee also 'setq'."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/shell.h000066400000000000000000000024271317072305000214620ustar00rootroot00000000000000/* Run a shell command. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include static debug_return_t dbg_cmd_shell(char *psz_varname) { int rc=system(psz_varname); shell_rc_status(rc); return debug_readloop; } static void dbg_cmd_shell_init(unsigned int c) { short_command[c].func = &dbg_cmd_shell; short_command[c].use = _("shell STRING"); short_command[c].doc = _("Execute the rest of the line as a shell."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/show.h000066400000000000000000000076241317072305000213370ustar00rootroot00000000000000/* Show debugger settings. */ /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../subcmd.h" subcommand_var_info_t show_subcommands[] = { { "args", "Show argument list to give program when it is started", NULL, NULL, false, 1}, { "basename", "Show if we are to show short or long filenames", NULL, &basename_filenames, true, 1}, { "commands", "Show the history of commands you typed.", NULL, NULL, false, 1}, { "debug", "GNU Make debug mask (set via --debug or -d)", NULL, &db_level, false, 1}, { "ignore-errors", "Value of GNU Make --ignore-errors (or -i) flag", NULL, &ignore_errors_flag, true, 1}, { "keep-going", "Value of GNU Make --keep-going (or -k) flag", NULL, &keep_going_flag, true, 1}, { "silent", "Value of GNU Make --silent (or -s) flags", NULL, &silent_flag, true, 1}, #ifdef FIXED { "trace", "Value of GNU Make --silent (or -s) flags", NULL, &no_shell_trace, true, 1}, #endif { "version", "Show the version of GNU Make + dbg.", NULL, NULL, false, 1}, { "warranty", "Various kinds of warranty you do not have.", NULL, NULL, false, 1}, { NULL, NULL, NULL, NULL, false, 0} }; debug_return_t dbg_cmd_show(char *psz_arg) { if (!psz_arg || 0==strlen(psz_arg)) { unsigned int i; for (i=0; show_subcommands[i].name; i++) { if ( 0 == strcmp(show_subcommands[i].name, "warranty") || 0 == strcmp(show_subcommands[i].name, "history")) continue; dbg_help_subcmd_entry("show", "%-10s -- %s", &(show_subcommands[i]), false); } } else { if (is_abbrev_of (psz_arg, "args", 3)) { print_cmdline(); } else if (is_abbrev_of (psz_arg, "basename", 4)) { printf("basename is %s.\n", var_to_on_off(basename_filenames)); } else if (is_abbrev_of (psz_arg, "debug", 3)) { printf("debug is 0x%x.\n", db_level); print_db_level(db_level); } else if (is_abbrev_of (psz_arg, "commands", 3)) { dbg_cmd_show_command(psz_arg); } else if (is_abbrev_of (psz_arg, "ignore-errors", 3)) { printf("ignore-errors is %s.\n", var_to_on_off(ignore_errors_flag)); } else if (is_abbrev_of (psz_arg, "keep-going", 4)) { printf("keep-going is %s.\n", var_to_on_off(keep_going_flag)); } else if (is_abbrev_of (psz_arg, "silent", 3)) { printf("silent is %s.\n", var_to_on_off(silent_flag)); } else if (is_abbrev_of (psz_arg, "version", 3)) { printf("version: %s\n", version_string); } else if (is_abbrev_of (psz_arg, "warranty", 3)) { printf("warranty: "); printf("%s", WARRANTY); } else { printf("Undefined command \"%s\". Try \"help show\"\n", psz_arg); } } return debug_readloop; } static void dbg_cmd_show_init(unsigned int c) { short_command[c].func = &dbg_cmd_show; short_command[c].use = _("show [SUBCOMMAND]"); short_command[c].doc = _("Show debugger information regarding SUBCOMMAND.\n" "If no SUBCOMMAND is specified, give a list of \"show\" subcommands."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/skip.h000066400000000000000000000023061317072305000213150ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Skip over next command or action. */ static debug_return_t dbg_cmd_skip (char *psz_arg) { UNUSED_ARGUMENT(psz_arg); return skip_execution; } static void dbg_cmd_skip_init(unsigned int c) { short_command[c].func = &dbg_cmd_skip; short_command[c].use = _("skip"); short_command[c].doc = _("Skip execution of next command or action." ); } /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/source.h000066400000000000000000000037101317072305000216470ustar00rootroot00000000000000/* Continue until the next command to be executed. */ #define DEPENDS_COMMANDS " depends commands" #include static debug_return_t dbg_cmd_source(char *psz_filename) { if (psz_filename && *psz_filename) { wordexp_t p; FILE *p_source_file; char *psz_expanded_file; wordexp(psz_filename, &p, 0); if (0 == p.we_wordc) { struct stat stat_buf; int ret = stat(psz_filename, &stat_buf); if (ret != 0) { dbg_errmsg("Can't find file %s:\n\t%s", psz_filename, strerror(errno)); return debug_cmd_error; } psz_expanded_file = psz_filename; } else if (1 != p.we_wordc) { dbg_errmsg("Expansion of %s doesn't lead to a single filename. \n" "Got %zu matches", psz_filename, p.we_wordc); return debug_cmd_error; } else { psz_expanded_file = p.we_wordv[0]; } p_source_file = fopen(psz_expanded_file, "r"); if (p_source_file != NULL) { debug_return_t debug_return = debug_readloop; char line[2048]; while (!feof(p_source_file) && debug_return == debug_readloop) { char *s; char *shut_up_gcc_warning = fgets(line, 2048, p_source_file); if (feof(p_source_file)) break; chomp(shut_up_gcc_warning); if ( *(s=stripwhite(line)) ) debug_return=execute_line(s); } fclose(p_source_file); } else dbg_errmsg("error reading file %s (expanded to %s):\n\t%s", psz_filename, psz_expanded_file, strerror(errno)); wordfree(&p); } else { dbg_errmsg("Expecting a file name"); return debug_cmd_error; } return debug_readloop; } static void dbg_cmd_source_init(unsigned int c) { short_command[c].func = &dbg_cmd_source; short_command[c].use = _("source FILENAME"); short_command[c].doc = _("Execute debugger commands from FILENAME.\n"); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/step.h000066400000000000000000000035761317072305000213340ustar00rootroot00000000000000/* Copyright (C) 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Step execution until another stopping point is reached Argument N means do this N times (or until there's another reason to stop. */ static debug_return_t dbg_cmd_step (char *psz_arg) { if (!psz_arg || !*psz_arg) { i_debugger_stepping = 1; i_debugger_nexting = 0; define_variable_in_set("MAKEFLAGS", sizeof("MAKEFLAGS")-1, "X", o_debugger, 0, NULL, NULL); return continue_execution; } if (get_uint(psz_arg, &i_debugger_stepping, true)) { define_variable_in_set("MAKEFLAGS", sizeof("MAKEFLAGS")-1, "X", o_debugger, 0, NULL, NULL); i_debugger_nexting = 0; return continue_execution; } else return debug_readloop; } static void dbg_cmd_step_init(unsigned int c) { short_command[c].func = &dbg_cmd_step; short_command[c].use = _("step [AMOUNT]"); short_command[c].doc = _("Step execution until another stopping point is reached.\n" "Argument AMOUNT means do this AMOUNT times (or until there's another\n" "reason to stop."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/target.h000066400000000000000000000070301317072305000216340ustar00rootroot00000000000000/* Show a variable or target definition. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ debug_return_t dbg_cmd_target(char *psz_args) { const char *psz_target; file_t *p_target = get_target(&psz_args, &psz_target); if (p_target) { print_target_mask_t i_mask = 0; char *psz_word; while( (psz_word = get_word(&psz_args))) { if (!*psz_word) { break; } else if (is_abbrev_of(psz_word, "depends", 1)) { i_mask |= PRINT_TARGET_DEPEND; } else if (is_abbrev_of(psz_word, "order", 1)) { i_mask |= PRINT_TARGET_ORDER; } else if (is_abbrev_of(psz_word, "nonorder", 1)) { i_mask |= PRINT_TARGET_NONORDER; } else if (is_abbrev_of(psz_word, "attributes", 1)) { i_mask |= PRINT_TARGET_ATTRS; } else if (is_abbrev_of(psz_word, "state", 1)) { i_mask |= PRINT_TARGET_STATE; } else if (is_abbrev_of(psz_word, "time", 1)) { i_mask |= PRINT_TARGET_TIME; } else if (is_abbrev_of(psz_word, "variables", 1)) { i_mask |= PRINT_TARGET_VARS; } else if (is_abbrev_of(psz_word, "commands", 1)) { i_mask |= PRINT_TARGET_CMDS; } else if (is_abbrev_of(psz_word, "expand", 1)) { i_mask |= (PRINT_TARGET_CMDS_EXP); } else if (is_abbrev_of(psz_word, "previous", 1)) { i_mask |= PRINT_TARGET_PREV; } else { printf("Don't understand attribute '%s'\n", psz_word); return debug_readloop; } } if (0 == i_mask) i_mask = PRINT_TARGET_ALL & (~PRINT_TARGET_VARS_HASH); if (i_mask & PRINT_TARGET_VARS) { initialize_file_variables (p_target, 0); set_file_variables (p_target); } print_target_props(p_target, i_mask); } return debug_readloop; } static void dbg_cmd_target_init(unsigned int c) { short_command[c].func = &dbg_cmd_target; short_command[c].use = _("target [TARGET-NAME] [info1 [info2...]]"); short_command[c].doc = _("Show information about a target.\n" "\nThe following attributes names can be given after a target name:\n" " attributes - rule attributes: precious, rule search, and pattern stem\n" " commands - shell commands that are run to update the target\n" " expand - like 'commands', but Makefile variables are expanded\n" " nonorder - non-order dependencies\n" " order - order dependencies\n" " depends - all target dependencies, i.e. order and non-order\n" " previous - previous target name hwen there are multiple double-colons\n" " state - shell command state\n" " time - last modification time and whether file has been updated\n" " variables - automatically set variables such as @ or <\n" "\n" "TARGET-NAME can be a variable like `@' (current target) or `<'\n" "(first dependency). If no variable or target name is supplied\n" "we to use the current target name.\n" ); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/up.h000066400000000000000000000027201317072305000207730ustar00rootroot00000000000000/** Move reported target frame position up by psz_amount. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ debug_return_t dbg_cmd_up (char *psz_amount) { unsigned int i_amount=1; if (!psz_amount || !*psz_amount) { i_amount = 1; } else { if (!get_uint(psz_amount, &i_amount, true)) return debug_readloop; } return dbg_adjust_frame(i_amount, false); } static void dbg_cmd_up_init(unsigned int c) { short_command[c].func = &dbg_cmd_up; short_command[c].use = _("up [AMOUNT]"); short_command[c].doc = _("Select and print target that caused this one to be examined.\n" "An argument says how many targets up to go."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/where.h000066400000000000000000000034761317072305000214720ustar00rootroot00000000000000/* Write commands associated with a given target. */ /* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Show target call stack info. */ debug_return_t dbg_cmd_where (char *psz_amount) { int i_amount; if (!psz_amount || !*psz_amount) { i_amount = MAX_STACK_SHOW; } else if (!get_int(psz_amount, &i_amount, true)) { return debug_readloop; } if (p_stack_top) print_target_stack (p_stack_top, i_stack_pos, i_amount); if (p_stack_floc_top) print_floc_stack (i_stack_pos, i_amount); /* If we are in a recursive Make, show the command invocation */ if (makelevel > 0) { printf("Most-recent (level %d) invocation:\n\t", makelevel); dbg_print_invocation(); } return debug_readloop; } static void dbg_cmd_where_init(unsigned int c) { short_command[c].func = &dbg_cmd_where; short_command[c].use = _("where"); short_command[c].doc = _("Print target stack or Makefile include stack.\n" "An argument specifies the maximum amount of entries to show."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/command/write.h000066400000000000000000000133261317072305000215050ustar00rootroot00000000000000/* Write commands associated with a given target. */ /* Copyright (C) 2011, 2017 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../../dep.h" static debug_return_t dbg_cmd_write(char *psz_args) { file_t *p_target = NULL; const char *psz_target = NULL; int b_stdout = 0; p_target = get_target(&psz_args, &psz_target); if (p_target) { variable_t *p_v = lookup_variable ("SHELL", strlen ("SHELL")); char *psz_filename = NULL; FILE *outfd; char *s; if (! p_target->cmds || ! p_target->cmds->commands) { printf(_("Target \"%s\" doesn't have commands associated with it.\n"), psz_target); return debug_readloop; } s = p_target->cmds->commands; /* FIXME: should get directory from a variable, e.g. TMPDIR */ if (psz_args && *psz_args) { if (strcmp (psz_args, "here") == 0) b_stdout = 1; else psz_filename = strdup(psz_args); } else { /* Create target from the basename of the target name. */ char *psz_target_basename = strrchr(psz_target, '/'); if (!psz_target_basename) psz_target_basename = (char *) psz_target; else psz_target_basename++; /* Skip delimiter */ psz_filename = CALLOC(char, strlen(psz_target_basename) + 10); snprintf(psz_filename, MAX_FILE_LENGTH, "/tmp/%s.sh", psz_target_basename); } /* Skip leading space, MAKE's command prefixes: echo suppression @, ignore-error -, and recursion + */ while (*s != '\0') { switch (*s) { case '@': case '+': case '-': ++s; break; default: if (!isblank ((unsigned char)*s)) goto found_begin; ++s; } } found_begin: if ( '\0' == *s ) { printf(_("Null command string parsed\n")); } else { dep_t *d; dep_t *ood = 0; if (b_stdout) outfd = stdout; else if (!(outfd = fopen (psz_filename, "w"))) { perror ("write target"); free(psz_filename); return debug_readloop; } if (p_v) { fprintf(outfd, "#!%s\n", variable_expand(p_v->value)); } if (!p_target->floc.filenm && p_target->cmds->fileinfo.filenm) { /* Fake the location based on the commands - it's better than nothing... */ fprintf(outfd, "## %s/%s:%lu\n", starting_directory, p_target->cmds->fileinfo.filenm, p_target->cmds->fileinfo.lineno-1); } else { fprintf(outfd, "## %s/%s:%lu\n", starting_directory, p_target->floc.filenm, p_target->floc.lineno); } /* FIXME: this code duplicaes some code in file.c: print_target_props. DRY. */ fprintf (outfd, "## %s:%s", p_target->name, p_target->double_colon ? ":" : ""); /* Print all normal dependencies; note any order-only deps. */ for (d = p_target->deps; d != 0; d = d->next) if (! d->ignore_mtime) { fprintf (outfd, " %s", dep_name (d)); } else if (! ood) ood = d; /* Print order-only deps, if we have any. */ if (ood) { fprintf (outfd, " | %s", dep_name (ood)); for (d = ood->next; d != 0; d = d->next) if (d->ignore_mtime) fprintf (outfd, " %s", dep_name (d)); } fprintf (outfd, "\n"); { char wd[300]; if (getcwd (wd, sizeof(wd))) { fprintf(outfd, "\n#cd %s\n", wd); } } initialize_file_variables (p_target, 0); set_file_variables (p_target); { #if 0 commands_t cmds; char **lines; unsigned int i; memcpy(&cmds, p_target->cmds, sizeof(cmds)); cmds.command_lines = NULL; chop_commands (&cmds); lines = xmalloc (cmds.ncommand_lines * sizeof (char *)); expand_command_lines(&cmds, lines, p_target); for (i = 0; i < cmds.ncommand_lines; ++i) { fprintf (outfd, "%s\n", lines[i]); free (lines[i]); } free (lines); #else char *line = allocated_variable_expand_for_file (s, p_target); fprintf (outfd, "%s\n", line); free(line); #endif } if (!b_stdout) { struct stat buf; if (0 == fstat(fileno(outfd), &buf)) { mode_t mode = buf.st_mode; if (buf.st_mode & S_IRUSR) mode |= S_IXUSR; if (buf.st_mode & S_IRGRP) mode |= S_IXGRP; if (buf.st_mode & S_IROTH) mode |= S_IXOTH; if (0 != fchmod(fileno(outfd), mode)) { printf(_("Can't set execute mode on \"%s\".\n"), psz_filename); } } fclose(outfd); printf(_("File \"%s\" written.\n"), psz_filename); free(psz_filename); } } } return debug_readloop; } static void dbg_cmd_write_init(unsigned int c) { short_command[c].func = &dbg_cmd_write; short_command[c].use = _("write [TARGET [FILENAME]]"); short_command[c].doc = _("writes the commands associated of a target to a file with MAKE\n" "variables expanded. If no target given, the basename of the current\n" "is used. If a filename is supplied it is used. If it is the string\n" "\"here\", we write the output to stdout. If no filename is\n" "given then create the filename by prepending a directory name to\n" "the target name and then append \".sh\"."); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/file2line.c000066400000000000000000000135331317072305000206010ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Create filename to line number table used by breakpoints */ #include "../make.h" #include #include "../filedef.h" #include "../file.h" #include "../read.h" #include "../rule.h" #include "./file2line.h" unsigned long file2lines_hash_1 (const void *key) { return_ISTRING_HASH_1 (((const lineno_array_t *) key)->hname); } unsigned long file2lines_hash_2 (const void *key) { return_ISTRING_HASH_2 (((const lineno_array_t *) key)->hname); } static int file2lines_hash_cmp (const void *x, const void *y) { return strcmp(((const lineno_array_t *) x)->hname, ((const lineno_array_t *) y)->hname); } lineno_array_t * lookup_file2lines (const char *psz_filename) { assert (*psz_filename != '\0'); return hash_find_item (&file2lines, &psz_filename); } /* FIXME return a status code when we fail. */ file_t * target_for_file_and_line (const char *psz_filename, unsigned int lineno, /*out*/ f2l_entry_t *entry_type) { lineno_array_t **pp_linenos; lineno_array_t lookup_linenos; assert (*psz_filename != '\0'); lookup_linenos.hname = psz_filename; if (0 == file2lines.ht_size) file2lines_init(); pp_linenos = (lineno_array_t **) hash_find_slot(&file2lines, &lookup_linenos); if (NULL == *pp_linenos) return NULL; if (lineno > (*pp_linenos)->size) return NULL; *entry_type = (*pp_linenos)->type[lineno]; return (*pp_linenos)->array[lineno]; } void enter_target_lineno (const char *psz_filename, unsigned int lineno, file_t *p_target) { lineno_array_t lookup_linenos; lineno_array_t **pp_linenos; file_t *p_file; lookup_linenos.hname = psz_filename; pp_linenos = (lineno_array_t **) hash_find_slot(&file2lines, &lookup_linenos); p_file = lookup_file(psz_filename); if (p_file == NULL) { printf("Could not find file %s\n", psz_filename); return; } if (p_file->nlines == 0) { printf("Warning: %s shows no lines\n", psz_filename); } if (HASH_VACANT(*pp_linenos)) { const unsigned int nlines = p_file->nlines+1; void **new_array = calloc (sizeof(void *), nlines); f2l_entry_t *new_type = calloc (sizeof(f2l_entry_t *), nlines); lineno_array_t *p_new_linenos = calloc (sizeof(lineno_array_t), 1); *pp_linenos = p_new_linenos; (*pp_linenos)->hname = psz_filename; (*pp_linenos)->type = new_type; (*pp_linenos)->array = new_array; (*pp_linenos)->size = nlines; } (*pp_linenos)->type[lineno] = F2L_TARGET; (*pp_linenos)->array[lineno] = p_target; } static void file2line_init (const void *item) { file_t *p_target = (file_t *) item; const gmk_floc *p_floc = &p_target->floc; if (p_floc && p_floc->filenm) { enter_target_lineno(p_floc->filenm, p_floc->lineno, p_target); } } static void enter_rule_lineno (rule_t *r) { lineno_array_t lookup_linenos; lineno_array_t **pp_linenos; const char *psz_filename = r->floc.filenm; const unsigned int lineno = r->floc.lineno; file_t *p_file; if (!psz_filename) return; lookup_linenos.hname = psz_filename; pp_linenos = (lineno_array_t **) hash_find_slot(&file2lines, &lookup_linenos); p_file = lookup_file(psz_filename); if (p_file == NULL) { printf("Could not find file %s\n", psz_filename); return; } if (p_file->nlines == 0) { printf("Warning: %s shows no lines\n", psz_filename); } if (HASH_VACANT(*pp_linenos)) { const unsigned int nlines = p_file->nlines+1; void **new_array = calloc (sizeof(void *), nlines); f2l_entry_t *new_type = calloc (sizeof(f2l_entry_t *), nlines); lineno_array_t *p_new_linenos = calloc (sizeof(lineno_array_t), 1); *pp_linenos = p_new_linenos; (*pp_linenos)->hname = psz_filename; (*pp_linenos)->type = new_type; (*pp_linenos)->array = new_array; (*pp_linenos)->size = nlines; } (*pp_linenos)->type[lineno] = F2L_PATTERN; (*pp_linenos)->array[lineno] = r; } /*! Initializes hash table file2lines. file2lines is used in breakpoints only. So we do this on demand. */ bool file2lines_init(void) { if (!read_makefiles) return false; hash_init (&file2lines, files.ht_size, file2lines_hash_1, file2lines_hash_2, file2lines_hash_cmp); hash_map (&files, file2line_init); { rule_t *r; for (r = pattern_rules; r != 0; r = r->next) { enter_rule_lineno(r); } } return true; } void file2lines_print_entry(const void *item) { const lineno_array_t *p_linenos = (lineno_array_t *) item; unsigned int i; file_t *p_target; printf("%s:\n", p_linenos->hname); for (i=0; isize; i++) { p_target = p_linenos->array[i]; if (p_target) { if (p_linenos->type[i] == F2L_TARGET) { printf("%8lu: %s\n", p_target->floc.lineno, p_target->name); } else { rule_t *p_rule = (rule_t *) p_target; printf("%8lu: %s (pattern)\n", p_rule->floc.lineno, p_rule->targets[0]); } } } } void file2lines_dump(void) { file2lines_init(); hash_map (&file2lines, file2lines_print_entry); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/file2line.h000066400000000000000000000032221317072305000206000ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef REMAKE_FILE2LINE #define REMAKE_FILE2LINE struct hash_table file2lines; typedef enum { F2L_TARGET, F2L_PATTERN } f2l_entry_t; typedef struct lineo_array_s { const char *hname; /**< Name stored in hash table */ unsigned int size; /**< Number of entries in array */ f2l_entry_t *type; /**< type[i] determines what object array[i] points to */ void **array; /**< target or implicit rule name or NULL. */ } lineno_array_t; /*! Initializes hash table file2lines. file2lines is used in breakpoints only. So we do this on demand. */ extern bool file2lines_init(void); extern file_t *target_for_file_and_line (const char *psz_filename, unsigned int lineno, /*out*/ f2l_entry_t *entry_type); extern void file2lines_dump(void); #endif /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/fns.c000066400000000000000000000305671317072305000175240ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008, 2010, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Helper routines for debugger command interface. */ #include "../rule.h" #include "../trace.h" #include "../commands.h" #include "../expand.h" #include "fns.h" #include "stack.h" #include "debug.h" #include "print.h" #include "msg.h" #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_LIBREADLINE # ifdef bcmp # undef bcmp # endif # ifdef bzero # undef bzero # endif # ifdef bcopy # undef bcopy # endif #include #endif gmk_floc *p_target_loc = NULL; char *psz_target_name = NULL; /*! We use the if when we fake a line number because a real one hasn't been recorded on the stack. */ gmk_floc fake_floc; /* From readline. ?? Should this be in configure? */ #ifndef whitespace #define whitespace(c) (((c) == ' ') || ((c) == '\t')) #endif brkpt_mask_t get_brkpt_option(const char *psz_break_type) { if (is_abbrev_of (psz_break_type, "all", 1)) { return BRK_ALL; } else if (is_abbrev_of (psz_break_type, "prerequisite", 3)) { return BRK_BEFORE_PREREQ; } else if (is_abbrev_of (psz_break_type, "run", 1)) { return BRK_AFTER_PREREQ; } else if (is_abbrev_of (psz_break_type, "end", 1)) { return BRK_AFTER_CMD; } else if (is_abbrev_of (psz_break_type, "temp", 1)) { return BRK_TEMP; } else { dbg_errmsg("Unknown breakpoint modifier %s", psz_break_type); return BRK_NONE; } } /*! Parse psz_arg for a signed integer. The value is returned in *pi_result. If warn is true, then we'll give a warning if no integer found. The return value is true if parsing succeeded in any event.. */ bool get_int(const char *psz_arg, int *pi_result, bool b_warn) { int i; char *endptr; if (!psz_arg || 0==strlen(psz_arg)) return 0; i = strtol(psz_arg, &endptr, 10); if (*endptr != '\0') { if (b_warn) dbg_errmsg("expecting %s to be an integer", psz_arg); return false; } *pi_result = i; return true; } bool get_uint(const char *psz_arg, unsigned int *result, bool b_warn) { unsigned int i; char *endptr; if (!psz_arg || 0==strlen(psz_arg)) return 0; i = strtol(psz_arg, &endptr, 10); if (*endptr != '\0') { if (b_warn) dbg_errmsg("expecting %s to be an integer", psz_arg); return false; } *result = i; return true; } /* Find the next "word" - skip leading blanks and the "word" is the largest non-blank characters after that. ppsz_str is modified to point after the portion returned and also the region initially pointed to by ppsz_str is modified so that word is zero-byte termintated. */ char * get_word(char **ppsz_str) { char *psz_word; /* Skip leading blanks. */ while (**ppsz_str && whitespace (**ppsz_str)) **ppsz_str += 1; /* Word starts here at first non blank character. */ psz_word = *ppsz_str; /* Find end of word - next whitespace. */ while (**ppsz_str && !whitespace (**ppsz_str)) (*ppsz_str)++; if (**ppsz_str) *((*ppsz_str)++) = '\0'; return psz_word; } /*! Return the current target from the stack or NULL if none set. */ const file_t * get_current_target(void) { if (p_stack && p_stack->p_target) return p_stack->p_target; else return NULL; } /*! Return the current target from the stack or NULL if none set. */ const gmk_floc * get_current_floc(void) { file_t *p_target = (file_t *) get_current_target(); gmk_floc *p_floc; p_floc = &p_target->floc; if (p_floc->filenm && p_floc->lineno != 0) return p_floc; else return NULL; } /*! Find the target in first word of psz_args or use $@ (the current stack) if none. We also allow $@ or @ explicitly as a target name to mean the current target on the stack. NULL is returned if a lookup of the target name was not found. ppsz_target is to the name looked up. */ file_t * get_target(char **ppsz_args, /*out*/ const char **ppsz_target) { if (!*ppsz_args || !**ppsz_args) { file_t *p_target = (file_t *) get_current_target(); /* Use current target */ if (p_target && p_target->name) { *ppsz_args = (char *) p_target->name; } else { printf(_("Default target not found here. You must supply one\n")); return NULL; } } *ppsz_target = get_word(ppsz_args); /* As a special case, we'll allow $@ or @ for the current target. */ if ( 0 == strcmp("$@", *ppsz_target) || 0 == strcmp("@", *ppsz_target) ) { if (p_stack && p_stack->p_target && p_stack->p_target->name) *ppsz_target = p_stack->p_target->name; else { printf(_("No current target found for $@ - supply a target name.\n")); return NULL; } } { file_t *p_target = lookup_file (*ppsz_target); if (!p_target) printf(_("Target \"%s\" doesn't appear to be a target name.\n"), *ppsz_target); return p_target; } } /*! Return true if psz_substr is an initial prefix (abbreviation) of psz_word. The empty string is not a valid abbreviation. */ bool is_abbrev_of(const char* psz_substr, const char* psz_word, unsigned int i_min) { if (strlen(psz_substr) < i_min) return false; else { const char *psz = strstr(psz_word, psz_substr); return (psz && psz == psz_word); } } /*! toggle var on or on or off depending on psz_onoff */ void on_off_toggle(const char *psz_onoff, int *var) { if (strcmp (psz_onoff, "on") == 0) *var = 1; else if (strcmp (psz_onoff, "off") == 0) *var = 0; else if (strcmp (psz_onoff, "toggle") == 0) *var = !*var; else printf(_("expecting \"on\", \"off\", or \"toggle\"; got \"%s\" \n"), psz_onoff); } /*! Print an interpretation of the debug level mask. */ void print_db_level(debug_level_mask_t e_debug_level) { if (e_debug_level & DB_BASIC) printf("Basic tracing (0x%x)\n", DB_BASIC); if (e_debug_level & DB_TRACE) printf("Tracing (0x%x)\n", DB_TRACE); if (e_debug_level & DB_VERBOSE) printf("Verbose Tracing (0x%x)\n", DB_VERBOSE); if (e_debug_level & DB_SHELL) printf("Tracing shell commands 0x%x\n", DB_SHELL); if (e_debug_level & DB_MAKEFILES) printf("Tracing Rebuilding Makefiles 0x%x\n", DB_MAKEFILES); if (e_debug_level & DB_UPDATE_GOAL) printf("Tracing Goal target updates 0x%x\n", DB_MAKEFILES); if (e_debug_level & DB_UPDATE_GOAL) printf("Tracing reading Makefiles 0x%x\n", DB_READ_MAKEFILES); if (e_debug_level & DB_CALL) printf("Tracing function call and returns 0x%x\n", DB_CALL); } static char *reason2str[] = { "->", "..", "<-", "||", "rd", "!!", "--", "++", ":o" }; /** Print where we are in the Makefile. */ void print_debugger_location(const file_t *p_target, debug_enter_reason_t reason, const floc_stack_node_t *p_stack_floc) { if (p_target_loc) { if (reason != DEBUG_NOT_GIVEN && reason != DEBUG_STACK_CHANGING) printf("%s ", reason2str[reason]); printf("("); if ( !p_target_loc->filenm && p_target_loc->lineno != 0 && p_target && p_target->name ) { /* We don't have file location info in the target floc, but we do have it as part of the name, so use that. This happens for example with we've stopped before reading a Makefile. */ if (p_target->cmds) { gmk_floc floc; memcpy(&floc, &(p_target->cmds->fileinfo.filenm), sizeof(gmk_floc)); /* HACK: is it okay to assume that the target is on the line before the first command? Or should we list the line that the command starts on - so we know we've faked the location? */ floc.lineno--; p_target_loc->filenm = floc.filenm; p_target_loc->lineno = floc.lineno; print_floc_prefix(&floc); printf (")\n"); } else if (p_target->phony) printf("%s: .PHONY target)\n", p_target->name); else printf("%s:0)\n", p_target->name); } else { print_floc_prefix(p_target_loc); printf (")\n"); } } else if (p_stack_floc && p_stack_floc->p_floc) { printf("\n("); print_floc_prefix(p_stack_floc->p_floc); printf (")\n"); } else if (p_stack_floc_top && p_stack_floc_top->p_floc) { printf("\n("); print_floc_prefix(p_stack_floc_top->p_floc); printf (")\n"); } /* Could/should generalize the below into a prompt string. */ switch (reason) { case DEBUG_BRKPT_BEFORE_PREREQ: case DEBUG_STEP_HIT: dbg_cmd_show_exp("$@: $+", true); break; case DEBUG_STACK_CHANGING: break; default: dbg_cmd_show_exp("$@", true); break; } } /** Strip whitespace from the start and end of STRING. Return a pointer into STRING. */ char * stripwhite (char *string) { char *s, *t; for (s = string; whitespace (*s); s++) ; if (*s == 0) return (s); t = s + strlen (s) - 1; while (t > s && whitespace (*t)) t--; *++t = '\0'; return s; } /* Show if i_bool is "on" or "off" */ char * var_to_on_off(int i_bool) { return i_bool ? "on" : "off"; } /*! See if psz_varname is $varname or $(varname) */ variable_t * try_without_dollar(const char *psz_varname) { printf("Can't find variable `%s'.\n", psz_varname); if (psz_varname && psz_varname[0] == '$') { const char *psz_nodollar = &(psz_varname[1]); char *psz_try = calloc(1, strlen(psz_varname)); if (psz_nodollar && 1 == sscanf(psz_nodollar, "(%s)", psz_try)) { /* Remove trailing ')' */ if ( ')' == psz_try[strlen(psz_try)-1] ) psz_try[strlen(psz_try)-1]='\0'; printf(_("Did you mean `%s'?\n"), psz_try); } else printf(_("Did you mean `%s'?\n"), psz_nodollar); free(psz_try); } else { printf("Adding variable `%s'.\n", psz_varname); return define_variable (psz_varname, strlen(psz_varname), "", o_debugger, 0); } return NULL; } /*! Show a expression. Set "expand" to 1 if you want variable definitions inside the displayed value expanded. */ bool dbg_cmd_show_exp (char *psz_varname, bool expand) { if (!psz_varname || 0==strlen(psz_varname)) { printf(_("You need to supply a variable name.\n")); return false; } else { variable_t *p_v; variable_set_t *p_set = NULL; variable_set_list_t *p_file_vars = NULL; if (p_stack && p_stack->p_target && p_stack->p_target->name) { const char *psz_target = p_stack->p_target->name; file_t *p_target = lookup_file (psz_target); if (p_target) { initialize_file_variables (p_target, 0); set_file_variables (p_target); p_file_vars = p_target->variables; p_set = p_file_vars->set; } } if (p_set) { p_v = lookup_variable_in_set(psz_varname, strlen(psz_varname), p_set); if (!p_v) /* May be a global variable. */ p_v = lookup_variable (psz_varname, strlen (psz_varname)); } else { p_v = lookup_variable (psz_varname, strlen (psz_varname)); } if (p_v) { if (expand) { print_variable_expand(p_v); } else print_variable(p_v); } else { if (expand) printf("%s\n", variable_expand_set(psz_varname, p_file_vars)); else { try_without_dollar(psz_varname); return false; } } } return true; } void dbg_print_invocation(void) { unsigned int i; printf("%s ", global_argv[0]); for (i = 1; global_argv[i]; i++) { printf(" %s", global_argv[i]); } printf("\n"); } rule_t *find_rule (const char *psz_name) { rule_t *r; for (r = pattern_rules; r != 0; r = r->next) { unsigned int i; for (i = 0; r->targets[i] != 0; ++i) if (0 == strcmp(r->targets[i], psz_name)) return r; } return NULL; } void chomp(char * line) { unsigned int len = strlen(line); if (line[len-1] == '\n') line[len-1] = '\0'; } void shell_rc_status(int rc) { if (rc == -1) printf(_("Error: %s\n"), strerror(errno)); else if (WEXITSTATUS(rc) != 0) printf(_("Warning: return code was %d\n"), WEXITSTATUS(rc)); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/debugger/fns.h000066400000000000000000000076021317072305000175230ustar00rootroot00000000000000/* Copyright (C) 2005, 2008, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file dbg_fns.h * * \brief debugger helper functions. */ #ifndef DBG_FNS_H #define DBG_FNS_H #include "debug.h" #include "filedef.h" #include "trace.h" #include "rule.h" extern gmk_floc *p_target_loc; extern char *psz_target_name; /*! We use the if when we fake a line number because a real one hasn't been recorded on the stack. */ extern gmk_floc fake_floc; brkpt_mask_t get_brkpt_option(const char *psz_break_type); const gmk_floc *get_current_floc(void); /*! Return the current target from the stack or NULL if none set. */ const file_t * get_current_target(void); /*! Parse psz_arg for a signed integer. The value is returned in *pi_result. If warn is true, then we'll give a warning if no integer found. The return value is true if parsing succeeded in any event.. */ extern bool get_int(const char *psz_arg, /*out*/ int *pi_result, bool b_warn); /*! Parse psz_arg for a unsigned integer. The value is returned in *pi_result. The retun value is true if parsing succeeded. */ extern bool get_uint(const char *psz_arg, /*out*/ unsigned int *pi_result, bool b_warn); /*! Find the next "word" - skip leading blanks and the "word" is the largest non-blank characters after that. ppsz_str is modified to point after the portion returned and also the region initially pointed to by ppsz_str is modified so that word is zero-byte termintated. */ extern char *get_word(char **ppsz_str); /*! Find the target in first word of psz_args or use $@ (the current stack) if none. We also allow $@ or @ explicitly as a target name to mean the current target on the stack. NULL is returned if a lookup of the target name was not found. ppsz_target is to the name looked up. */ file_t * get_target(/*in/out*/ char **ppsz_args, /*out*/ const char **ppsz_target); /*! Return true if psz_substr is an initial prefix (abbreviation) of psz_word. The empty string is not a valid abbreviation. */ extern bool is_abbrev_of(const char *psz_substr, const char *psz_word, unsigned int i_min); /*! toggle var on or on or off depending on psz_onoff */ extern void on_off_toggle(const char *psz_onoff, int *var) ; /** Print where we are in the Makefile. */ extern void print_debugger_location(const file_t *p_target, debug_enter_reason_t reason, const floc_stack_node_t *p_stack_floc); /** Strip whitespace from the start and end of STRING. Return a pointer into STRING. */ extern char *stripwhite (char *string); /*! Show if i_bool is "on" or "off" */ extern char *var_to_on_off(int i_bool); /*! Show a expression. Set "expand" to 1 if you want variable definitions inside the displayed value expanded. */ extern bool dbg_cmd_show_exp(char *psz_arg, bool expand); /*! Print an interpretation of the debug level mask. */ extern void print_db_level(debug_level_mask_t e_debug_level); /*! See if psz_varname is $varname or $(varname) */ extern variable_t *try_without_dollar(const char *psz_varname); extern void dbg_print_invocation(void); extern rule_t *find_rule (const char *psz_name); extern void shell_rc_status(int rc); extern void chomp(char * line); #endif /* DBG_FNS_H*/ remake-4.1+dbg1.3~dfsg.1/debugger/info.h000066400000000000000000000020571317072305000176670ustar00rootroot00000000000000/* $Id: dbg_info.h,v 1.11 2006/03/19 12:17:44 rockyb Exp $ Copyright (C) 2008 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file dbg_info.h * * \brief debugger info headers */ #ifndef DBG_INFO_H #define DBG_INFO_H #include "cmd.h" #include "trace.h" extern debug_enter_reason_t last_stop_reason; extern const char *WARRANTY; #endif /* DBG_INFO_H*/ remake-4.1+dbg1.3~dfsg.1/debugger/msg.c000066400000000000000000000042641317072305000175170ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Debugger messages */ #include "msg.h" #if HAVE_VPRINTF || HAVE_DOPRNT # define HAVE_STDVARARGS 1 # if __STDC__ # include # define VA_START(args, lastarg) va_start(args, lastarg) # else # include # define VA_START(args, lastarg) va_start(args) # endif # if HAVE_VPRINTF # define VA_PRINTF(fp, lastarg, args) vfprintf((fp), (lastarg), (args)) # else # define VA_PRINTF(fp, lastarg, args) _doprnt((lastarg), (args), (fp)) # endif # define VA_END(args) va_end(args) #else /* # undef HAVE_STDVARARGS */ # define va_alist a1, a2, a3, a4, a5, a6, a7, a8 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; # define VA_START(args, lastarg) # define VA_PRINTF(fp, lastarg, args) fprintf((fp), (lastarg), va_alist) # define VA_END(args) #endif /* Print an error message on stdout. */ void #if __STDC__ && HAVE_STDVARARGS dbg_errmsg(const char *fmt, ...) #else dbg_errmsg (const char *fmt, va_alist) #endif { #if HAVE_STDVARARGS va_list args; #endif fprintf(stdout, "** "); VA_START (args, fmt); VA_PRINTF (stdout, fmt, args); VA_END (args); fprintf (stdout, "\n"); fflush (stdout); } /* Print a message on stdout. */ void #if __STDC__ && HAVE_STDVARARGS dbg_msg(const char *fmt, ...) #else dbg_msg (const char *fmt, va_alist) #endif { #if HAVE_STDVARARGS va_list args; #endif VA_START (args, fmt); VA_PRINTF (stdout, fmt, args); VA_END (args); fprintf (stdout, "\n"); fflush (stdout); } remake-4.1+dbg1.3~dfsg.1/debugger/msg.h000066400000000000000000000006361317072305000175230ustar00rootroot00000000000000/*! Versions of error and fatal with the ability to show call-stack. */ #ifndef REMAKE_DBG_MSG_H #define REMAKE_DBG_MSG_H #include "../make.h" #if defined __STDC__ && __STDC__ void dbg_msg (const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); void dbg_errmsg (const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); #else void dbg_msg(); void dbg_errmsg(); #endif #endif remake-4.1+dbg1.3~dfsg.1/debugger/stack.c000066400000000000000000000060461317072305000200360ustar00rootroot00000000000000/* Copyright (C) 2005, 2008, 2009, 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* debugger command interface. */ #include "fns.h" #include "msg.h" #include "print.h" #include "stack.h" #include "commands.h" int i_stack_pos = 0; /** Pointer to current target call stack at the place we are currently focused on. */ target_stack_node_t *p_stack = NULL; floc_stack_node_t *p_floc_stack = NULL; unsigned int dbg_stack_size() { int i=0; if (p_stack_top) { for ( p_stack=p_stack_top; p_stack ; p_stack = p_stack->p_parent ) { i++; } return i; } else if (p_stack_floc_top) { /* We have a Makefile stack */ for ( p_floc_stack=p_stack_floc_top; p_floc_stack ; p_floc_stack = p_floc_stack->p_parent ) { i++; } } return i; } debug_return_t dbg_adjust_frame(int i_amount, int b_absolute) { int i=0; int i_try_frame_pos; if (b_absolute) { if (i_amount < 0) i_try_frame_pos = dbg_stack_size() + i_amount; else i_try_frame_pos = i_amount; } else i_try_frame_pos = i_stack_pos + i_amount; if (i_try_frame_pos < 0) { dbg_errmsg(_("Moving target would go beyond bottom-most target position.")); return debug_cmd_error; } i = i_try_frame_pos + 1; if (p_stack_top) { for ( p_stack=p_stack_top; p_stack ; p_stack = p_stack->p_parent ) { i--; if (0 == i) break; } if (0 != i) { dbg_errmsg(_("Can't set frame to position %d; " "%d is the highest target position."), i_try_frame_pos, i_try_frame_pos - i); return debug_cmd_error; } i_stack_pos = i_try_frame_pos; p_target_loc = &(p_stack->p_target->floc); print_target_stack_entry(p_stack->p_target, i_stack_pos, i_stack_pos); print_debugger_location(p_stack->p_target, DEBUG_STACK_CHANGING, NULL); } else if (p_stack_floc_top) { /* We have a Makefile stack */ for ( p_floc_stack=p_stack_floc_top; p_floc_stack ; p_floc_stack = p_floc_stack->p_parent ) { i--; if (0 == i) break; } if (0 != i) { dbg_errmsg(_("Can't set frame to position %d; " "%d is the highest target position."), i_try_frame_pos, i_try_frame_pos - i); return debug_cmd_error; } i_stack_pos = i_try_frame_pos; print_debugger_location(NULL, DEBUG_NOT_GIVEN, p_floc_stack); } return debug_readloop; } remake-4.1+dbg1.3~dfsg.1/debugger/stack.h000066400000000000000000000022711317072305000200370ustar00rootroot00000000000000/* Copyright (C) 2005, 2011 R. Bernstein rocky@gnu.org This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file dbg_stack.h * * \brief debugger command stack routines. */ #ifndef DBG_STACK_H #define DBG_STACK_H #include "trace.h" extern int i_stack_pos; /** Pointer to current target call stack at the place we are currently focused on. */ extern target_stack_node_t *p_stack; extern floc_stack_node_t *p_floc_stack; extern debug_return_t dbg_adjust_frame(int i_amount, int b_absolute); #endif /* DBG_STACK_H */ remake-4.1+dbg1.3~dfsg.1/debugger/subcmd.h000066400000000000000000000015351317072305000202110ustar00rootroot00000000000000#ifndef REMAKE_DBG_SUBCMD_H #define REMAKE_DBG_SUBCMD_H typedef struct { const char *name; /* name of subcommand command. */ const char *short_doc; /* short description of subcommand */ const char *doc; /* full description of subcommand */ int *var; /* address of variable setting. NULL if no setting. */ bool b_onoff; /* True if on/off variable, false if int. FIXME: generalize into enumeration. */ unsigned int min_abbrev; /* Fewest number of characters needed to match name. */ } subcommand_var_info_t; extern void dbg_help_subcmd_entry(const char *psz_subcmd_name, const char *psz_fmt, subcommand_var_info_t *p_subcmd, bool full_info); #endif /* DBG_CMD_H*/ /* * Local variables: * c-file-style: "gnu" * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/default.c000066400000000000000000000434741317072305000165770ustar00rootroot00000000000000/* Data base of default implicit rules for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include "filedef.h" #include "variable.h" #include "rule.h" #include "dep.h" #include "job.h" #include "commands.h" /* Define GCC_IS_NATIVE if gcc is the native development environment on your system (gcc/bison/flex vs cc/yacc/lex). */ #if defined(__MSDOS__) || defined(__EMX__) # define GCC_IS_NATIVE #endif /* This is the default list of suffixes for suffix rules. '.s' must come last, so that a '.o' file will be made from a '.c' or '.p' or ... file rather than from a .s file. */ static char default_suffixes[] #ifdef VMS /* VMS should include all UNIX/POSIX + some VMS extensions */ = ".out .exe .a .olb .hlb .tlb .mlb .ln .o .obj .c .cxx .cc .cpp .pas .p \ .for .f .r .y .l .ym .yl .mar .s .ss .i .ii .mod .sym .def .h .info .dvi \ .tex .texinfo .texi .txinfo .mem .hlp .brn .rnh .rno .rnt .rnx .w .ch .cweb \ .web .com .sh .elc .el"; #elif defined(__EMX__) = ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \ .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ .w .ch .web .sh .elc .el .obj .exe .dll .lib"; #else = ".out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S \ .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ .w .ch .web .sh .elc .el"; #endif static struct pspec default_pattern_rules[] = { #ifdef VMS { "(%)", "%", "@if f$$search(\"$@\") .eqs. \"\" then $(LIBRARY)/CREATE/" "$(or " "$(patsubst %,TEXT,$(filter %.tlb %.TLB,$@))," "$(patsubst %,HELP,$(filter %.hlb %.HLB,$@))," "$(patsubst %,MACRO,$(filter %.mlb %.MLB,$@))," "$(and " "$(patsubst %,SHARE,$(filter %.olb %.OLB,$@))," "$(patsubst %,SHARE,$(filter %.exe %.EXE,$<)))," "OBJECT)" " $@\n" "$(AR) $(ARFLAGS) $@ $<" }, #else { "(%)", "%", "$(AR) $(ARFLAGS) $@ $<" }, #endif /* The X.out rules are only in BSD's default set because BSD Make has no null-suffix rules, so 'foo.out' and 'foo' are the same thing. */ #ifdef VMS { "%.exe", "%", "$(CP) $< $@" }, #endif { "%.out", "%", "@rm -f $@ \n cp $< $@" }, /* Syntax is "ctangle foo.w foo.ch foo.c". */ { "%.c", "%.w %.ch", "$(CTANGLE) $^ $@" }, { "%.tex", "%.w %.ch", "$(CWEAVE) $^ $@" }, { 0, 0, 0 } }; static struct pspec default_terminal_rules[] = { #ifdef VMS /* RCS. */ { "%", "%$$5lv", /* Multinet style */ "if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" }, { "%", "[.$$rcs]%$$5lv", /* Multinet style */ "if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" }, { "%", "%_v", /* Normal style */ "if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" }, { "%", "[.rcs]%_v", /* Normal style */ "if f$$search(\"$@\") .nes. \"\" then +$(CHECKOUT,v)" }, /* SCCS. */ /* ain't no SCCS on vms */ #else /* RCS. */ { "%", "%,v", "$(CHECKOUT,v)" }, { "%", "RCS/%,v", "$(CHECKOUT,v)" }, { "%", "RCS/%", "$(CHECKOUT,v)" }, /* SCCS. */ { "%", "s.%", "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" }, { "%", "SCCS/s.%", "$(GET) $(GFLAGS) $(SCCS_OUTPUT_OPTION) $<" }, #endif /* !VMS */ { 0, 0, 0 } }; static const char *default_suffix_rules[] = { #ifdef VMS ".obj.exe", "$(LINK.obj) $^ $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".mar.exe", "$(COMPILE.mar) $^ \n $(LINK.obj) $(subst .mar,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".s.exe", "$(COMPILE.s) $^ \n $(LINK.obj) $(subst .s,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".c.exe", "$(COMPILE.c) $^ \n $(LINK.obj) $(subst .c,.obj,$^) $(LOADLIBES) $(LDLIBS) $(CRT0) /exe=$@", ".cc.exe", #ifdef GCC_IS_NATIVE "$(COMPILE.cc) $^ \n $(LINK.obj) $(CXXSTARTUP),sys$$disk:[]$(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", #else "$(COMPILE.cc) $^ \n $(CXXLINK.obj) $(subst .cc,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", ".cxx.exe", "$(COMPILE.cxx) $^ \n $(CXXLINK.obj) $(subst .cxx,.obj,$^) $(LOADLIBES) $(LXLIBS) $(LDLIBS) $(CXXRT0) /exe=$@", #endif ".for.exe", "$(COMPILE.for) $^ \n $(LINK.obj) $(subst .for,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@", ".pas.exe", "$(COMPILE.pas) $^ \n $(LINK.obj) $(subst .pas,.obj,$^) $(LOADLIBES) $(LDLIBS) /exe=$@", ".com", "copy $< >$@", ".mar.obj", "$(COMPILE.mar) /obj=$@ $<", ".s.obj", "$(COMPILE.s) /obj=$@ $<", ".ss.obj", "$(COMPILE.s) /obj=$@ $<", ".c.i", "$(COMPILE.c)/prep /list=$@ $<", ".c.s", "$(COMPILE.c)/noobj/machine /list=$@ $<", ".i.s", "$(COMPILE.c)/noprep/noobj/machine /list=$@ $<", ".c.obj", "$(COMPILE.c) /obj=$@ $<", ".c.o", "$(COMPILE.c) /obj=$@ $<", ".cc.ii", "$(COMPILE.cc)/prep /list=$@ $<", ".cc.ss", "$(COMPILE.cc)/noobj/machine /list=$@ $<", ".ii.ss", "$(COMPILE.cc)/noprep/noobj/machine /list=$@ $<", ".cc.obj", "$(COMPILE.cc) /obj=$@ $<", ".cc.o", "$(COMPILE.cc) /obj=$@ $<", ".cxx.obj", "$(COMPILE.cxx) /obj=$@ $<", ".cxx.o", "$(COMPILE.cxx) /obj=$@ $<", ".for.obj", "$(COMPILE.for) /obj=$@ $<", ".for.o", "$(COMPILE.for) /obj=$@ $<", ".pas.obj", "$(COMPILE.pas) /obj=$@ $<", ".pas.o", "$(COMPILE.pas) /obj=$@ $<", ".y.c", "$(YACC.y) $< \n rename y_tab.c $@", ".l.c", "$(LEX.l) $< \n rename lexyy.c $@", ".texinfo.info", "$(MAKEINFO) $<", ".tex.dvi", "$(TEX) $<", #else /* ! VMS */ ".o", "$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".s", "$(LINK.s) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".S", "$(LINK.S) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".c", "$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".cc", "$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".C", "$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".cpp", "$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".f", "$(LINK.f) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".m", "$(LINK.m) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".p", "$(LINK.p) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".F", "$(LINK.F) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".r", "$(LINK.r) $^ $(LOADLIBES) $(LDLIBS) -o $@", ".mod", "$(COMPILE.mod) -o $@ -e $@ $^", ".def.sym", "$(COMPILE.def) -o $@ $<", ".sh", "cat $< >$@ \n chmod a+x $@", ".s.o", "$(COMPILE.s) -o $@ $<", ".S.o", "$(COMPILE.S) -o $@ $<", ".c.o", "$(COMPILE.c) $(OUTPUT_OPTION) $<", ".cc.o", "$(COMPILE.cc) $(OUTPUT_OPTION) $<", ".C.o", "$(COMPILE.C) $(OUTPUT_OPTION) $<", ".cpp.o", "$(COMPILE.cpp) $(OUTPUT_OPTION) $<", ".f.o", "$(COMPILE.f) $(OUTPUT_OPTION) $<", ".m.o", "$(COMPILE.m) $(OUTPUT_OPTION) $<", ".p.o", "$(COMPILE.p) $(OUTPUT_OPTION) $<", ".F.o", "$(COMPILE.F) $(OUTPUT_OPTION) $<", ".r.o", "$(COMPILE.r) $(OUTPUT_OPTION) $<", ".mod.o", "$(COMPILE.mod) -o $@ $<", ".c.ln", "$(LINT.c) -C$* $<", ".y.ln", #ifndef __MSDOS__ "$(YACC.y) $< \n $(LINT.c) -C$* y.tab.c \n $(RM) y.tab.c", #else "$(YACC.y) $< \n $(LINT.c) -C$* y_tab.c \n $(RM) y_tab.c", #endif ".l.ln", "@$(RM) $*.c\n $(LEX.l) $< > $*.c\n$(LINT.c) -i $*.c -o $@\n $(RM) $*.c", ".y.c", #ifndef __MSDOS__ "$(YACC.y) $< \n mv -f y.tab.c $@", #else "$(YACC.y) $< \n mv -f y_tab.c $@", #endif ".l.c", "@$(RM) $@ \n $(LEX.l) $< > $@", ".ym.m", "$(YACC.m) $< \n mv -f y.tab.c $@", ".lm.m", "@$(RM) $@ \n $(LEX.m) $< > $@", ".F.f", "$(PREPROCESS.F) $(OUTPUT_OPTION) $<", ".r.f", "$(PREPROCESS.r) $(OUTPUT_OPTION) $<", /* This might actually make lex.yy.c if there's no %R% directive in $*.l, but in that case why were you trying to make $*.r anyway? */ ".l.r", "$(LEX.l) $< > $@ \n mv -f lex.yy.r $@", ".S.s", "$(PREPROCESS.S) $< > $@", ".texinfo.info", "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@", ".texi.info", "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@", ".txinfo.info", "$(MAKEINFO) $(MAKEINFO_FLAGS) $< -o $@", ".tex.dvi", "$(TEX) $<", ".texinfo.dvi", "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<", ".texi.dvi", "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<", ".txinfo.dvi", "$(TEXI2DVI) $(TEXI2DVI_FLAGS) $<", ".w.c", "$(CTANGLE) $< - $@", /* The '-' says there is no '.ch' file. */ ".web.p", "$(TANGLE) $<", ".w.tex", "$(CWEAVE) $< - $@", /* The '-' says there is no '.ch' file. */ ".web.tex", "$(WEAVE) $<", #endif /* !VMS */ 0, 0, }; static const char *default_variables[] = { #ifdef VMS #ifdef __ALPHA "ARCH", "ALPHA", #endif #ifdef __ia64 "ARCH", "IA64", #endif #ifdef __VAX "ARCH", "VAX", #endif "AR", "library", "LIBRARY", "library", "ARFLAGS", "/replace", "AS", "macro", "MACRO", "macro", #ifdef GCC_IS_NATIVE "CC", "gcc", #else "CC", "cc", #endif "CD", "builtin_cd", "ECHO", "builtin_echo", #ifdef GCC_IS_NATIVE "C++", "gcc/plus", "CXX", "gcc/plus", #else "C++", "cxx", "CXX", "cxx", #ifndef __ia64 "CXXLD", "cxxlink", "CXXLINK", "cxxlink", #else /* CXXLINK is not used on VMS/IA64 */ "CXXLD", "link", "CXXLINK", "link", #endif #endif "CO", "co", "CPP", "$(CC) /preprocess_only", "FC", "fortran", /* System V uses these, so explicit rules using them should work. However, there is no way to make implicit rules use them and FC. */ "F77", "$(FC)", "F77FLAGS", "$(FFLAGS)", "LD", "link", "LEX", "lex", "PC", "pascal", "YACC", "bison/yacc", "YFLAGS", "/Define/Verbose", "BISON", "bison", "MAKEINFO", "makeinfo", "TEX", "tex", "TEXINDEX", "texindex", "RM", "delete/nolog", "CSTARTUP", "", #ifdef GCC_IS_NATIVE "CRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crt0.obj", "CXXSTARTUP", "gnu_cc_library:crtbegin.obj", "CXXRT0", ",sys$$library:vaxcrtl.olb/lib,gnu_cc_library:crtend.obj,gnu_cc_library:gxx_main.obj", "LXLIBS", ",gnu_cc_library:libstdcxx.olb/lib,gnu_cc_library:libgccplus.olb/lib", "LDLIBS", ",gnu_cc_library:libgcc.olb/lib", #else "CRT0", "", "CXXSTARTUP", "", "CXXRT0", "", "LXLIBS", "", "LDLIBS", "", #endif "LINK.obj", "$(LD) $(LDFLAGS)", #ifndef GCC_IS_NATIVE "CXXLINK.obj", "$(CXXLD) $(LDFLAGS)", "COMPILE.cxx", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", #endif "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "YACC.y", "$(YACC) $(YFLAGS)", "LEX.l", "$(LEX) $(LFLAGS)", "COMPILE.for", "$(FC) $(FFLAGS) $(TARGET_ARCH)", "COMPILE.pas", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "COMPILE.mar", "$(MACRO) $(MACROFLAGS)", "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)", "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", "MV", "rename/new_version", "CP", "copy", ".LIBPATTERNS", "%.olb lib%.a", #else /* !VMS */ "AR", "ar", "ARFLAGS", "rv", "AS", "as", #ifdef GCC_IS_NATIVE "CC", "gcc", # ifdef __MSDOS__ "CXX", "gpp", /* g++ is an invalid name on MSDOS */ # else "CXX", "gcc", # endif /* __MSDOS__ */ "OBJC", "gcc", #else "CC", "cc", "CXX", "g++", "OBJC", "cc", #endif /* This expands to $(CO) $(COFLAGS) $< $@ if $@ does not exist, and to the empty string if $@ does exist. */ "CHECKOUT,v", "+$(if $(wildcard $@),,$(CO) $(COFLAGS) $< $@)", "CO", "co", "COFLAGS", "", "CPP", "$(CC) -E", #ifdef CRAY "CF77PPFLAGS", "-P", "CF77PP", "/lib/cpp", "CFT", "cft77", "CF", "cf77", "FC", "$(CF)", #else /* Not CRAY. */ #ifdef _IBMR2 "FC", "xlf", #else #ifdef __convex__ "FC", "fc", #else "FC", "f77", #endif /* __convex__ */ #endif /* _IBMR2 */ /* System V uses these, so explicit rules using them should work. However, there is no way to make implicit rules use them and FC. */ "F77", "$(FC)", "F77FLAGS", "$(FFLAGS)", #endif /* Cray. */ "GET", SCCS_GET, "LD", "ld", #ifdef GCC_IS_NATIVE "LEX", "flex", #else "LEX", "lex", #endif "LINT", "lint", "M2C", "m2c", #ifdef pyr "PC", "pascal", #else #ifdef CRAY "PC", "PASCAL", "SEGLDR", "segldr", #else "PC", "pc", #endif /* CRAY. */ #endif /* pyr. */ #ifdef GCC_IS_NATIVE "YACC", "bison -y", #else "YACC", "yacc", /* Or "bison -y" */ #endif "MAKEINFO", "makeinfo", "TEX", "tex", "TEXI2DVI", "texi2dvi", "WEAVE", "weave", "CWEAVE", "cweave", "TANGLE", "tangle", "CTANGLE", "ctangle", "RM", "rm -f", "LINK.o", "$(CC) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", "LINK.c", "$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", "LINK.m", "$(OBJC) $(OBJCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", "COMPILE.C", "$(COMPILE.cc)", "COMPILE.cpp", "$(COMPILE.cc)", "LINK.cc", "$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "LINK.C", "$(LINK.cc)", "LINK.cpp", "$(LINK.cc)", "YACC.y", "$(YACC) $(YFLAGS)", "LEX.l", "$(LEX) $(LFLAGS) -t", "YACC.m", "$(YACC) $(YFLAGS)", "LEX.m", "$(LEX) $(LFLAGS) -t", "COMPILE.f", "$(FC) $(FFLAGS) $(TARGET_ARCH) -c", "LINK.f", "$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", "LINK.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c", "LINK.r", "$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "COMPILE.def", "$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH)", "COMPILE.mod", "$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH)", "COMPILE.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c", "LINK.p", "$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)", "LINK.s", "$(CC) $(ASFLAGS) $(LDFLAGS) $(TARGET_MACH)", "COMPILE.s", "$(AS) $(ASFLAGS) $(TARGET_MACH)", "LINK.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_MACH)", "COMPILE.S", "$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_MACH) -c", "PREPROCESS.S", "$(CC) -E $(CPPFLAGS)", "PREPROCESS.F", "$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -F", "PREPROCESS.r", "$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -F", "LINT.c", "$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH)", #ifndef NO_MINUS_C_MINUS_O "OUTPUT_OPTION", "-o $@", #endif #ifdef SCCS_GET_MINUS_G "SCCS_OUTPUT_OPTION", "-G$@", #endif #if defined(_AMIGA) ".LIBPATTERNS", "%.lib", #elif defined(__MSDOS__) ".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a", #elif defined(__APPLE__) ".LIBPATTERNS", "lib%.dylib lib%.a", #elif defined(__CYGWIN__) || defined(WINDOWS32) ".LIBPATTERNS", "lib%.dll.a %.dll.a lib%.a %.lib lib%.dll %.dll", #else ".LIBPATTERNS", "lib%.so lib%.a", #endif #endif /* !VMS */ /* Make this assignment to avoid undefined variable warnings. */ "GNUMAKEFLAGS", "", 0, 0 }; /* Set up the default .SUFFIXES list. */ void set_default_suffixes (void) { suffix_file = enter_file (strcache_add (".SUFFIXES")); suffix_file->builtin = 1; if (no_builtin_rules_flag) define_variable_cname ("SUFFIXES", "", o_default, 0); else { struct dep *d; const char *p = default_suffixes; suffix_file->deps = enter_prereqs (PARSE_SIMPLE_SEQ ((char **)&p, struct dep), NULL); for (d = suffix_file->deps; d; d = d->next) d->file->builtin = 1; define_variable_cname ("SUFFIXES", default_suffixes, o_default, 0); } } /* Enter the default suffix rules as file rules. This used to be done in install_default_implicit_rules, but that loses because we want the suffix rules installed before reading makefiles, and the pattern rules installed after. */ void install_default_suffix_rules (void) { const char **s; if (no_builtin_rules_flag) return; for (s = default_suffix_rules; *s != 0; s += 2) { struct file *f = enter_file (strcache_add (s[0])); /* This function should run before any makefile is parsed. */ assert (f->cmds == 0); f->cmds = xmalloc (sizeof (struct commands)); f->cmds->fileinfo.filenm = 0; f->cmds->commands = xstrdup (s[1]); f->cmds->command_lines = 0; f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT; f->builtin = 1; } } /* Install the default pattern rules. */ void install_default_implicit_rules (void) { struct pspec *p; if (no_builtin_rules_flag) return; for (p = default_pattern_rules; p->target != 0; ++p) install_pattern_rule (p, 0); for (p = default_terminal_rules; p->target != 0; ++p) install_pattern_rule (p, 1); } void define_default_variables (void) { const char **s; if (no_builtin_variables_flag) return; for (s = default_variables; *s != 0; s += 2) define_variable (s[0], strlen (s[0]), s[1], o_default, 1); } void undefine_default_variables (void) { const char **s; for (s = default_variables; *s != 0; s += 2) undefine_variable_global (s[0], strlen (s[0]), o_default); } remake-4.1+dbg1.3~dfsg.1/dep.h000066400000000000000000000065161317072305000157240ustar00rootroot00000000000000/* Definitions of dependency data structures for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* Flag bits for the second argument to 'read_makefile'. These flags are saved in the 'changed' field of each 'struct dep' in the chain returned by 'read_all_makefiles'. */ #ifndef REMAKE_DEP_H #define REMAKE_DEP_H #include "gnumake.h" #define RM_NO_DEFAULT_GOAL (1 << 0) /* Do not set default goal. */ #define RM_INCLUDED (1 << 1) /* Search makefile search path. */ #define RM_DONTCARE (1 << 2) /* No error if it doesn't exist. */ #define RM_NO_TILDE (1 << 3) /* Don't expand ~ in file name. */ #define RM_NOFLAG 0 /* Structure representing one dependency of a file. Each struct file's 'deps' points to a chain of these, chained through the 'next'. 'stem' is the stem for this dep line of static pattern rule or NULL. Note that the first two words of this match a struct nameseq. */ struct dep { struct dep *next; const char *name; const char *stem; struct file *file; unsigned int changed : 8; unsigned int ignore_mtime : 1; unsigned int staticpattern : 1; unsigned int need_2nd_expansion : 1; unsigned int dontcare : 1; }; /* Structure used in chains of names, for parsing and globbing. */ struct nameseq { struct nameseq *next; const char *name; }; #define PARSEFS_NONE 0x0000 #define PARSEFS_NOSTRIP 0x0001 #define PARSEFS_NOAR 0x0002 #define PARSEFS_NOGLOB 0x0004 #define PARSEFS_EXISTS 0x0008 #define PARSEFS_NOCACHE 0x0010 #define PARSE_FILE_SEQ(_s,_t,_c,_p,_f) \ (_t *)parse_file_seq ((_s),sizeof (_t),(_c),(_p),(_f)) #define PARSE_SIMPLE_SEQ(_s,_t) \ (_t *)parse_file_seq ((_s),sizeof (_t),MAP_NUL,NULL,PARSEFS_NONE) #ifdef VMS void *parse_file_seq (); #else void *parse_file_seq (char **stringp, unsigned int size, int stopmap, const char *prefix, int flags); #endif char *remake_tilde_expand (const char *name); #ifndef NO_ARCHIVES struct nameseq *ar_glob (const char *arname, const char *member_pattern, unsigned int size); #endif #define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name) #define alloc_dep() (xcalloc (sizeof (struct dep))) #define free_ns(_n) free (_n) #define free_dep(_d) free_ns (_d) struct dep *copy_dep_chain (const struct dep *d); void free_dep_chain (struct dep *d); void free_ns_chain (struct nameseq *n); struct dep *read_all_makefiles (const char **makefiles); /*! The chain of makefiles read by read_makefile. */ struct dep *read_makefiles; void eval_buffer (char *buffer, const gmk_floc *floc); enum update_status update_goal_chain (struct dep *goals); #endif /*REMAKE_DEP_H*/ remake-4.1+dbg1.3~dfsg.1/dir.c000066400000000000000000001007641317072305000157250ustar00rootroot00000000000000/* Directory hashing for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "hash.h" #include "filedef.h" #include "dep.h" #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN # undef NAMLEN # define NAMLEN(d) _D_NAMLEN(d) #endif #if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__) /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 # define FAKE_DIR_ENTRY(dp) #else # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) # define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1) #endif /* POSIX */ #ifdef __MSDOS__ #include #include /* If it's MSDOS that doesn't have _USE_LFN, disable LFN support. */ #ifndef _USE_LFN #define _USE_LFN 0 #endif static const char * dosify (const char *filename) { static char dos_filename[14]; char *df; int i; if (filename == 0 || _USE_LFN) return filename; /* FIXME: what about filenames which violate 8+3 constraints, like "config.h.in", or ".emacs"? */ if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0) return filename; df = dos_filename; /* First, transform the name part. */ for (i = 0; i < 8 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) *df++ = tolower ((unsigned char)*filename++); /* Now skip to the next dot. */ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) ++filename; if (*filename != '\0') { *df++ = *filename++; for (i = 0; i < 3 && ! STOP_SET (*filename, MAP_DOT|MAP_NUL); ++i) *df++ = tolower ((unsigned char)*filename++); } /* Look for more dots. */ while (! STOP_SET (*filename, MAP_DOT|MAP_NUL)) ++filename; if (*filename == '.') return filename; *df = 0; return dos_filename; } #endif /* __MSDOS__ */ #ifdef WINDOWS32 #include "pathstuff.h" #endif #ifdef _AMIGA #include #endif #ifdef HAVE_CASE_INSENSITIVE_FS static const char * downcase (const char *filename) { static PATH_VAR (new_filename); char *df; if (filename == 0) return 0; df = new_filename; while (*filename != '\0') { *df++ = tolower ((unsigned char)*filename); ++filename; } *df = 0; return new_filename; } #endif /* HAVE_CASE_INSENSITIVE_FS */ #ifdef VMS static int vms_hash (const char *name) { int h = 0; while (*name) { unsigned char uc = *name; int g; #ifdef HAVE_CASE_INSENSITIVE_FS h = (h << 4) + (isupper (uc) ? tolower (uc) : uc); #else h = (h << 4) + uc; #endif name++; g = h & 0xf0000000; if (g) { h = h ^ (g >> 24); h = h ^ g; } } return h; } /* fake stat entry for a directory */ static int vmsstat_dir (const char *name, struct stat *st) { char *s; int h; DIR *dir; dir = opendir (name); if (dir == 0) return -1; closedir (dir); s = strchr (name, ':'); /* find device */ if (s) { /* to keep the compiler happy we said "const char *name", now we cheat */ *s++ = 0; st->st_dev = (char *)vms_hash (name); h = vms_hash (s); *(s-1) = ':'; } else { st->st_dev = 0; h = vms_hash (name); } st->st_ino[0] = h & 0xff; st->st_ino[1] = h & 0xff00; st->st_ino[2] = h >> 16; return 0; } #endif /* VMS */ /* Hash table of directories. */ #ifndef DIRECTORY_BUCKETS #define DIRECTORY_BUCKETS 199 #endif struct directory_contents { dev_t dev; /* Device and inode numbers of this dir. */ #ifdef WINDOWS32 /* Inode means nothing on WINDOWS32. Even file key information is * unreliable because it is random per file open and undefined for remote * filesystems. The most unique attribute I can come up with is the fully * qualified name of the directory. Beware though, this is also * unreliable. I'm open to suggestion on a better way to emulate inode. */ char *path_key; int ctime; int mtime; /* controls check for stale directory cache */ int fs_flags; /* FS_FAT, FS_NTFS, ... */ # define FS_FAT 0x1 # define FS_NTFS 0x2 # define FS_UNKNOWN 0x4 #else # ifdef VMS ino_t ino[3]; # else ino_t ino; # endif #endif /* WINDOWS32 */ struct hash_table dirfiles; /* Files in this directory. */ DIR *dirstream; /* Stream reading this directory. */ }; static unsigned long directory_contents_hash_1 (const void *key_0) { const struct directory_contents *key = key_0; unsigned long hash; #ifdef WINDOWS32 hash = 0; ISTRING_HASH_1 (key->path_key, hash); hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) key->ctime; #else # ifdef VMS hash = (((unsigned int) key->dev << 4) ^ ((unsigned int) key->ino[0] + (unsigned int) key->ino[1] + (unsigned int) key->ino[2])); # else hash = ((unsigned int) key->dev << 4) ^ (unsigned int) key->ino; # endif #endif /* WINDOWS32 */ return hash; } static unsigned long directory_contents_hash_2 (const void *key_0) { const struct directory_contents *key = key_0; unsigned long hash; #ifdef WINDOWS32 hash = 0; ISTRING_HASH_2 (key->path_key, hash); hash ^= ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ctime; #else # ifdef VMS hash = (((unsigned int) key->dev << 4) ^ ~((unsigned int) key->ino[0] + (unsigned int) key->ino[1] + (unsigned int) key->ino[2])); # else hash = ((unsigned int) key->dev << 4) ^ (unsigned int) ~key->ino; # endif #endif /* WINDOWS32 */ return hash; } /* Sometimes it's OK to use subtraction to get this value: result = X - Y; But, if we're not sure of the type of X and Y they may be too large for an int (on a 64-bit system for example). So, use ?: instead. See Savannah bug #15534. NOTE! This macro has side-effects! */ #define MAKECMP(_x,_y) ((_x)<(_y)?-1:((_x)==(_y)?0:1)) static int directory_contents_hash_cmp (const void *xv, const void *yv) { const struct directory_contents *x = xv; const struct directory_contents *y = yv; int result; #ifdef WINDOWS32 ISTRING_COMPARE (x->path_key, y->path_key, result); if (result) return result; result = MAKECMP(x->ctime, y->ctime); if (result) return result; #else # ifdef VMS result = MAKECMP(x->ino[0], y->ino[0]); if (result) return result; result = MAKECMP(x->ino[1], y->ino[1]); if (result) return result; result = MAKECMP(x->ino[2], y->ino[2]); if (result) return result; # else result = MAKECMP(x->ino, y->ino); if (result) return result; # endif #endif /* WINDOWS32 */ return MAKECMP(x->dev, y->dev); } /* Table of directory contents hashed by device and inode number. */ static struct hash_table directory_contents; struct directory { const char *name; /* Name of the directory. */ /* The directory's contents. This data may be shared by several entries in the hash table, which refer to the same directory (identified uniquely by 'dev' and 'ino') under different names. */ struct directory_contents *contents; }; static unsigned long directory_hash_1 (const void *key) { return_ISTRING_HASH_1 (((const struct directory *) key)->name); } static unsigned long directory_hash_2 (const void *key) { return_ISTRING_HASH_2 (((const struct directory *) key)->name); } static int directory_hash_cmp (const void *x, const void *y) { return_ISTRING_COMPARE (((const struct directory *) x)->name, ((const struct directory *) y)->name); } /* Table of directories hashed by name. */ static struct hash_table directories; /* Never have more than this many directories open at once. */ #define MAX_OPEN_DIRECTORIES 10 static unsigned int open_directories = 0; /* Hash table of files in each directory. */ struct dirfile { const char *name; /* Name of the file. */ short length; short impossible; /* This file is impossible. */ }; static unsigned long dirfile_hash_1 (const void *key) { return_ISTRING_HASH_1 (((struct dirfile const *) key)->name); } static unsigned long dirfile_hash_2 (const void *key) { return_ISTRING_HASH_2 (((struct dirfile const *) key)->name); } static int dirfile_hash_cmp (const void *xv, const void *yv) { const struct dirfile *x = xv; const struct dirfile *y = yv; int result = x->length - y->length; if (result) return result; return_ISTRING_COMPARE (x->name, y->name); } #ifndef DIRFILE_BUCKETS #define DIRFILE_BUCKETS 107 #endif static int dir_contents_file_exists_p (struct directory_contents *dir, const char *filename); static struct directory *find_directory (const char *name); /* Find the directory named NAME and return its 'struct directory'. */ static struct directory * find_directory (const char *name) { struct directory *dir; struct directory **dir_slot; struct directory dir_key; #ifdef VMS if ((*name == '.') && (*(name+1) == 0)) name = "[]"; else name = vmsify (name,1); #endif dir_key.name = name; dir_slot = (struct directory **) hash_find_slot (&directories, &dir_key); dir = *dir_slot; if (HASH_VACANT (dir)) { /* The directory was not found. Create a new entry for it. */ const char *p = name + strlen (name); struct stat st; int r; dir = xmalloc (sizeof (struct directory)); #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) dir->name = strcache_add_len (downcase (name), p - name); #else dir->name = strcache_add_len (name, p - name); #endif hash_insert_at (&directories, dir, dir_slot); /* The directory is not in the name hash table. Find its device and inode numbers, and look it up by them. */ #ifdef VMS r = vmsstat_dir (name, &st); #elif defined(WINDOWS32) { char tem[MAXPATHLEN], *tstart, *tend; /* Remove any trailing slashes. Windows32 stat fails even on valid directories if they end in a slash. */ memcpy (tem, name, p - name + 1); tstart = tem; if (tstart[1] == ':') tstart += 2; for (tend = tem + (p - name - 1); tend > tstart && (*tend == '/' || *tend == '\\'); tend--) *tend = '\0'; r = stat (tem, &st); } #else EINTRLOOP (r, stat (name, &st)); #endif if (r < 0) { /* Couldn't stat the directory. Mark this by setting the 'contents' member to a nil pointer. */ dir->contents = 0; } else { /* Search the contents hash table; device and inode are the key. */ #ifdef WINDOWS32 char *w32_path; #endif struct directory_contents *dc; struct directory_contents **dc_slot; struct directory_contents dc_key; dc_key.dev = st.st_dev; #ifdef WINDOWS32 dc_key.path_key = w32_path = w32ify (name, 1); dc_key.ctime = st.st_ctime; #else # ifdef VMS dc_key.ino[0] = st.st_ino[0]; dc_key.ino[1] = st.st_ino[1]; dc_key.ino[2] = st.st_ino[2]; # else dc_key.ino = st.st_ino; # endif #endif dc_slot = (struct directory_contents **) hash_find_slot (&directory_contents, &dc_key); dc = *dc_slot; if (HASH_VACANT (dc)) { /* Nope; this really is a directory we haven't seen before. */ #ifdef WINDOWS32 char fs_label[BUFSIZ]; char fs_type[BUFSIZ]; unsigned long fs_serno; unsigned long fs_flags; unsigned long fs_len; #endif dc = (struct directory_contents *) xmalloc (sizeof (struct directory_contents)); /* Enter it in the contents hash table. */ dc->dev = st.st_dev; #ifdef WINDOWS32 dc->path_key = xstrdup (w32_path); dc->ctime = st.st_ctime; dc->mtime = st.st_mtime; /* NTFS is the only WINDOWS32 filesystem that bumps mtime on a directory when files are added/deleted from a directory. */ w32_path[3] = '\0'; if (GetVolumeInformation (w32_path, fs_label, sizeof (fs_label), &fs_serno, &fs_len, &fs_flags, fs_type, sizeof (fs_type)) == FALSE) dc->fs_flags = FS_UNKNOWN; else if (!strcmp (fs_type, "FAT")) dc->fs_flags = FS_FAT; else if (!strcmp (fs_type, "NTFS")) dc->fs_flags = FS_NTFS; else dc->fs_flags = FS_UNKNOWN; #else # ifdef VMS dc->ino[0] = st.st_ino[0]; dc->ino[1] = st.st_ino[1]; dc->ino[2] = st.st_ino[2]; # else dc->ino = st.st_ino; # endif #endif /* WINDOWS32 */ hash_insert_at (&directory_contents, dc, dc_slot); ENULLLOOP (dc->dirstream, opendir (name)); if (dc->dirstream == 0) /* Couldn't open the directory. Mark this by setting the 'files' member to a nil pointer. */ dc->dirfiles.ht_vec = 0; else { hash_init (&dc->dirfiles, DIRFILE_BUCKETS, dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); /* Keep track of how many directories are open. */ ++open_directories; if (open_directories == MAX_OPEN_DIRECTORIES) /* We have too many directories open already. Read the entire directory and then close it. */ dir_contents_file_exists_p (dc, 0); } } /* Point the name-hashed entry for DIR at its contents data. */ dir->contents = dc; } } return dir; } /* Return 1 if the name FILENAME is entered in DIR's hash table. FILENAME must contain no slashes. */ static int dir_contents_file_exists_p (struct directory_contents *dir, const char *filename) { struct dirfile *df; struct dirent *d; #ifdef WINDOWS32 struct stat st; int rehash = 0; #endif if (dir == 0 || dir->dirfiles.ht_vec == 0) /* The directory could not be stat'd or opened. */ return 0; #ifdef __MSDOS__ filename = dosify (filename); #endif #ifdef HAVE_CASE_INSENSITIVE_FS filename = downcase (filename); #endif #ifdef __EMX__ if (filename != 0) _fnlwr (filename); /* lower case for FAT drives */ #endif #ifdef VMS filename = vmsify (filename,0); #endif if (filename != 0) { struct dirfile dirfile_key; if (*filename == '\0') { /* Checking if the directory exists. */ return 1; } dirfile_key.name = filename; dirfile_key.length = strlen (filename); df = hash_find_item (&dir->dirfiles, &dirfile_key); if (df) return !df->impossible; } /* The file was not found in the hashed list. Try to read the directory further. */ if (dir->dirstream == 0) { #ifdef WINDOWS32 /* * Check to see if directory has changed since last read. FAT * filesystems force a rehash always as mtime does not change * on directories (ugh!). */ if (dir->path_key) { if ((dir->fs_flags & FS_FAT) != 0) { dir->mtime = time ((time_t *) 0); rehash = 1; } else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime) { /* reset date stamp to show most recent re-process. */ dir->mtime = st.st_mtime; rehash = 1; } /* If it has been already read in, all done. */ if (!rehash) return 0; /* make sure directory can still be opened; if not return. */ dir->dirstream = opendir (dir->path_key); if (!dir->dirstream) return 0; } else #endif /* The directory has been all read in. */ return 0; } while (1) { /* Enter the file in the hash table. */ unsigned int len; struct dirfile dirfile_key; struct dirfile **dirfile_slot; ENULLLOOP (d, readdir (dir->dirstream)); if (d == 0) { if (errno) pfatal_with_name ("INTERNAL: readdir"); break; } #if defined(VMS) && defined(HAVE_DIRENT_H) /* In VMS we get file versions too, which have to be stripped off */ { char *p = strrchr (d->d_name, ';'); if (p) *p = '\0'; } #endif if (!REAL_DIR_ENTRY (d)) continue; len = NAMLEN (d); dirfile_key.name = d->d_name; dirfile_key.length = len; dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key); #ifdef WINDOWS32 /* * If re-reading a directory, don't cache files that have * already been discovered. */ if (! rehash || HASH_VACANT (*dirfile_slot)) #endif { df = xmalloc (sizeof (struct dirfile)); #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) df->name = strcache_add_len (downcase (d->d_name), len); #else df->name = strcache_add_len (d->d_name, len); #endif df->length = len; df->impossible = 0; hash_insert_at (&dir->dirfiles, df, dirfile_slot); } /* Check if the name matches the one we're searching for. */ if (filename != 0 && patheq (d->d_name, filename)) return 1; } /* If the directory has been completely read in, close the stream and reset the pointer to nil. */ if (d == 0) { --open_directories; closedir (dir->dirstream); dir->dirstream = 0; } return 0; } /* Return 1 if the name FILENAME in directory DIRNAME is entered in the dir hash table. FILENAME must contain no slashes. */ int dir_file_exists_p (const char *dirname, const char *filename) { return dir_contents_file_exists_p (find_directory (dirname)->contents, filename); } /* Return 1 if the file named NAME exists. */ int file_exists_p (const char *name) { const char *dirend; const char *dirname; const char *slash; #ifndef NO_ARCHIVES { time_t member_date; if (ar_name (name)) return ar_member_date (name, &member_date); } #endif #ifdef VMS dirend = strrchr (name, ']'); if (dirend == 0) dirend = strrchr (name, ':'); if (dirend == 0) return dir_file_exists_p ("[]", name); #else /* !VMS */ dirend = strrchr (name, '/'); #ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr (name, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && name[0] && name[1] == ':') dirend = name + 1; } #endif /* HAVE_DOS_PATHS */ if (dirend == 0) #ifndef _AMIGA return dir_file_exists_p (".", name); #else /* !VMS && !AMIGA */ return dir_file_exists_p ("", name); #endif /* AMIGA */ #endif /* VMS */ slash = dirend; if (dirend == name) dirname = "/"; else { char *p; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < name + 3 && name[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif p = alloca (dirend - name + 1); memcpy (p, name, dirend - name); p[dirend - name] = '\0'; dirname = p; } return dir_file_exists_p (dirname, slash + 1); } /* Mark FILENAME as 'impossible' for 'file_impossible_p'. This means an attempt has been made to search for FILENAME as an intermediate file, and it has failed. */ void file_impossible (const char *filename) { const char *dirend; const char *p = filename; struct directory *dir; struct dirfile *new; #ifdef VMS dirend = strrchr (p, ']'); if (dirend == 0) dirend = strrchr (p, ':'); dirend++; if (dirend == (char *)1) dir = find_directory ("[]"); #else dirend = strrchr (p, '/'); # ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr (p, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && p[0] && p[1] == ':') dirend = p + 1; } # endif /* HAVE_DOS_PATHS */ if (dirend == 0) # ifdef _AMIGA dir = find_directory (""); # else /* !VMS && !AMIGA */ dir = find_directory ("."); # endif /* AMIGA */ #endif /* VMS */ else { const char *dirname; const char *slash = dirend; if (dirend == p) dirname = "/"; else { char *cp; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < p + 3 && p[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif cp = alloca (dirend - p + 1); memcpy (cp, p, dirend - p); cp[dirend - p] = '\0'; dirname = cp; } dir = find_directory (dirname); filename = p = slash + 1; } if (dir->contents == 0) /* The directory could not be stat'd. We allocate a contents structure for it, but leave it out of the contents hash table. */ dir->contents = xcalloc (sizeof (struct directory_contents)); if (dir->contents->dirfiles.ht_vec == 0) { hash_init (&dir->contents->dirfiles, DIRFILE_BUCKETS, dirfile_hash_1, dirfile_hash_2, dirfile_hash_cmp); } /* Make a new entry and put it in the table. */ new = xmalloc (sizeof (struct dirfile)); new->length = strlen (filename); #if defined(HAVE_CASE_INSENSITIVE_FS) && defined(VMS) new->name = strcache_add_len (downcase (filename), new->length); #else new->name = strcache_add_len (filename, new->length); #endif new->impossible = 1; hash_insert (&dir->contents->dirfiles, new); } /* Return nonzero if FILENAME has been marked impossible. */ int file_impossible_p (const char *filename) { const char *dirend; struct directory_contents *dir; struct dirfile *dirfile; struct dirfile dirfile_key; #ifdef VMS dirend = strrchr (filename, ']'); if (dirend == 0) dir = find_directory ("[]")->contents; #else dirend = strrchr (filename, '/'); #ifdef HAVE_DOS_PATHS /* Forward and backslashes might be mixed. We need the rightmost one. */ { const char *bslash = strrchr (filename, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && filename[0] && filename[1] == ':') dirend = filename + 1; } #endif /* HAVE_DOS_PATHS */ if (dirend == 0) #ifdef _AMIGA dir = find_directory ("")->contents; #else /* !VMS && !AMIGA */ dir = find_directory (".")->contents; #endif /* AMIGA */ #endif /* VMS */ else { const char *dirname; const char *slash = dirend; if (dirend == filename) dirname = "/"; else { char *cp; #ifdef HAVE_DOS_PATHS /* d:/ and d: are *very* different... */ if (dirend < filename + 3 && filename[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++; #endif cp = alloca (dirend - filename + 1); memcpy (cp, filename, dirend - filename); cp[dirend - filename] = '\0'; dirname = cp; } dir = find_directory (dirname)->contents; filename = slash + 1; } if (dir == 0 || dir->dirfiles.ht_vec == 0) /* There are no files entered for this directory. */ return 0; #ifdef __MSDOS__ filename = dosify (filename); #endif #ifdef HAVE_CASE_INSENSITIVE_FS filename = downcase (filename); #endif #ifdef VMS filename = vmsify (filename, 1); #endif dirfile_key.name = filename; dirfile_key.length = strlen (filename); dirfile = hash_find_item (&dir->dirfiles, &dirfile_key); if (dirfile) return dirfile->impossible; return 0; } /* Return the already allocated name in the directory hash table that matches DIR. */ const char * dir_name (const char *dir) { return find_directory (dir)->name; } /* Print the data base of directories. */ void print_dir_data_base (void) { unsigned int files; unsigned int impossible; struct directory **dir_slot; struct directory **dir_end; puts (_("\n# Directories\n")); files = impossible = 0; dir_slot = (struct directory **) directories.ht_vec; dir_end = dir_slot + directories.ht_size; for ( ; dir_slot < dir_end; dir_slot++) { struct directory *dir = *dir_slot; if (! HASH_VACANT (dir)) { if (dir->contents == 0) printf (_("# %s: could not be stat'd.\n"), dir->name); else if (dir->contents->dirfiles.ht_vec == 0) { #ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): could not be opened.\n"), dir->name, dir->contents->path_key,dir->contents->mtime); #else /* WINDOWS32 */ #ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]); #else printf (_("# %s (device %ld, inode %ld): could not be opened.\n"), dir->name, (long int) dir->contents->dev, (long int) dir->contents->ino); #endif #endif /* WINDOWS32 */ } else { unsigned int f = 0; unsigned int im = 0; struct dirfile **files_slot; struct dirfile **files_end; files_slot = (struct dirfile **) dir->contents->dirfiles.ht_vec; files_end = files_slot + dir->contents->dirfiles.ht_size; for ( ; files_slot < files_end; files_slot++) { struct dirfile *df = *files_slot; if (! HASH_VACANT (df)) { if (df->impossible) ++im; else ++f; } } #ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): "), dir->name, dir->contents->path_key, dir->contents->mtime); #else /* WINDOWS32 */ #ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): "), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]); #else printf (_("# %s (device %ld, inode %ld): "), dir->name, (long)dir->contents->dev, (long)dir->contents->ino); #endif #endif /* WINDOWS32 */ if (f == 0) fputs (_("No"), stdout); else printf ("%u", f); fputs (_(" files, "), stdout); if (im == 0) fputs (_("no"), stdout); else printf ("%u", im); fputs (_(" impossibilities"), stdout); if (dir->contents->dirstream == 0) puts ("."); else puts (_(" so far.")); files += f; impossible += im; } } } fputs ("\n# ", stdout); if (files == 0) fputs (_("No"), stdout); else printf ("%u", files); fputs (_(" files, "), stdout); if (impossible == 0) fputs (_("no"), stdout); else printf ("%u", impossible); printf (_(" impossibilities in %lu directories.\n"), directories.ht_fill); } /* Hooks for globbing. */ #include /* Structure describing state of iterating through a directory hash table. */ struct dirstream { struct directory_contents *contents; /* The directory being read. */ struct dirfile **dirfile_slot; /* Current slot in table. */ }; /* Forward declarations. */ static __ptr_t open_dirstream (const char *); static struct dirent *read_dirstream (__ptr_t); static __ptr_t open_dirstream (const char *directory) { struct dirstream *new; struct directory *dir = find_directory (directory); if (dir->contents == 0 || dir->contents->dirfiles.ht_vec == 0) /* DIR->contents is nil if the directory could not be stat'd. DIR->contents->dirfiles is nil if it could not be opened. */ return 0; /* Read all the contents of the directory now. There is no benefit in being lazy, since glob will want to see every file anyway. */ dir_contents_file_exists_p (dir->contents, 0); new = xmalloc (sizeof (struct dirstream)); new->contents = dir->contents; new->dirfile_slot = (struct dirfile **) new->contents->dirfiles.ht_vec; return (__ptr_t) new; } static struct dirent * read_dirstream (__ptr_t stream) { static char *buf; static unsigned int bufsz; struct dirstream *const ds = (struct dirstream *) stream; struct directory_contents *dc = ds->contents; struct dirfile **dirfile_end = (struct dirfile **) dc->dirfiles.ht_vec + dc->dirfiles.ht_size; while (ds->dirfile_slot < dirfile_end) { struct dirfile *df = *ds->dirfile_slot++; if (! HASH_VACANT (df) && !df->impossible) { /* The glob interface wants a 'struct dirent', so mock one up. */ struct dirent *d; unsigned int len = df->length + 1; unsigned int sz = sizeof (*d) - sizeof (d->d_name) + len; if (sz > bufsz) { bufsz *= 2; if (sz > bufsz) bufsz = sz; buf = xrealloc (buf, bufsz); } d = (struct dirent *) buf; #ifdef __MINGW32__ # if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && \ __MINGW32_MINOR_VERSION == 0) d->d_name = xmalloc (len); # endif #endif FAKE_DIR_ENTRY (d); #ifdef _DIRENT_HAVE_D_NAMLEN d->d_namlen = len - 1; #endif #ifdef _DIRENT_HAVE_D_TYPE d->d_type = DT_UNKNOWN; #endif memcpy (d->d_name, df->name, len); return d; } } return 0; } /* On 64 bit ReliantUNIX (5.44 and above) in LFS mode, stat() is actually a * macro for stat64(). If stat is a macro, make a local wrapper function to * invoke it. * * On MS-Windows, stat() "succeeds" for foo/bar/. where foo/bar is a * regular file; fix that here. */ #if !defined(stat) && !defined(WINDOWS32) # ifndef VMS int stat (const char *path, struct stat *sbuf); # endif # define local_stat stat #else static int local_stat (const char *path, struct stat *buf) { int e; #ifdef WINDOWS32 size_t plen = strlen (path); /* Make sure the parent of "." exists and is a directory, not a file. This is because 'stat' on Windows normalizes the argument foo/. => foo without checking first that foo is a directory. */ if (plen > 1 && path[plen - 1] == '.' && (path[plen - 2] == '/' || path[plen - 2] == '\\')) { char parent[MAXPATHLEN]; strncpy (parent, path, plen - 2); parent[plen - 2] = '\0'; if (stat (parent, buf) < 0 || !_S_ISDIR (buf->st_mode)) return -1; } #endif EINTRLOOP (e, stat (path, buf)); return e; } #endif void dir_setup_glob (glob_t *gl) { gl->gl_opendir = open_dirstream; gl->gl_readdir = read_dirstream; gl->gl_closedir = free; gl->gl_stat = local_stat; /* We don't bother setting gl_lstat, since glob never calls it. The slot is only there for compatibility with 4.4 BSD. */ } void hash_init_directories (void) { hash_init (&directories, DIRECTORY_BUCKETS, directory_hash_1, directory_hash_2, directory_hash_cmp); hash_init (&directory_contents, DIRECTORY_BUCKETS, directory_contents_hash_1, directory_contents_hash_2, directory_contents_hash_cmp); } remake-4.1+dbg1.3~dfsg.1/doc/000077500000000000000000000000001317072305000155405ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/doc/.cvsignore000066400000000000000000000003351317072305000175410ustar00rootroot00000000000000Makefile Makefile.in version.texi fdl.texi make-stds.texi texinfo.tex make.info* make*.html make.aux make.cp make.cps make.fn make.fns make.ky make.pg make.toc make.tp make.vr make.log make.dvi make.ps make.pdf stamp-vti remake-4.1+dbg1.3~dfsg.1/doc/.gitignore000066400000000000000000000005701317072305000175320ustar00rootroot00000000000000/*~ /Makefile /Makefile.in /fdl.texi /make-stds.texi /make.info /make.info-1 /make.info-2 /make_abt.html /mdb.info /remake.aux /remake.cp /remake.cps /remake.dvi /remake.fn /remake.html /remake.info /remake.ky /remake.kys /remake.log /remake.pdf /remake.pg /remake.toc /remake.tp /remake.vr /remake_1.html /remake_2.html /stamp-1 /stamp-vti /version-remake.texi /version.texi remake-4.1+dbg1.3~dfsg.1/doc/Makefile.am000066400000000000000000000016311317072305000175750ustar00rootroot00000000000000# -*-Makefile-*-, or close enough # Copyright (C) 2000-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . TEXI2HTML = texi2html TEXI2HTML_FLAGS = -split_chapter # info_TEXINFOS = make.texi # make_TEXINFOS = fdl.texi make-stds.texi CLEANFILES = callgrind.out.* make*.html remake-4.1+dbg1.3~dfsg.1/doc/test1.mk000066400000000000000000000003041317072305000171260ustar00rootroot00000000000000# Makefile to show off tracing .PHONY: all all: foo foo: @case $(MAKE) in \ */remake|remake) echo "Enlightened!";; \ */make|make) echo "This is what most folks use.";; \ esac @bogus-command remake-4.1+dbg1.3~dfsg.1/doc/test2.mk000066400000000000000000000001451317072305000171320ustar00rootroot00000000000000PACKAGE=make all: $(PACKAGE).txt $(PACKAGE).txt: ../doc/remake.texi makeinfo --no-headers $< > $@ remake-4.1+dbg1.3~dfsg.1/dosbuild.bat000066400000000000000000000064701317072305000172770ustar00rootroot00000000000000@echo off rem Copyright (C) 1998-2014 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Building Make for MSDOS rem Echo ON so they will see what is going on. @echo on gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g commands.c -o commands.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g output.c -o output.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g job.c -o job.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g dir.c -o dir.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g file.c -o file.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g misc.c -o misc.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g main.c -o main.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -DINCLUDEDIR=\"c:/djgpp/include\" -O2 -g read.c -o read.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -DLIBDIR=\"c:/djgpp/lib\" -O2 -g remake.c -o remake.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g rule.c -o rule.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g implicit.c -o implicit.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g default.c -o default.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g variable.c -o variable.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g expand.c -o expand.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g function.c -o function.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g vpath.c -o vpath.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g hash.c -o hash.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g strcache.c -o strcache.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g version.c -o version.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g ar.c -o ar.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g arscan.c -o arscan.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g signame.c -o signame.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g remote-stub.c -o remote-stub.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt.c -o getopt.o gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g getopt1.c -o getopt1.o @cd glob @if exist libglob.a del libglob.a gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g glob.c -o glob.o gcc -I. -c -DHAVE_CONFIG_H -I.. -O2 -g fnmatch.c -o fnmatch.o ar rv libglob.a glob.o fnmatch.o @echo off cd .. echo commands.o > respf.$$$ for %%f in (job output dir file misc main read remake rule implicit default variable) do echo %%f.o >> respf.$$$ for %%f in (expand function vpath hash strcache version ar arscan signame remote-stub getopt getopt1) do echo %%f.o >> respf.$$$ echo glob/libglob.a >> respf.$$$ rem gcc -c -I. -I./glob -DHAVE_CONFIG_H -O2 -g guile.c -o guile.o rem echo guile.o >> respf.$$$ @echo Linking... @echo on gcc -o make.new @respf.$$$ @if exist make.exe echo Make.exe is now built! @if not exist make.exe echo Make.exe build failed... @if exist make.exe del respf.$$$ remake-4.1+dbg1.3~dfsg.1/expand.c000066400000000000000000000441471317072305000164300ustar00rootroot00000000000000/* Variable expansion functions for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include "filedef.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" /* Initially, any errors reported when expanding strings will be reported against the file where the error appears. */ const gmk_floc **expanding_var = &reading_file; /* The next two describe the variable output buffer. This buffer is used to hold the variable-expansion of a line of the makefile. It is made bigger with realloc whenever it is too small. variable_buffer_length is the size currently allocated. variable_buffer is the address of the buffer. For efficiency, it's guaranteed that the buffer will always have VARIABLE_BUFFER_ZONE extra bytes allocated. This allows you to add a few extra chars without having to call a function. Note you should never use these bytes unless you're _sure_ you have room (you know when the buffer length was last checked. */ #define VARIABLE_BUFFER_ZONE 5 static unsigned int variable_buffer_length; char *variable_buffer; /* Subroutine of variable_expand and friends: The text to add is LENGTH chars starting at STRING to the variable_buffer. The text is added to the buffer at PTR, and the updated pointer into the buffer is returned as the value. Thus, the value returned by each call to variable_buffer_output should be the first argument to the following call. */ char * variable_buffer_output (char *ptr, const char *string, unsigned int length) { register unsigned int newlen = length + (ptr - variable_buffer); if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length) { unsigned int offset = ptr - variable_buffer; variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length ? newlen + 100 : 2 * variable_buffer_length); variable_buffer = xrealloc (variable_buffer, variable_buffer_length); ptr = variable_buffer + offset; } memcpy (ptr, string, length); return ptr + length; } /* Return a pointer to the beginning of the variable buffer. */ static char * initialize_variable_output (void) { /* If we don't have a variable output buffer yet, get one. */ if (variable_buffer == 0) { variable_buffer_length = 200; variable_buffer = xmalloc (variable_buffer_length); variable_buffer[0] = '\0'; } return variable_buffer; } /* Recursively expand V. The returned string is malloc'd. */ static char *allocated_variable_append (const struct variable *v); char * recursively_expand_for_file (struct variable *v, struct file *file) { char *value; const gmk_floc *this_var; const gmk_floc **saved_varp; struct variable_set_list *save = 0; int set_reading = 0; /* Don't install a new location if this location is empty. This can happen for command-line variables, builtin variables, etc. */ saved_varp = expanding_var; if (v->fileinfo.filenm) { this_var = &v->fileinfo; expanding_var = &this_var; } /* If we have no other file-reading context, use the variable's context. */ if (!reading_file) { set_reading = 1; reading_file = &v->fileinfo; } if (v->expanding) { if (!v->exp_count) /* Expanding V causes infinite recursion. Lose. */ OS (fatal, *expanding_var, _("Recursive variable '%s' references itself (eventually)"), v->name); --v->exp_count; } if (file) { save = current_variable_set_list; current_variable_set_list = file->variables; } v->expanding = 1; if (v->append) value = allocated_variable_append (v); else value = allocated_variable_expand (v->value); v->expanding = 0; if (set_reading) reading_file = 0; if (file) current_variable_set_list = save; expanding_var = saved_varp; return value; } /* Expand a simple reference to variable NAME, which is LENGTH chars long. */ #ifdef __GNUC__ __inline #endif static char * reference_variable (char *o, const char *name, unsigned int length) { struct variable *v; char *value; v = lookup_variable (name, length); if (v == 0) warn_undefined (name, length); /* If there's no variable by that name or it has no value, stop now. */ if (v == 0 || (*v->value == '\0' && !v->append)) return o; value = (v->recursive ? recursively_expand (v) : v->value); o = variable_buffer_output (o, value, strlen (value)); if (v->recursive) free (value); return o; } /* Scan STRING for variable references and expansion-function calls. Only LENGTH bytes of STRING are actually scanned. If LENGTH is -1, scan until a null byte is found. Write the results to LINE, which must point into 'variable_buffer'. If LINE is NULL, start at the beginning of the buffer. Return a pointer to LINE, or to the beginning of the buffer if LINE is NULL. */ char * variable_expand_string (char *line, const char *string, long length) { struct variable *v; const char *p, *p1; char *save; char *o; unsigned int line_offset; if (!line) line = initialize_variable_output (); o = line; line_offset = line - variable_buffer; if (length == 0) { variable_buffer_output (o, "", 1); return (variable_buffer); } /* We need a copy of STRING: due to eval, it's possible that it will get freed as we process it (it might be the value of a variable that's reset for example). Also having a nil-terminated string is handy. */ save = length < 0 ? xstrdup (string) : xstrndup (string, length); p = save; while (1) { /* Copy all following uninteresting chars all at once to the variable output buffer, and skip them. Uninteresting chars end at the next $ or the end of the input. */ p1 = strchr (p, '$'); o = variable_buffer_output (o, p, p1 != 0 ? (unsigned int)(p1 - p) : strlen (p) + 1); if (p1 == 0) break; p = p1 + 1; /* Dispatch on the char that follows the $. */ switch (*p) { case '$': /* $$ seen means output one $ to the variable output buffer. */ o = variable_buffer_output (o, p, 1); break; case '(': case '{': /* $(...) or ${...} is the general case of substitution. */ { char openparen = *p; char closeparen = (openparen == '(') ? ')' : '}'; const char *begp; const char *beg = p + 1; char *op; char *abeg = NULL; const char *end, *colon; op = o; begp = p; if (handle_function (&op, &begp)) { o = op; p = begp; break; } /* Is there a variable reference inside the parens or braces? If so, expand it before expanding the entire reference. */ end = strchr (beg, closeparen); if (end == 0) /* Unterminated variable reference. */ O (fatal, *expanding_var, _("unterminated variable reference")); p1 = lindex (beg, end, '$'); if (p1 != 0) { /* BEG now points past the opening paren or brace. Count parens or braces until it is matched. */ int count = 0; for (p = beg; *p != '\0'; ++p) { if (*p == openparen) ++count; else if (*p == closeparen && --count < 0) break; } /* If COUNT is >= 0, there were unmatched opening parens or braces, so we go to the simple case of a variable name such as '$($(a)'. */ if (count < 0) { abeg = expand_argument (beg, p); /* Expand the name. */ beg = abeg; end = strchr (beg, '\0'); } } else /* Advance P to the end of this reference. After we are finished expanding this one, P will be incremented to continue the scan. */ p = end; /* This is not a reference to a built-in function and any variable references inside are now expanded. Is the resultant text a substitution reference? */ colon = lindex (beg, end, ':'); if (colon) { /* This looks like a substitution reference: $(FOO:A=B). */ const char *subst_beg = colon + 1; const char *subst_end = lindex (subst_beg, end, '='); if (subst_end == 0) /* There is no = in sight. Punt on the substitution reference and treat this as a variable name containing a colon, in the code below. */ colon = 0; else { const char *replace_beg = subst_end + 1; const char *replace_end = end; /* Extract the variable name before the colon and look up that variable. */ v = lookup_variable (beg, colon - beg); if (v == 0) warn_undefined (beg, colon - beg); /* If the variable is not empty, perform the substitution. */ if (v != 0 && *v->value != '\0') { char *pattern, *replace, *ppercent, *rpercent; char *value = (v->recursive ? recursively_expand (v) : v->value); /* Copy the pattern and the replacement. Add in an extra % at the beginning to use in case there isn't one in the pattern. */ pattern = alloca (subst_end - subst_beg + 2); *(pattern++) = '%'; memcpy (pattern, subst_beg, subst_end - subst_beg); pattern[subst_end - subst_beg] = '\0'; replace = alloca (replace_end - replace_beg + 2); *(replace++) = '%'; memcpy (replace, replace_beg, replace_end - replace_beg); replace[replace_end - replace_beg] = '\0'; /* Look for %. Set the percent pointers properly based on whether we find one or not. */ ppercent = find_percent (pattern); if (ppercent) { ++ppercent; rpercent = find_percent (replace); if (rpercent) ++rpercent; } else { ppercent = pattern; rpercent = replace; --pattern; --replace; } o = patsubst_expand_pat (o, value, pattern, replace, ppercent, rpercent); if (v->recursive) free (value); } } } if (colon == 0) /* This is an ordinary variable reference. Look up the value of the variable. */ o = reference_variable (o, beg, end - beg); free (abeg); } break; case '\0': break; default: if (isblank ((unsigned char)p[-1])) break; /* A $ followed by a random char is a variable reference: $a is equivalent to $(a). */ o = reference_variable (o, p, 1); break; } if (*p == '\0') break; ++p; } free (save); variable_buffer_output (o, "", 1); return (variable_buffer + line_offset); } /* Scan LINE for variable references and expansion-function calls. Build in 'variable_buffer' the result of expanding the references and calls. Return the address of the resulting string, which is null-terminated and is valid only until the next time this function is called. */ char * variable_expand (const char *line) { return variable_expand_string (NULL, line, (long)-1); } /* Expand an argument for an expansion function. The text starting at STR and ending at END is variable-expanded into a null-terminated string that is returned as the value. This is done without clobbering 'variable_buffer' or the current variable-expansion that is in progress. */ char * expand_argument (const char *str, const char *end) { char *tmp, *alloc = NULL; char *r; if (str == end) return xstrdup (""); if (!end || *end == '\0') return allocated_variable_expand (str); if (end - str + 1 > 1000) tmp = alloc = xmalloc (end - str + 1); else tmp = alloca (end - str + 1); memcpy (tmp, str, end - str); tmp[end - str] = '\0'; r = allocated_variable_expand (tmp); free (alloc); return r; } /* Expand LINE for FILE. Error messages refer to the file and line where FILE's commands were found. Expansion uses FILE's variable set list. */ char * variable_expand_for_file (const char *line, struct file *file) { char *result; struct variable_set_list *savev; const gmk_floc *savef; if (file == 0) return variable_expand (line); savev = current_variable_set_list; current_variable_set_list = file->variables; savef = reading_file; if (file->cmds && file->cmds->fileinfo.filenm) reading_file = &file->cmds->fileinfo; else reading_file = 0; result = variable_expand (line); current_variable_set_list = savev; reading_file = savef; return result; } /** Expand PSZ_LINE. Expansion uses P_FILE_SET if it is not NULL. */ char * variable_expand_set (char *psz_line, variable_set_list_t *p_file_vars) { char *psz_result; variable_set_list_t *p_vars_save; p_vars_save = current_variable_set_list; if (p_file_vars) current_variable_set_list = p_file_vars; psz_result = variable_expand (psz_line); current_variable_set_list = p_vars_save; return psz_result; } /* Like allocated_variable_expand, but for += target-specific variables. First recursively construct the variable value from its appended parts in any upper variable sets. Then expand the resulting value. */ static char * variable_append (const char *name, unsigned int length, const struct variable_set_list *set, int local) { const struct variable *v; char *buf = 0; /* If this set is local and the next is not a parent, then next is local. */ int nextlocal = local && set->next_is_parent == 0; /* If there's nothing left to check, return the empty buffer. */ if (!set) return initialize_variable_output (); /* Try to find the variable in this variable set. */ v = lookup_variable_in_set (name, length, set->set); /* If there isn't one, or this one is private, try the set above us. */ if (!v || (!local && v->private_var)) return variable_append (name, length, set->next, nextlocal); /* If this variable type is append, first get any upper values. If not, initialize the buffer. */ if (v->append) buf = variable_append (name, length, set->next, nextlocal); else buf = initialize_variable_output (); /* Append this value to the buffer, and return it. If we already have a value, first add a space. */ if (buf > variable_buffer) buf = variable_buffer_output (buf, " ", 1); /* Either expand it or copy it, depending. */ if (! v->recursive) return variable_buffer_output (buf, v->value, strlen (v->value)); buf = variable_expand_string (buf, v->value, strlen (v->value)); return (buf + strlen (buf)); } static char * allocated_variable_append (const struct variable *v) { char *val; /* Construct the appended variable value. */ char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; variable_buffer = 0; val = variable_append (v->name, strlen (v->name), current_variable_set_list, 1); variable_buffer_output (val, "", 1); val = variable_buffer; variable_buffer = obuf; variable_buffer_length = olen; return val; } /* Like variable_expand_for_file, but the returned string is malloc'd. This function is called a lot. It wants to be efficient. */ char * allocated_variable_expand_for_file (const char *line, struct file *file) { char *value; char *obuf = variable_buffer; unsigned int olen = variable_buffer_length; variable_buffer = 0; value = variable_expand_for_file (line, file); variable_buffer = obuf; variable_buffer_length = olen; return value; } /* Install a new variable_buffer context, returning the current one for safe-keeping. */ void install_variable_buffer (char **bufp, unsigned int *lenp) { *bufp = variable_buffer; *lenp = variable_buffer_length; variable_buffer = 0; initialize_variable_output (); } /* Restore a previously-saved variable_buffer setting (free the current one). */ void restore_variable_buffer (char *buf, unsigned int len) { free (variable_buffer); variable_buffer = buf; variable_buffer_length = len; } remake-4.1+dbg1.3~dfsg.1/expand.h000066400000000000000000000052121317072305000164230ustar00rootroot00000000000000/* $Id: expand.h,v 1.9 2006/12/18 10:12:25 rockyb Exp $ Copyright (C) 2005 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file expand.h * * \brief Header for variable expansion functions for GNU Make. */ #ifndef REMAKE_EXPAND_H #define REMAKE_EXPAND_H #include "variable.h" #include "filedef.h" /*! Like variable_expand_for_file, but the returned string is malloc'd. This function is called a lot. It wants to be efficient. */ extern char *allocated_variable_expand_for_file(const char *psz_line, file_t *p_file); /*! Expand an argument for an expansion function. The text starting at STR and ending at END is variable-expanded into a null-terminated string that is returned as the value. This is done without clobbering `variable_buffer' or the current variable-expansion that is in progress. */ extern char *expand_argument(const char *str, const char *end); /*! Install a new variable_buffer context, returning the current one for safe-keeping. */ extern void install_variable_buffer (char **pp_buf, unsigned int *pi_len); /*! Restore a previously-saved variable_buffer setting (free the current one). */ #define recursively_expand(v) recursively_expand_for_file (v, NULL) /*! Recursively expand V. The returned string is malloc'd. */ extern char *recursively_expand_for_file(variable_t *v, file_t *file); /*! Subroutine of variable_expand and friends: The text to add is LENGTH chars starting at STRING to the variable_buffer. The text is added to the buffer at PTR, and the updated pointer into the buffer is returned as the value. Thus, the value returned by each call to variable_buffer_output should be the first argument to the following call. */ extern void restore_variable_buffer(char *p_buf, unsigned int len); /** Expand PSZ_LINE. Expansion uses P_FILE_SET if it is not NULL. */ extern char *variable_expand_set (char *psz_line, variable_set_list_t *p_file_set); #endif /*REMAKE_EXPAND_H*/ remake-4.1+dbg1.3~dfsg.1/file.c000066400000000000000000000773531317072305000160750ustar00rootroot00000000000000/* Target file management for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "file_basic.h" #include #include "filedef.h" #include "file.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "debug.h" #include "hash.h" /* Remember whether snap_deps has been invoked: we need this to be sure we don't add new rules (via $(eval ...)) afterwards. In the future it would be nice to support this, but it means we'd need to re-run snap_deps() or at least its functionality... it might mean changing snap_deps() to be run per-file, so we can invoke it after the eval... or remembering which files in the hash have been snapped (a new boolean flag?) and having snap_deps() only work on files which have not yet been snapped. */ int snapped_deps = 0; /* Hash table of files the makefile knows how to make. */ /* Whether or not .SECONDARY with no prerequisites was given. */ static int all_secondary = 0; /* Rehash FILE to NAME. This is not as simple as resetting the 'hname' member, since it must be put in a new hash bucket, and possibly merged with an existing file called NAME. */ void rehash_file (struct file *from_file, const char *to_hname) { struct file file_key; struct file **file_slot; struct file *to_file; struct file *deleted_file; struct file *f; /* If it's already that name, we're done. */ from_file->builtin = 0; file_key.hname = to_hname; if (! file_hash_cmp (from_file, &file_key)) return; /* Find the end of the renamed list for the "from" file. */ file_key.hname = from_file->hname; while (from_file->renamed != 0) from_file = from_file->renamed; if (file_hash_cmp (from_file, &file_key)) /* hname changed unexpectedly!! */ abort (); /* Remove the "from" file from the hash. */ deleted_file = hash_delete (&files, from_file); if (deleted_file != from_file) /* from_file isn't the one stored in files */ abort (); /* Find where the newly renamed file will go in the hash. */ file_key.hname = to_hname; file_slot = (struct file **) hash_find_slot (&files, &file_key); to_file = *file_slot; /* Change the hash name for this file. */ from_file->hname = to_hname; for (f = from_file->double_colon; f != 0; f = f->prev) f->hname = to_hname; /* If the new name doesn't exist yet just set it to the renamed file. */ if (HASH_VACANT (to_file)) { hash_insert_at (&files, from_file, file_slot); return; } /* TO_FILE already exists under TO_HNAME. We must retain TO_FILE and merge FROM_FILE into it. */ if (from_file->cmds != 0) { if (to_file->cmds == 0) to_file->cmds = from_file->cmds; else if (from_file->cmds != to_file->cmds) { size_t l = strlen (from_file->name); /* We have two sets of commands. We will go with the one given in the rule explicitly mentioning this name, but give a message to let the user know what's going on. */ if (to_file->cmds->fileinfo.filenm != 0) error (&from_file->cmds->fileinfo, l + strlen (to_file->cmds->fileinfo.filenm) + INTSTR_LENGTH, _("Recipe was specified for file '%s' at %s:%lu,"), from_file->name, to_file->cmds->fileinfo.filenm, to_file->cmds->fileinfo.lineno); else error (&from_file->cmds->fileinfo, l, _("Recipe for file '%s' was found by implicit rule search,"), from_file->name); l += strlen (to_hname); error (&from_file->cmds->fileinfo, l, _("but '%s' is now considered the same file as '%s'."), from_file->name, to_hname); error (&from_file->cmds->fileinfo, l, _("Recipe for '%s' will be ignored in favor of the one for '%s'."), to_hname, from_file->name); } } /* Merge the dependencies of the two files. */ if (to_file->deps == 0) to_file->deps = from_file->deps; else { struct dep *deps = to_file->deps; while (deps->next != 0) deps = deps->next; deps->next = from_file->deps; } merge_variable_set_lists (&to_file->variables, from_file->variables); if (to_file->double_colon && from_file->is_target && !from_file->double_colon) OSS (fatal, NILF, _("can't rename single-colon '%s' to double-colon '%s'"), from_file->name, to_hname); if (!to_file->double_colon && from_file->double_colon) { if (to_file->is_target) OSS (fatal, NILF, _("can't rename double-colon '%s' to single-colon '%s'"), from_file->name, to_hname); else to_file->double_colon = from_file->double_colon; } if (from_file->last_mtime > to_file->last_mtime) /* %%% Kludge so -W wins on a file that gets vpathized. */ to_file->last_mtime = from_file->last_mtime; to_file->mtime_before_update = from_file->mtime_before_update; #define MERGE(field) to_file->field |= from_file->field MERGE (precious); MERGE (tried_implicit); MERGE (updating); MERGE (updated); MERGE (is_target); MERGE (cmd_target); MERGE (phony); MERGE (loaded); MERGE (ignore_vpath); #undef MERGE to_file->builtin = 0; from_file->renamed = to_file; } /* Rename FILE to NAME. This is not as simple as resetting the 'name' member, since it must be put in a new hash bucket, and possibly merged with an existing file called NAME. */ void rename_file (struct file *from_file, const char *to_hname) { rehash_file (from_file, to_hname); while (from_file) { from_file->name = from_file->hname; from_file = from_file->prev; } } /* Remove all nonprecious intermediate files. If SIG is nonzero, this was caused by a fatal signal, meaning that a different message will be printed, and the message will go to stderr rather than stdout. */ void remove_intermediates (int sig) { struct file **file_slot; struct file **file_end; int doneany = 0; /* If there's no way we will ever remove anything anyway, punt early. */ if (question_flag || touch_flag || all_secondary) return; if (sig && just_print_flag) return; file_slot = (struct file **) files.ht_vec; file_end = file_slot + files.ht_size; for ( ; file_slot < file_end; file_slot++) if (! HASH_VACANT (*file_slot)) { struct file *f = *file_slot; /* Is this file eligible for automatic deletion? Yes, IFF: it's marked intermediate, it's not secondary, it wasn't given on the command line, and it's either a -include makefile or it's not precious. */ if (f->intermediate && (f->dontcare || !f->precious) && !f->secondary && !f->cmd_target) { int status; if (f->update_status == us_none) /* If nothing would have created this file yet, don't print an "rm" command for it. */ continue; if (just_print_flag) status = 0; else { status = unlink (f->name); if (status < 0 && errno == ENOENT) continue; } if (!f->dontcare) { if (sig) OS (error, NILF, _("*** Deleting intermediate file '%s'"), f->name); else { if (! doneany) DB (DB_BASIC, (_("Removing intermediate files...\n"))); if (!silent_flag) { if (! doneany) { fputs ("rm ", stdout); doneany = 1; } else putchar (' '); fputs (f->name, stdout); fflush (stdout); } } if (status < 0) perror_with_name ("unlink: ", f->name); } } } if (doneany && !sig) { putchar ('\n'); fflush (stdout); } } /* Given a string containing prerequisites (fully expanded), break it up into a struct dep list. Enter each of these prereqs into the file database. */ struct dep * split_prereqs (char *p) { struct dep *new = PARSE_FILE_SEQ (&p, struct dep, MAP_PIPE, NULL, PARSEFS_NONE); if (*p) { /* Files that follow '|' are "order-only" prerequisites that satisfy the dependency by existing: their modification times are irrelevant. */ struct dep *ood; ++p; ood = PARSE_SIMPLE_SEQ (&p, struct dep); if (! new) new = ood; else { struct dep *dp; for (dp = new; dp->next != NULL; dp = dp->next) ; dp->next = ood; } for (; ood != NULL; ood = ood->next) ood->ignore_mtime = 1; } return new; } /* Given a list of prerequisites, enter them into the file database. If STEM is set then first expand patterns using STEM. */ struct dep * enter_prereqs (struct dep *deps, const char *stem) { struct dep *d1; if (deps == 0) return 0; /* If we have a stem, expand the %'s. We use patsubst_expand to translate the prerequisites' patterns into plain prerequisite names. */ if (stem) { const char *pattern = "%"; char *buffer = variable_expand (""); struct dep *dp = deps, *dl = 0; while (dp != 0) { char *percent; int nl = strlen (dp->name) + 1; char *nm = alloca (nl); memcpy (nm, dp->name, nl); percent = find_percent (nm); if (percent) { char *o; /* We have to handle empty stems specially, because that would be equivalent to $(patsubst %,dp->name,) which will always be empty. */ if (stem[0] == '\0') { memmove (percent, percent+1, strlen (percent)); o = variable_buffer_output (buffer, nm, strlen (nm) + 1); } else o = patsubst_expand_pat (buffer, stem, pattern, nm, pattern+1, percent+1); /* If the name expanded to the empty string, ignore it. */ if (buffer[0] == '\0') { struct dep *df = dp; if (dp == deps) dp = deps = deps->next; else dp = dl->next = dp->next; free_dep (df); continue; } /* Save the name. */ dp->name = strcache_add_len (buffer, o - buffer); } dp->stem = stem; dp->staticpattern = 1; dl = dp; dp = dp->next; } } /* Enter them as files, unless they need a 2nd expansion. */ for (d1 = deps; d1 != 0; d1 = d1->next) { if (d1->need_2nd_expansion) continue; d1->file = lookup_file (d1->name); if (d1->file == 0) d1->file = enter_file (d1->name); d1->staticpattern = 0; d1->name = 0; } return deps; } /* Set the intermediate flag. */ static void set_intermediate (const void *item) { struct file *f = (struct file *) item; f->intermediate = 1; } /* Expand and parse each dependency line. */ void expand_deps (struct file *f) { struct dep *d; struct dep **dp; const char *file_stem = f->stem; int initialized = 0; f->updating = 0; /* Walk through the dependencies. For any dependency that needs 2nd expansion, expand it then insert the result into the list. */ dp = &f->deps; d = f->deps; while (d != 0) { char *p; struct dep *new, *next; char *name = (char *)d->name; if (! d->name || ! d->need_2nd_expansion) { /* This one is all set already. */ dp = &d->next; d = d->next; continue; } /* If it's from a static pattern rule, convert the patterns into "$*" so they'll expand properly. */ if (d->staticpattern) { char *o = variable_expand (""); o = subst_expand (o, name, "%", "$*", 1, 2, 0); *o = '\0'; free (name); d->name = name = xstrdup (variable_buffer); d->staticpattern = 0; } /* We're going to do second expansion so initialize file variables for the file. Since the stem for static pattern rules comes from individual dep lines, we will temporarily set f->stem to d->stem. */ if (!initialized) { initialize_file_variables (f, 0); initialized = 1; } if (d->stem != 0) f->stem = d->stem; set_file_variables (f); p = variable_expand_for_file (d->name, f); if (d->stem != 0) f->stem = file_stem; /* At this point we don't need the name anymore: free it. */ free (name); /* Parse the prerequisites and enter them into the file database. */ new = enter_prereqs (split_prereqs (p), d->stem); /* If there were no prereqs here (blank!) then throw this one out. */ if (new == 0) { *dp = d->next; free_dep (d); d = *dp; continue; } /* Add newly parsed prerequisites. */ next = d->next; *dp = new; for (dp = &new->next, d = new->next; d != 0; dp = &d->next, d = d->next) ; *dp = next; d = *dp; } } /* Reset the updating flag. */ static void reset_updating (const void *item) { struct file *f = (struct file *) item; f->updating = 0; } /* For each dependency of each file, make the 'struct dep' point at the appropriate 'struct file' (which may have to be created). Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT, and various other special targets. */ void snap_deps (void) { struct file *f; struct file *f2; struct dep *d; /* Remember that we've done this. Once we start snapping deps we can no longer define new targets. */ snapped_deps = 1; /* Perform second expansion and enter each dependency name as a file. We must use hash_dump() here because within these loops we likely add new files to the table, possibly causing an in-situ table expansion. We only need to do this if second_expansion has been defined; if it hasn't then all deps were expanded as the makefile was read in. If we ever change make to be able to unset .SECONDARY_EXPANSION this will have to change. */ if (second_expansion) { struct file **file_slot_0 = (struct file **) hash_dump (&files, 0, 0); struct file **file_end = file_slot_0 + files.ht_fill; struct file **file_slot; const char *suffixes; /* Expand .SUFFIXES: its prerequisites are used for $$* calc. */ f = lookup_file (".SUFFIXES"); suffixes = f ? f->name : 0; for (; f != 0; f = f->prev) expand_deps (f); /* For every target that's not .SUFFIXES, expand its prerequisites. */ for (file_slot = file_slot_0; file_slot < file_end; file_slot++) for (f = *file_slot; f != 0; f = f->prev) if (f->name != suffixes) expand_deps (f); free (file_slot_0); } else /* We're not doing second expansion, so reset updating. */ hash_map (&files, reset_updating); /* Now manage all the special targets. */ for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev) for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->precious = 1; for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev) for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->low_resolution_time = 1; for (f = lookup_file (".PHONY"); f != 0; f = f->prev) for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) { /* Mark this file as phony nonexistent target. */ f2->phony = 1; f2->is_target = 1; f2->last_mtime = NONEXISTENT_MTIME; f2->mtime_before_update = NONEXISTENT_MTIME; } for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev) /* Mark .INTERMEDIATE deps as intermediate files. */ for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->intermediate = 1; /* .INTERMEDIATE with no deps does nothing. Marking all files as intermediates is useless since the goal targets would be deleted after they are built. */ for (f = lookup_file (".SECONDARY"); f != 0; f = f->prev) /* Mark .SECONDARY deps as both intermediate and secondary. */ if (f->deps) for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->intermediate = f2->secondary = 1; /* .SECONDARY with no deps listed marks *all* files that way. */ else { all_secondary = 1; hash_map (&files, set_intermediate); } f = lookup_file (".EXPORT_ALL_VARIABLES"); if (f != 0 && f->is_target) export_all_variables = 1; f = lookup_file (".IGNORE"); if (f != 0 && f->is_target) { if (f->deps == 0) ignore_errors_flag = 1; else for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->command_flags |= COMMANDS_NOERROR; } f = lookup_file (".SILENT"); if (f != 0 && f->is_target) { if (f->deps == 0) silent_flag = 1; else for (d = f->deps; d != 0; d = d->next) for (f2 = d->file; f2 != 0; f2 = f2->prev) f2->command_flags |= COMMANDS_SILENT; } f = lookup_file (".NOTPARALLEL"); if (f != 0 && f->is_target) not_parallel = 1; #ifndef NO_MINUS_C_MINUS_O /* If .POSIX was defined, remove OUTPUT_OPTION to comply. */ /* This needs more work: what if the user sets this in the makefile? if (posix_pedantic) define_variable_cname ("OUTPUT_OPTION", "", o_default, 1); */ #endif } /* Set the 'command_state' member of FILE and all its 'also_make's. */ void set_command_state (struct file *file, enum cmd_state state) { struct dep *d; file->command_state = state; for (d = file->also_make; d != 0; d = d->next) d->file->command_state = state; } /* Convert an external file timestamp to internal form. */ FILE_TIMESTAMP file_timestamp_cons (const char *fname, time_t stamp, long int ns) { int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0); FILE_TIMESTAMP s = stamp; FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS; FILE_TIMESTAMP ts = product + offset; if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX) && product <= ts && ts <= ORDINARY_MTIME_MAX)) { char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; const char *f = fname ? fname : _("Current time"); ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; file_timestamp_sprintf (buf, ts); OSS (error, NILF, _("%s: Timestamp out of range; substituting %s"), f, buf); } return ts; } /* Return the current time as a file timestamp, setting *RESOLUTION to its resolution. */ FILE_TIMESTAMP file_timestamp_now (int *resolution) { int r; time_t s; int ns; /* Don't bother with high-resolution clocks if file timestamps have only one-second resolution. The code below should work, but it's not worth the hassle of debugging it on hosts where it fails. */ #if FILE_TIMESTAMP_HI_RES # if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME { struct timespec timespec; if (clock_gettime (CLOCK_REALTIME, ×pec) == 0) { r = 1; s = timespec.tv_sec; ns = timespec.tv_nsec; goto got_time; } } # endif # if HAVE_GETTIMEOFDAY { struct timeval timeval; if (gettimeofday (&timeval, 0) == 0) { r = 1000; s = timeval.tv_sec; ns = timeval.tv_usec * 1000; goto got_time; } } # endif #endif r = 1000000000; s = time ((time_t *) 0); ns = 0; #if FILE_TIMESTAMP_HI_RES got_time: #endif *resolution = r; return file_timestamp_cons (0, s, ns); } /* Place into the buffer P a printable representation of the file timestamp TS. */ void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts) { time_t t = FILE_TIMESTAMP_S (ts); struct tm *tm = localtime (&t); if (tm) sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); else if (t < 0) sprintf (p, "%ld", (long) t); else sprintf (p, "%lu", (unsigned long) t); p += strlen (p); /* Append nanoseconds as a fraction, but remove trailing zeros. We don't know the actual timestamp resolution, since clock_getres applies only to local times, whereas this timestamp might come from a remote filesystem. So removing trailing zeros is the best guess that we can do. */ sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts)); p += strlen (p) - 1; while (*p == '0') p--; p += *p != '.'; *p = '\0'; } /*! Print some or all properties of the data base of files. */ void print_target_props (file_t *p_target, print_target_mask_t i_mask) { dep_t *d; dep_t *ood = 0; putchar ('\n'); if (!p_target->is_target) puts (_("# Not a target:")); printf ("%s:%s", p_target->name, p_target->double_colon ? ":" : ""); /* Print all normal dependencies; note any order-only deps. */ for (d = p_target->deps; d != 0; d = d->next) if (! d->ignore_mtime) { if (i_mask & PRINT_TARGET_NONORDER) printf (" %s", dep_name (d)); } else if (! ood) ood = d; if (i_mask & PRINT_TARGET_ORDER) { /* Print order-only deps, if we have any. */ if (ood) { printf (" | %s", dep_name (ood)); for (d = ood->next; d != 0; d = d->next) if (d->ignore_mtime) printf (" %s", dep_name (d)); } } putchar ('\n'); if (i_mask & PRINT_TARGET_ATTRS) { if (p_target->precious) puts (_("# Precious file (prerequisite of .PRECIOUS).")); if (p_target->phony) puts (_("# Phony target (prerequisite of .PHONY).")); if (p_target->cmd_target) puts (_("# Command-line target.")); if (p_target->dontcare) puts (_("# A default, MAKEFILES, or -include/sinclude makefile.")); puts (p_target->tried_implicit ? _("# Implicit rule search has been done.") : _("# Implicit rule search has not been done.")); if (p_target->stem != 0) printf (_("# Implicit/static pattern stem: `%s'\n"), p_target->stem); if (p_target->intermediate) puts (_("# File is an intermediate prerequisite.")); if (p_target->also_make != 0) { fputs (_("# Also makes:"), stdout); for (d = p_target->also_make; d != 0; d = d->next) printf (" %s", dep_name (d)); putchar ('\n'); } } if (i_mask & PRINT_TARGET_TIME) { if (p_target->last_mtime == UNKNOWN_MTIME) puts (_("# Modification time never checked.")); else if (p_target->last_mtime == NONEXISTENT_MTIME) puts (_("# File does not exist.")); else if (p_target->last_mtime == OLD_MTIME) puts (_("# File is very old.")); else { char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; file_timestamp_sprintf (buf, p_target->last_mtime); printf (_("# Last modified %s\n"), buf); } puts (p_target->updated ? _("# File has been updated.") : _("# File has not been updated.")); } if (i_mask & PRINT_TARGET_STATE) { switch (p_target->command_state) { case cs_running: puts (_("# Commands currently running (THIS IS A BUG).")); break; case cs_deps_running: puts (_("# Dependencies commands running (THIS IS A BUG).")); break; case cs_not_started: puts (_("# Commands not yet started.")); break; case cs_finished: switch (p_target->update_status) { case us_success: puts (_("# Successfully updated.")); break; case us_none: puts (_("# No attempt to update has been made.")); break; case us_question: assert (question_flag); puts (_("# Needs to be updated (-q is set).")); break; case us_failed: puts (_("# Failed to be updated.")); break; default: puts (_("# Invalid value in `update_status' member!")); fflush (stdout); fflush (stderr); abort (); } break; default: puts (_("# Invalid value in `command_state' member!")); fflush (stdout); fflush (stderr); abort (); } } if (p_target->variables != 0 && i_mask & PRINT_TARGET_VARS) print_file_variables (p_target, i_mask & PRINT_TARGET_VARS_HASH); if (p_target->cmds != 0 && i_mask & PRINT_TARGET_CMDS) print_commands (p_target, p_target->cmds, false); if (p_target->cmds != 0 && i_mask & PRINT_TARGET_CMDS_EXP) print_commands (p_target, p_target->cmds, true); if (p_target->prev && i_mask & PRINT_TARGET_PREV) print_target_props (p_target->prev, i_mask); } /* Print the data base of files. */ void print_prereqs (const struct dep *deps) { const struct dep *ood = 0; /* Print all normal dependencies; note any order-only deps. */ for (; deps != 0; deps = deps->next) if (! deps->ignore_mtime) printf (" %s", dep_name (deps)); else if (! ood) ood = deps; /* Print order-only deps, if we have any. */ if (ood) { printf (" | %s", dep_name (ood)); for (ood = ood->next; ood != 0; ood = ood->next) if (ood->ignore_mtime) printf (" %s", dep_name (ood)); } putchar ('\n'); } static void print_file (const void *item) { const struct file *f = item; /* If we're not using builtin targets, don't show them. Ideally we'd be able to delete them altogether but currently there's no facility to ever delete a file once it's been added. */ if (no_builtin_rules_flag && f->builtin) return; putchar ('\n'); if (f->cmds && f->cmds->recipe_prefix != cmd_prefix) { fputs (".RECIPEPREFIX = ", stdout); cmd_prefix = f->cmds->recipe_prefix; if (cmd_prefix != RECIPEPREFIX_DEFAULT) putchar (cmd_prefix); putchar ('\n'); } if (f->variables != 0) print_target_variables (f); if (!f->is_target) puts (_("# Not a target:")); printf ("%s:%s", f->name, f->double_colon ? ":" : ""); print_prereqs (f->deps); if (f->precious) puts (_("# Precious file (prerequisite of .PRECIOUS).")); if (f->phony) puts (_("# Phony target (prerequisite of .PHONY).")); if (f->cmd_target) puts (_("# Command line target.")); if (f->dontcare) puts (_("# A default, MAKEFILES, or -include/sinclude makefile.")); if (f->builtin) puts (_("# Builtin rule")); puts (f->tried_implicit ? _("# Implicit rule search has been done.") : _("# Implicit rule search has not been done.")); if (f->stem != 0) printf (_("# Implicit/static pattern stem: '%s'\n"), f->stem); if (f->intermediate) puts (_("# File is an intermediate prerequisite.")); if (f->also_make != 0) { const struct dep *d; fputs (_("# Also makes:"), stdout); for (d = f->also_make; d != 0; d = d->next) printf (" %s", dep_name (d)); putchar ('\n'); } if (f->last_mtime == UNKNOWN_MTIME) puts (_("# Modification time never checked.")); else if (f->last_mtime == NONEXISTENT_MTIME) puts (_("# File does not exist.")); else if (f->last_mtime == OLD_MTIME) puts (_("# File is very old.")); else { char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; file_timestamp_sprintf (buf, f->last_mtime); printf (_("# Last modified %s\n"), buf); } puts (f->updated ? _("# File has been updated.") : _("# File has not been updated.")); switch (f->command_state) { case cs_running: puts (_("# Recipe currently running (THIS IS A BUG).")); break; case cs_deps_running: puts (_("# Dependencies recipe running (THIS IS A BUG).")); break; case cs_not_started: case cs_finished: switch (f->update_status) { case us_none: break; case us_success: puts (_("# Successfully updated.")); break; case us_question: assert (question_flag); puts (_("# Needs to be updated (-q is set).")); break; case us_failed: puts (_("# Failed to be updated.")); break; } break; default: puts (_("# Invalid value in 'command_state' member!")); fflush (stdout); fflush (stderr); abort (); } if (f->variables != 0) print_file_variables (f, 1); if (f->cmds != 0) { print_commands (NULL, f->cmds, false); // print_commands (p_target, p_target->cmds, false); } if (f->prev) print_file ((const void *) f->prev); } /*! Print the data base of files. */ void print_target (const void *item) { file_t *p_target = (file_t *) item; print_target_props(p_target, PRINT_TARGET_ALL); } void print_file_data_base (void) { puts (_("\n# Files")); hash_map (&files, print_file); fputs (_("\n# files hash-table stats:\n# "), stdout); hash_print_stats (&files, stdout); } /* Verify the integrity of the data base of files. */ #define VERIFY_CACHED(_p,_n) \ do{ \ if (_p->_n && _p->_n[0] && !strcache_iscached (_p->_n)) \ error (NULL, strlen (_p->name) + CSTRLEN (# _n) + strlen (_p->_n), \ _("%s: Field '%s' not cached: %s"), _p->name, # _n, _p->_n); \ }while(0) static void verify_file (const void *item) { const struct file *f = item; const struct dep *d; VERIFY_CACHED (f, name); VERIFY_CACHED (f, hname); VERIFY_CACHED (f, vpath); VERIFY_CACHED (f, stem); /* Check the deps. */ for (d = f->deps; d != 0; d = d->next) { if (! d->need_2nd_expansion) VERIFY_CACHED (d, name); VERIFY_CACHED (d, stem); } } void verify_file_data_base (void) { hash_map (&files, verify_file); } #define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500) char * build_target_list (char *value) { static unsigned long last_targ_count = 0; if (files.ht_fill != last_targ_count) { unsigned long max = EXPANSION_INCREMENT (strlen (value)); unsigned long len; char *p; struct file **fp = (struct file **) files.ht_vec; struct file **end = &fp[files.ht_size]; /* Make sure we have at least MAX bytes in the allocated buffer. */ value = xrealloc (value, max); p = value; len = 0; for (; fp < end; ++fp) if (!HASH_VACANT (*fp) && (*fp)->is_target) { struct file *f = *fp; int l = strlen (f->name); len += l + 1; if (len > max) { unsigned long off = p - value; max += EXPANSION_INCREMENT (l + 1); value = xrealloc (value, max); p = &value[off]; } memcpy (p, f->name, l); p += l; *(p++) = ' '; } *(p-1) = '\0'; last_targ_count = files.ht_fill; } return value; } /* EOF */ remake-4.1+dbg1.3~dfsg.1/file.h000066400000000000000000000052061317072305000160660ustar00rootroot00000000000000/* $Id: file.h,v 1.11 2006/03/30 05:01:49 rockyb Exp $ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file file.h * * \brief Definition of target file data structures for GNU Make. */ #ifndef FILE_H #define FILE_H #include "make.h" #include "types.h" #include "hash.h" extern struct hash_table files; /*! Free memory associated with p_file. */ void free_file (file_t *p_file); /*! Remove all nonprecious intermediate files. @param sig if is nonzero, this was caused by a fatal signal, meaning that a different message will be printed, and the message will go to stderr rather than stdout. */ void remove_intermediates (int sig); void init_hash_files (void); char *build_target_list (char *old_list); /*! Thing of the below as a bit mask rather than an enumeration and use print_target_mask; The enumeration is created be helpful in debuggers where wants just to refer to the PRINT_TARGET_ names and get something. */ typedef enum { PRINT_TARGET_NONORDER = 0x001, PRINT_TARGET_ORDER = 0x002, PRINT_TARGET_ATTRS = 0x004, PRINT_TARGET_TIME = 0x008, PRINT_TARGET_STATE = 0x010, PRINT_TARGET_VARS = 0x020, PRINT_TARGET_VARS_HASH = 0x040, PRINT_TARGET_CMDS = 0x080, PRINT_TARGET_PREV = 0x100, PRINT_TARGET_CMDS_EXP = 0x200, PRINT_TARGET_DEPEND = (PRINT_TARGET_ORDER|PRINT_TARGET_NONORDER), PRINT_TARGET_ALL = 0x0FF, } print_target_mask_t; /* The below variable is to make sure the enumerations are accessible in a debugger. */ extern print_target_mask_t debugger_enum_mask; /*! Print the data base of files. */ extern void print_target (const void *item); /*! Print some or all properties of the data base of files. */ extern void print_target_props (file_t *p_target, print_target_mask_t i_mask); /*! Expand and parse each dependency line. */ extern void expand_deps (file_t *f); #endif /*FILE_H*/ remake-4.1+dbg1.3~dfsg.1/file_basic.c000066400000000000000000000105221317072305000172170ustar00rootroot00000000000000/* Target file management for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include "filedef.h" #include "file.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "debug.h" #include "hash.h" struct hash_table files; extern unsigned long file_hash_1 (const void *key) { return_ISTRING_HASH_1 (((struct file const *) key)->hname); } extern unsigned long file_hash_2 (const void *key) { return_ISTRING_HASH_2 (((struct file const *) key)->hname); } extern int file_hash_cmp (const void *x, const void *y) { return_ISTRING_COMPARE (((struct file const *) x)->hname, ((struct file const *) y)->hname); } #ifndef FILE_BUCKETS #define FILE_BUCKETS 1007 #endif /* Access the hash table of all file records. lookup_file given a name, return the struct file * for that name, or nil if there is none. */ struct file * lookup_file (const char *name) { struct file *f; struct file file_key; #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) char *lname; #endif assert (*name != '\0'); /* This is also done in parse_file_seq, so this is redundant for names read from makefiles. It is here for names passed on the command line. */ #ifdef VMS # ifndef WANT_CASE_SENSITIVE_TARGETS if (*name != '.') { const char *n; char *ln; lname = xstrdup (name); for (n = name, ln = lname; *n != '\0'; ++n, ++ln) *ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n; *ln = '\0'; name = lname; } # endif while (name[0] == '[' && name[1] == ']' && name[2] != '\0') name += 2; #endif while (name[0] == '.' #ifdef HAVE_DOS_PATHS && (name[1] == '/' || name[1] == '\\') #else && name[1] == '/' #endif && name[2] != '\0') { name += 2; while (*name == '/' #ifdef HAVE_DOS_PATHS || *name == '\\' #endif ) /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } if (*name == '\0') /* It was all slashes after a dot. */ #if defined(VMS) name = "[]"; #elif defined(_AMIGA) name = ""; #else name = "./"; #endif file_key.hname = name; f = hash_find_item (&files, &file_key); #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) if (*name != '.') free (lname); #endif return f; } struct file * enter_file (const char *name) { struct file *f; struct file *new; struct file **file_slot; struct file file_key; assert (*name != '\0'); assert (! verify_flag || strcache_iscached (name)); #if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) if (*name != '.') { const char *n; char *lname, *ln; lname = xstrdup (name); for (n = name, ln = lname; *n != '\0'; ++n, ++ln) if (isupper ((unsigned char)*n)) *ln = tolower ((unsigned char)*n); else *ln = *n; *ln = '\0'; name = strcache_add (lname); free (lname); } #endif file_key.hname = name; file_slot = (struct file **) hash_find_slot (&files, &file_key); f = *file_slot; if (! HASH_VACANT (f) && !f->double_colon) { f->builtin = 0; return f; } new = xcalloc (sizeof (struct file)); new->name = new->hname = name; new->update_status = us_none; if (HASH_VACANT (f)) { new->last = new; hash_insert_at (&files, new, file_slot); } else { /* There is already a double-colon entry for this file. */ new->double_colon = f; f->last->prev = new; f->last = new; } return new; } void init_hash_files (void) { hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp); } remake-4.1+dbg1.3~dfsg.1/file_basic.h000066400000000000000000000004701317072305000172250ustar00rootroot00000000000000#include "filedef.h" extern unsigned long file_hash_1 (const void *key); extern unsigned long file_hash_2 (const void *key); extern int file_hash_cmp (const void *x, const void *y); extern void init_hash_files (void); extern file_t *lookup_file (const char *name); extern file_t *enter_file (const char *name); remake-4.1+dbg1.3~dfsg.1/filedef.h000066400000000000000000000253141317072305000165470ustar00rootroot00000000000000/* Definition of target file data structures for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* Structure that represents the info on one file that the makefile says how to make. All of these are chained together through 'next'. */ #ifndef _REMAKE_FILEDEF_H #define _REMAKE_FILEDEF_H #include "hash.h" #include "gnumake.h" #include "types.h" struct file { const char *name; const char *hname; /* Hashed filename */ const char *vpath; /* VPATH/vpath pathname */ gmk_floc floc; /* location in Makefile - for tracing */ uint64_t elapsed_time; /* Runtime in 100microsec to build target */ unsigned int nlines; /* Number of lines in file - for debugging. */ const char *description; /* Description of target taken from comment. Part after #: */ struct dep *deps; /* all dependencies, including duplicates */ struct commands *cmds; /* Commands to execute for this target. */ const char *stem; /* Implicit stem, if an implicit rule has been used */ struct dep *also_make; /* Targets that are made by making this. */ struct file *prev; /* Previous entry for same file name; used when there are multiple double-colon entries for the same file. */ struct file *last; /* Last entry for the same file name. */ /* File that this file was renamed to. After any time that a file could be renamed, call 'check_renamed' (below). */ struct file *renamed; /* List of variable sets used for this file. */ struct variable_set_list *variables; /* Pattern-specific variable reference for this target, or null if there isn't one. Also see the pat_searched flag, below. */ struct variable_set_list *pat_variables; /* Immediate dependent that caused this target to be remade, or nil if there isn't one. */ struct file *parent; /* For a double-colon entry, this is the first double-colon entry for the same file. Otherwise this is null. */ struct file *double_colon; FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */ FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating has been performed. */ int command_flags; /* Flags OR'd in for cmds; see commands.h. */ enum update_status /* Status of the last attempt to update. */ { us_success = 0, /* Successfully updated. Must be 0! */ us_none, /* No attempt to update has been made. */ us_question, /* Needs to be updated (-q is is set). */ us_failed /* Update failed. */ } update_status ENUM_BITFIELD (2); enum cmd_state /* State of the commands. */ { cs_not_started = 0, /* Not yet started. Must be 0! */ cs_deps_running, /* Dep commands running. */ cs_running, /* Commands running. */ cs_finished /* Commands finished. */ } command_state ENUM_BITFIELD (2); breakpoint_mask_t tracing; /* breakpoint status of target. */ unsigned int builtin:1; /* True if the file is a builtin rule. */ unsigned int precious:1; /* Non-0 means don't delete file on quit */ unsigned int loaded:1; /* True if the file is a loaded object. */ unsigned int low_resolution_time:1; /* Nonzero if this file's time stamp has only one-second resolution. */ unsigned int tried_implicit:1; /* Nonzero if have searched for implicit rule for making this file; don't search again. */ unsigned int updating:1; /* Nonzero while updating deps of this file */ unsigned int updated:1; /* Nonzero if this file has been remade. */ unsigned int is_target:1; /* Nonzero if file is described as target. */ unsigned int cmd_target:1; /* Nonzero if file was given on cmd line. */ unsigned int phony:1; /* Nonzero if this is a phony file i.e., a prerequisite of .PHONY. */ unsigned int intermediate:1;/* Nonzero if this is an intermediate file. */ unsigned int secondary:1; /* Nonzero means remove_intermediates should not delete it. */ unsigned int dontcare:1; /* Nonzero if no complaint is to be made if this target cannot be remade. */ unsigned int ignore_vpath:1;/* Nonzero if we threw out VPATH name. */ unsigned int pat_searched:1;/* Nonzero if we already searched for pattern-specific variables. */ unsigned int considered:1; /* equal to 'considered' if file has been considered on current scan of goal chain */ unsigned int no_diag:1; /* True if the file failed to update and no diagnostics has been issued (dontcare). */ unsigned int file_profiled:1; /* True if --profile has been set and we have emitted a callgrind file line. */ }; extern struct file *suffix_file, *default_file; struct file *lookup_file (const char *name); struct file *enter_file (const char *name); struct dep *split_prereqs (char *prereqstr); struct dep *enter_prereqs (struct dep *prereqs, const char *stem); void remove_intermediates (int sig); void snap_deps (void); void rename_file (struct file *file, const char *name); void rehash_file (struct file *file, const char *name); void set_command_state (struct file *file, enum cmd_state state); void notice_finished_file (struct file *file); void init_hash_files (void); char *build_target_list (char *old_list); void print_prereqs (const struct dep *deps); void print_file_data_base (void); #if FILE_TIMESTAMP_HI_RES # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, (st).ST_MTIM_NSEC) #else # define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ file_timestamp_cons (fname, (st).st_mtime, 0) #endif /* If FILE_TIMESTAMP is 64 bits (or more), use nanosecond resolution. (Multiply by 2**30 instead of by 10**9 to save time at the cost of slightly decreasing the number of available timestamps.) With 64-bit FILE_TIMESTAMP, this stops working on 2514-05-30 01:53:04 UTC, but by then uintmax_t should be larger than 64 bits. */ #define FILE_TIMESTAMPS_PER_S (FILE_TIMESTAMP_HI_RES ? 1000000000 : 1) #define FILE_TIMESTAMP_LO_BITS (FILE_TIMESTAMP_HI_RES ? 30 : 0) #define FILE_TIMESTAMP_S(ts) (((ts) - ORDINARY_MTIME_MIN) \ >> FILE_TIMESTAMP_LO_BITS) #define FILE_TIMESTAMP_NS(ts) ((int) (((ts) - ORDINARY_MTIME_MIN) \ & ((1 << FILE_TIMESTAMP_LO_BITS) - 1))) /* Upper bound on length of string "YYYY-MM-DD HH:MM:SS.NNNNNNNNN" representing a file timestamp. The upper bound is not necessarily 29, since the year might be less than -999 or greater than 9999. Subtract one for the sign bit if in case file timestamps can be negative; subtract FLOOR_LOG2_SECONDS_PER_YEAR to yield an upper bound on how many file timestamp bits might affect the year; 302 / 1000 is log10 (2) rounded up; add one for integer division truncation; add one more for a minus sign if file timestamps can be negative; add 4 to allow for any 4-digit epoch year (e.g. 1970); add 25 to allow for "-MM-DD HH:MM:SS.NNNNNNNNN". */ #define FLOOR_LOG2_SECONDS_PER_YEAR 24 #define FILE_TIMESTAMP_PRINT_LEN_BOUND \ (((sizeof (FILE_TIMESTAMP) * CHAR_BIT - 1 - FLOOR_LOG2_SECONDS_PER_YEAR) \ * 302 / 1000) \ + 1 + 1 + 4 + 25) /** Convert an external file timestamp to internal form. */ extern FILE_TIMESTAMP file_timestamp_cons (char const *, time_t, long int); /** Return the current time as a file timestamp, setting *RESOLUTION to its resolution. */ extern FILE_TIMESTAMP file_timestamp_now (int *); /** Place into the buffer P a printable representation of the file timestamp TS. @param p output buffer for printable timestamp @param ts timestamp to convert. */ void file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts); /* Return the mtime of file F (a struct file *), caching it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime(f) file_mtime_1 ((f), 1) /* Return the mtime of file F (a struct file *), caching it. Don't search using vpath for the file--if it doesn't actually exist, we don't find it. The value is NONEXISTENT_MTIME if the file does not exist. */ #define file_mtime_no_search(f) file_mtime_1 ((f), 0) FILE_TIMESTAMP f_mtime (struct file *file, int search); #define file_mtime_1(f, v) \ ((f)->last_mtime == UNKNOWN_MTIME ? f_mtime ((f), v) : (f)->last_mtime) /* Special timestamp values. */ /* The file's timestamp is not yet known. */ #define UNKNOWN_MTIME 0 /* The file does not exist. */ #define NONEXISTENT_MTIME 1 /* The file does not exist, and we assume that it is older than any actual file. */ #define OLD_MTIME 2 /* The smallest and largest ordinary timestamps. */ #define ORDINARY_MTIME_MIN (OLD_MTIME + 1) #define ORDINARY_MTIME_MAX ((FILE_TIMESTAMP_S (NEW_MTIME) \ << FILE_TIMESTAMP_LO_BITS) \ + ORDINARY_MTIME_MIN + FILE_TIMESTAMPS_PER_S - 1) /* Modtime value to use for 'infinitely new'. We used to get the current time from the system and use that whenever we wanted 'new'. But that causes trouble when the machine running make and the machine holding a file have different ideas about what time it is; and can also lose for 'force' targets, which need to be considered newer than anything that depends on them, even if said dependents' modtimes are in the future. */ #define NEW_MTIME INTEGER_TYPE_MAXIMUM (FILE_TIMESTAMP) #define check_renamed(file) \ while ((file)->renamed != 0) (file) = (file)->renamed /* No ; here. */ /* Have we snapped deps yet? */ extern int snapped_deps; #endif /*FILEDEF_H*/ remake-4.1+dbg1.3~dfsg.1/function.c000066400000000000000000002065421317072305000167750ustar00rootroot00000000000000/* Builtin function expansion for GNU Make. Copyright (C) 1988-2016 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "expand.h" #include "variable.h" #include "dep.h" #include "job.h" #include "commands.h" #include "debug.h" #include "debugger/cmd.h" struct function_table_entry { union { char *(*func_ptr) (char *output, char **argv, const char *fname); gmk_func_ptr alloc_func_ptr; } fptr; const char *name; unsigned char len; unsigned char minimum_args; unsigned char maximum_args; unsigned char expand_args:1; unsigned char alloc_fn:1; }; static unsigned long function_table_entry_hash_1 (const void *keyv) { const struct function_table_entry *key = keyv; return_STRING_N_HASH_1 (key->name, key->len); } static unsigned long function_table_entry_hash_2 (const void *keyv) { const struct function_table_entry *key = keyv; return_STRING_N_HASH_2 (key->name, key->len); } static int function_table_entry_hash_cmp (const void *xv, const void *yv) { const struct function_table_entry *x = xv; const struct function_table_entry *y = yv; int result = x->len - y->len; if (result) return result; return_STRING_N_COMPARE (x->name, y->name, x->len); } static struct hash_table function_table; /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing each occurrence of SUBST with REPLACE. TEXT is null-terminated. SLEN is the length of SUBST and RLEN is the length of REPLACE. If BY_WORD is nonzero, substitutions are done only on matches which are complete whitespace-delimited words. */ char * subst_expand (char *o, const char *text, const char *subst, const char *replace, unsigned int slen, unsigned int rlen, int by_word) { const char *t = text; const char *p; if (slen == 0 && !by_word) { /* The first occurrence of "" in any string is its end. */ o = variable_buffer_output (o, t, strlen (t)); if (rlen > 0) o = variable_buffer_output (o, replace, rlen); return o; } do { if (by_word && slen == 0) /* When matching by words, the empty string should match the end of each word, rather than the end of the whole text. */ p = end_of_token (next_token (t)); else { p = strstr (t, subst); if (p == 0) { /* No more matches. Output everything left on the end. */ o = variable_buffer_output (o, t, strlen (t)); return o; } } /* Output everything before this occurrence of the string to replace. */ if (p > t) o = variable_buffer_output (o, t, p - t); /* If we're substituting only by fully matched words, or only at the ends of words, check that this case qualifies. */ if (by_word && ((p > text && !isblank ((unsigned char)p[-1])) || ! STOP_SET (p[slen], MAP_BLANK|MAP_NUL))) /* Struck out. Output the rest of the string that is no longer to be replaced. */ o = variable_buffer_output (o, subst, slen); else if (rlen > 0) /* Output the replacement string. */ o = variable_buffer_output (o, replace, rlen); /* Advance T past the string to be replaced. */ t = p + slen; } while (*t != '\0'); return o; } /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing strings matching PATTERN with REPLACE. If PATTERN_PERCENT is not nil, PATTERN has already been run through find_percent, and PATTERN_PERCENT is the result. If REPLACE_PERCENT is not nil, REPLACE has already been run through find_percent, and REPLACE_PERCENT is the result. Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the character _AFTER_ the %, not to the % itself. */ char * patsubst_expand_pat (char *o, const char *text, const char *pattern, const char *replace, const char *pattern_percent, const char *replace_percent) { unsigned int pattern_prepercent_len, pattern_postpercent_len; unsigned int replace_prepercent_len, replace_postpercent_len; const char *t; unsigned int len; int doneany = 0; /* Record the length of REPLACE before and after the % so we don't have to compute these lengths more than once. */ if (replace_percent) { replace_prepercent_len = replace_percent - replace - 1; replace_postpercent_len = strlen (replace_percent); } else { replace_prepercent_len = strlen (replace); replace_postpercent_len = 0; } if (!pattern_percent) /* With no % in the pattern, this is just a simple substitution. */ return subst_expand (o, text, pattern, replace, strlen (pattern), strlen (replace), 1); /* Record the length of PATTERN before and after the % so we don't have to compute it more than once. */ pattern_prepercent_len = pattern_percent - pattern - 1; pattern_postpercent_len = strlen (pattern_percent); while ((t = find_next_token (&text, &len)) != 0) { int fail = 0; /* Is it big enough to match? */ if (len < pattern_prepercent_len + pattern_postpercent_len) fail = 1; /* Does the prefix match? */ if (!fail && pattern_prepercent_len > 0 && (*t != *pattern || t[pattern_prepercent_len - 1] != pattern_percent[-2] || !strneq (t + 1, pattern + 1, pattern_prepercent_len - 1))) fail = 1; /* Does the suffix match? */ if (!fail && pattern_postpercent_len > 0 && (t[len - 1] != pattern_percent[pattern_postpercent_len - 1] || t[len - pattern_postpercent_len] != *pattern_percent || !strneq (&t[len - pattern_postpercent_len], pattern_percent, pattern_postpercent_len - 1))) fail = 1; if (fail) /* It didn't match. Output the string. */ o = variable_buffer_output (o, t, len); else { /* It matched. Output the replacement. */ /* Output the part of the replacement before the %. */ o = variable_buffer_output (o, replace, replace_prepercent_len); if (replace_percent != 0) { /* Output the part of the matched string that matched the % in the pattern. */ o = variable_buffer_output (o, t + pattern_prepercent_len, len - (pattern_prepercent_len + pattern_postpercent_len)); /* Output the part of the replacement after the %. */ o = variable_buffer_output (o, replace_percent, replace_postpercent_len); } } /* Output a space, but not if the replacement is "". */ if (fail || replace_prepercent_len > 0 || (replace_percent != 0 && len + replace_postpercent_len > 0)) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } if (doneany) /* Kill the last space. */ --o; return o; } /* Store into VARIABLE_BUFFER at O the result of scanning TEXT and replacing strings matching PATTERN with REPLACE. If PATTERN_PERCENT is not nil, PATTERN has already been run through find_percent, and PATTERN_PERCENT is the result. If REPLACE_PERCENT is not nil, REPLACE has already been run through find_percent, and REPLACE_PERCENT is the result. Note that we expect PATTERN_PERCENT and REPLACE_PERCENT to point to the character _AFTER_ the %, not to the % itself. */ char * patsubst_expand (char *o, const char *text, char *pattern, char *replace) { const char *pattern_percent = find_percent (pattern); const char *replace_percent = find_percent (replace); /* If there's a percent in the pattern or replacement skip it. */ if (replace_percent) ++replace_percent; if (pattern_percent) ++pattern_percent; return patsubst_expand_pat (o, text, pattern, replace, pattern_percent, replace_percent); } /* Look up a function by name. */ static const struct function_table_entry * lookup_function (const char *s) { struct function_table_entry function_table_entry_key; const char *e = s; while (STOP_SET (*e, MAP_USERFUNC)) e++; if (e == s || !STOP_SET(*e, MAP_NUL|MAP_SPACE)) return NULL; function_table_entry_key.name = s; function_table_entry_key.len = e - s; return hash_find_item (&function_table, &function_table_entry_key); } /* Return 1 if PATTERN matches STR, 0 if not. */ int pattern_matches (const char *pattern, const char *percent, const char *str) { unsigned int sfxlen, strlength; if (percent == 0) { unsigned int len = strlen (pattern) + 1; char *new_chars = alloca (len); memcpy (new_chars, pattern, len); percent = find_percent (new_chars); if (percent == 0) return streq (new_chars, str); pattern = new_chars; } sfxlen = strlen (percent + 1); strlength = strlen (str); if (strlength < (percent - pattern) + sfxlen || !strneq (pattern, str, percent - pattern)) return 0; return !strcmp (percent + 1, str + (strlength - sfxlen)); } /* Find the next comma or ENDPAREN (counting nested STARTPAREN and ENDPARENtheses), starting at PTR before END. Return a pointer to next character. If no next argument is found, return NULL. */ static char * find_next_argument (char startparen, char endparen, const char *ptr, const char *end) { int count = 0; for (; ptr < end; ++ptr) if (*ptr == startparen) ++count; else if (*ptr == endparen) { --count; if (count < 0) return NULL; } else if (*ptr == ',' && !count) return (char *)ptr; /* We didn't find anything. */ return NULL; } /* Glob-expand LINE. The returned pointer is only good until the next call to string_glob. */ static char * string_glob (char *line) { static char *result = 0; static unsigned int length; struct nameseq *chain; unsigned int idx; chain = PARSE_FILE_SEQ (&line, struct nameseq, MAP_NUL, NULL, /* We do not want parse_file_seq to strip './'s. That would break examples like: $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ PARSEFS_NOSTRIP|PARSEFS_NOCACHE|PARSEFS_EXISTS); if (result == 0) { length = 100; result = xmalloc (100); } idx = 0; while (chain != 0) { struct nameseq *next = chain->next; unsigned int len = strlen (chain->name); if (idx + len + 1 > length) { length += (len + 1) * 2; result = xrealloc (result, length); } memcpy (&result[idx], chain->name, len); idx += len; result[idx++] = ' '; /* Because we used PARSEFS_NOCACHE above, we have to free() NAME. */ free ((char *)chain->name); free (chain); chain = next; } /* Kill the last space and terminate the string. */ if (idx == 0) result[0] = '\0'; else result[idx - 1] = '\0'; return result; } /* Builtin functions */ static char * func_patsubst (char *o, char **argv, const char *funcname UNUSED) { o = patsubst_expand (o, argv[2], argv[0], argv[1]); return o; } static char * func_join (char *o, char **argv, const char *funcname UNUSED) { int doneany = 0; /* Write each word of the first argument directly followed by the corresponding word of the second argument. If the two arguments have a different number of words, the excess words are just output separated by blanks. */ const char *tp; const char *pp; const char *list1_iterator = argv[0]; const char *list2_iterator = argv[1]; do { unsigned int len1, len2; tp = find_next_token (&list1_iterator, &len1); if (tp != 0) o = variable_buffer_output (o, tp, len1); pp = find_next_token (&list2_iterator, &len2); if (pp != 0) o = variable_buffer_output (o, pp, len2); if (tp != 0 || pp != 0) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } while (tp != 0 || pp != 0); if (doneany) /* Kill the last blank. */ --o; return o; } static char * func_origin (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ struct variable *v = lookup_variable (argv[0], strlen (argv[0])); if (v == 0) o = variable_buffer_output (o, "undefined", 9); else switch (v->origin) { default: case o_invalid: abort (); break; case o_default: o = variable_buffer_output (o, "default", 7); break; case o_env: o = variable_buffer_output (o, "environment", 11); break; case o_file: o = variable_buffer_output (o, "file", 4); break; case o_env_override: o = variable_buffer_output (o, "environment override", 20); break; case o_command: o = variable_buffer_output (o, "command line", 12); break; case o_override: o = variable_buffer_output (o, "override", 8); break; case o_automatic: o = variable_buffer_output (o, "automatic", 9); break; } return o; } static char * func_flavor (char *o, char **argv, const char *funcname UNUSED) { struct variable *v = lookup_variable (argv[0], strlen (argv[0])); if (v == 0) o = variable_buffer_output (o, "undefined", 9); else if (v->recursive) o = variable_buffer_output (o, "recursive", 9); else o = variable_buffer_output (o, "simple", 6); return o; } static char * func_notdir_suffix (char *o, char **argv, const char *funcname) { /* Expand the argument. */ const char *list_iterator = argv[0]; const char *p2; int doneany =0; unsigned int len=0; int is_suffix = funcname[0] == 's'; int is_notdir = !is_suffix; int stop = MAP_DIRSEP | (is_suffix ? MAP_DOT : 0); #ifdef VMS /* For VMS list_iterator points to a comma separated list. To use the common [find_]next_token, create a local copy and replace the commas with spaces. Obviously, there is a problem if there is a ',' in the VMS filename (can only happen on ODS5), the same problem as with spaces in filenames, which seems to be present in make on all platforms. */ char *vms_list_iterator = alloca(strlen(list_iterator) + 1); int i; for (i = 0; list_iterator[i]; i++) if (list_iterator[i] == ',') vms_list_iterator[i] = ' '; else vms_list_iterator[i] = list_iterator[i]; vms_list_iterator[i] = list_iterator[i]; while ((p2 = find_next_token((const char**) &vms_list_iterator, &len)) != 0) #else while ((p2 = find_next_token (&list_iterator, &len)) != 0) #endif { const char *p = p2 + len - 1; while (p >= p2 && ! STOP_SET (*p, stop)) --p; if (p >= p2) { if (is_notdir) ++p; else if (*p != '.') continue; o = variable_buffer_output (o, p, len - (p - p2)); } #ifdef HAVE_DOS_PATHS /* Handle the case of "d:foo/bar". */ else if (is_notdir && p2[0] && p2[1] == ':') { p = p2 + 2; o = variable_buffer_output (o, p, len - (p - p2)); } #endif else if (is_notdir) o = variable_buffer_output (o, p2, len); if (is_notdir || p >= p2) { o = variable_buffer_output (o, " ", 1); doneany = 1; } } if (doneany) /* Kill last space. */ --o; return o; } static char * func_basename_dir (char *o, char **argv, const char *funcname) { /* Expand the argument. */ const char *p3 = argv[0]; const char *p2; int doneany = 0; unsigned int len = 0; int is_basename = funcname[0] == 'b'; int is_dir = !is_basename; int stop = MAP_DIRSEP | (is_basename ? MAP_DOT : 0) | MAP_NUL; while ((p2 = find_next_token (&p3, &len)) != 0) { const char *p = p2 + len - 1; while (p >= p2 && ! STOP_SET (*p, stop)) --p; if (p >= p2 && (is_dir)) o = variable_buffer_output (o, p2, ++p - p2); else if (p >= p2 && (*p == '.')) o = variable_buffer_output (o, p2, p - p2); #ifdef HAVE_DOS_PATHS /* Handle the "d:foobar" case */ else if (p2[0] && p2[1] == ':' && is_dir) o = variable_buffer_output (o, p2, 2); #endif else if (is_dir) o = variable_buffer_output (o, "./", 2); else /* The entire name is the basename. */ o = variable_buffer_output (o, p2, len); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill last space. */ --o; return o; } static char * func_addsuffix_addprefix (char *o, char **argv, const char *funcname) { int fixlen = strlen (argv[0]); const char *list_iterator = argv[1]; int is_addprefix = funcname[3] == 'p'; int is_addsuffix = !is_addprefix; int doneany = 0; const char *p; unsigned int len; while ((p = find_next_token (&list_iterator, &len)) != 0) { if (is_addprefix) o = variable_buffer_output (o, argv[0], fixlen); o = variable_buffer_output (o, p, len); if (is_addsuffix) o = variable_buffer_output (o, argv[0], fixlen); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill last space. */ --o; return o; } static char * func_subst (char *o, char **argv, const char *funcname UNUSED) { o = subst_expand (o, argv[2], argv[0], argv[1], strlen (argv[0]), strlen (argv[1]), 0); return o; } static char * func_firstword (char *o, char **argv, const char *funcname UNUSED) { unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p = find_next_token (&words, &i); if (p != 0) o = variable_buffer_output (o, p, i); return o; } static char * func_lastword (char *o, char **argv, const char *funcname UNUSED) { unsigned int i; const char *words = argv[0]; /* Use a temp variable for find_next_token */ const char *p = NULL; const char *t; while ((t = find_next_token (&words, &i))) p = t; if (p != 0) o = variable_buffer_output (o, p, i); return o; } static char * func_words (char *o, char **argv, const char *funcname UNUSED) { int i = 0; const char *word_iterator = argv[0]; char buf[20]; while (find_next_token (&word_iterator, NULL) != 0) ++i; sprintf (buf, "%d", i); o = variable_buffer_output (o, buf, strlen (buf)); return o; } /* Set begpp to point to the first non-whitespace character of the string, * and endpp to point to the last non-whitespace character of the string. * If the string is empty or contains nothing but whitespace, endpp will be * begpp-1. */ char * strip_whitespace (const char **begpp, const char **endpp) { while (*begpp <= *endpp && isspace ((unsigned char)**begpp)) (*begpp) ++; while (*endpp >= *begpp && isspace ((unsigned char)**endpp)) (*endpp) --; return (char *)*begpp; } static void check_numeric (const char *s, const char *msg) { const char *end = s + strlen (s) - 1; const char *beg = s; strip_whitespace (&s, &end); for (; s <= end; ++s) if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see makeint.h. */ break; if (s <= end || end - beg < 0) OSS (fatal, *expanding_var, "%s: '%s'", msg, beg); } static char * func_word (char *o, char **argv, const char *funcname UNUSED) { const char *end_p; const char *p; int i; /* Check the first argument. */ check_numeric (argv[0], _("non-numeric first argument to 'word' function")); i = atoi (argv[0]); if (i == 0) O (fatal, *expanding_var, _("first argument to 'word' function must be greater than 0")); end_p = argv[1]; while ((p = find_next_token (&end_p, 0)) != 0) if (--i == 0) break; if (i == 0) o = variable_buffer_output (o, p, end_p - p); return o; } static char * func_wordlist (char *o, char **argv, const char *funcname UNUSED) { int start, count; /* Check the arguments. */ check_numeric (argv[0], _("non-numeric first argument to 'wordlist' function")); check_numeric (argv[1], _("non-numeric second argument to 'wordlist' function")); start = atoi (argv[0]); if (start < 1) ON (fatal, *expanding_var, "invalid first argument to 'wordlist' function: '%d'", start); count = atoi (argv[1]) - start + 1; if (count > 0) { const char *p; const char *end_p = argv[2]; /* Find the beginning of the "start"th word. */ while (((p = find_next_token (&end_p, 0)) != 0) && --start) ; if (p) { /* Find the end of the "count"th word from start. */ while (--count && (find_next_token (&end_p, 0) != 0)) ; /* Return the stuff in the middle. */ o = variable_buffer_output (o, p, end_p - p); } } return o; } static char * func_findstring (char *o, char **argv, const char *funcname UNUSED) { /* Find the first occurrence of the first string in the second. */ if (strstr (argv[1], argv[0]) != 0) o = variable_buffer_output (o, argv[0], strlen (argv[0])); return o; } static char * func_foreach (char *o, char **argv, const char *funcname UNUSED) { /* expand only the first two. */ char *varname = expand_argument (argv[0], NULL); char *list = expand_argument (argv[1], NULL); const char *body = argv[2]; int doneany = 0; const char *list_iterator = list; const char *p; unsigned int len; struct variable *var; push_new_variable_scope (); var = define_variable (varname, strlen (varname), "", o_automatic, 0); /* loop through LIST, put the value in VAR and expand BODY */ while ((p = find_next_token (&list_iterator, &len)) != 0) { char *result = 0; free (var->value); var->value = xstrndup (p, len); result = allocated_variable_expand (body); o = variable_buffer_output (o, result, strlen (result)); o = variable_buffer_output (o, " ", 1); doneany = 1; free (result); } if (doneany) /* Kill the last space. */ --o; pop_variable_scope (); free (varname); free (list); return o; } struct a_word { struct a_word *next; struct a_word *chain; char *str; int length; int matched; }; static unsigned long a_word_hash_1 (const void *key) { return_STRING_HASH_1 (((struct a_word const *) key)->str); } static unsigned long a_word_hash_2 (const void *key) { return_STRING_HASH_2 (((struct a_word const *) key)->str); } static int a_word_hash_cmp (const void *x, const void *y) { int result = ((struct a_word const *) x)->length - ((struct a_word const *) y)->length; if (result) return result; return_STRING_COMPARE (((struct a_word const *) x)->str, ((struct a_word const *) y)->str); } struct a_pattern { struct a_pattern *next; char *str; char *percent; int length; }; static char * func_filter_filterout (char *o, char **argv, const char *funcname) { struct a_word *wordhead; struct a_word **wordtail; struct a_word *wp; struct a_pattern *pathead; struct a_pattern **pattail; struct a_pattern *pp; struct hash_table a_word_table; int is_filter = funcname[CSTRLEN ("filter")] == '\0'; const char *pat_iterator = argv[0]; const char *word_iterator = argv[1]; int literals = 0; int words = 0; int hashing = 0; char *p; unsigned int len; /* Chop ARGV[0] up into patterns to match against the words. We don't need to preserve it because our caller frees all the argument memory anyway. */ pattail = &pathead; while ((p = find_next_token (&pat_iterator, &len)) != 0) { struct a_pattern *pat = alloca (sizeof (struct a_pattern)); *pattail = pat; pattail = &pat->next; if (*pat_iterator != '\0') ++pat_iterator; pat->str = p; p[len] = '\0'; pat->percent = find_percent (p); if (pat->percent == 0) literals++; /* find_percent() might shorten the string so LEN is wrong. */ pat->length = strlen (pat->str); } *pattail = 0; /* Chop ARGV[1] up into words to match against the patterns. */ wordtail = &wordhead; while ((p = find_next_token (&word_iterator, &len)) != 0) { struct a_word *word = alloca (sizeof (struct a_word)); *wordtail = word; wordtail = &word->next; if (*word_iterator != '\0') ++word_iterator; p[len] = '\0'; word->str = p; word->length = len; word->matched = 0; word->chain = 0; words++; } *wordtail = 0; /* Only use a hash table if arg list lengths justifies the cost. */ hashing = (literals >= 2 && (literals * words) >= 10); if (hashing) { hash_init (&a_word_table, words, a_word_hash_1, a_word_hash_2, a_word_hash_cmp); for (wp = wordhead; wp != 0; wp = wp->next) { struct a_word *owp = hash_insert (&a_word_table, wp); if (owp) wp->chain = owp; } } if (words) { int doneany = 0; /* Run each pattern through the words, killing words. */ for (pp = pathead; pp != 0; pp = pp->next) { if (pp->percent) for (wp = wordhead; wp != 0; wp = wp->next) wp->matched |= pattern_matches (pp->str, pp->percent, wp->str); else if (hashing) { struct a_word a_word_key; a_word_key.str = pp->str; a_word_key.length = pp->length; wp = hash_find_item (&a_word_table, &a_word_key); while (wp) { wp->matched |= 1; wp = wp->chain; } } else for (wp = wordhead; wp != 0; wp = wp->next) wp->matched |= (wp->length == pp->length && strneq (pp->str, wp->str, wp->length)); } /* Output the words that matched (or didn't, for filter-out). */ for (wp = wordhead; wp != 0; wp = wp->next) if (is_filter ? wp->matched : !wp->matched) { o = variable_buffer_output (o, wp->str, strlen (wp->str)); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill the last space. */ --o; } if (hashing) hash_free (&a_word_table, 0); return o; } static char * func_strip (char *o, char **argv, const char *funcname UNUSED) { const char *p = argv[0]; int doneany = 0; while (*p != '\0') { int i=0; const char *word_start; while (isspace ((unsigned char)*p)) ++p; word_start = p; for (i=0; *p != '\0' && !isspace ((unsigned char)*p); ++p, ++i) {} if (!i) break; o = variable_buffer_output (o, word_start, i); o = variable_buffer_output (o, " ", 1); doneany = 1; } if (doneany) /* Kill the last space. */ --o; return o; } /* Print a warning or fatal message. */ static char * func_error (char *o, char **argv, const char *funcname) { char **argvp; char *msg, *p; int len; /* The arguments will be broken on commas. Rather than create yet another special case where function arguments aren't broken up, just create a format string that puts them back together. */ for (len=0, argvp=argv; *argvp != 0; ++argvp) len += strlen (*argvp) + 2; p = msg = alloca (len + 1); for (argvp=argv; argvp[1] != 0; ++argvp) { strcpy (p, *argvp); p += strlen (*argvp); *(p++) = ','; *(p++) = ' '; } strcpy (p, *argvp); switch (*funcname) { case 'e': OS (fatal, reading_file, "%s", msg); case 'w': OS (error, reading_file, "%s", msg); break; case 'i': outputs (0, msg); outputs (0, "\n"); break; default: OS (fatal, *expanding_var, "Internal error: func_error: '%s'", funcname); } /* The warning function expands to the empty string. */ return o; } /* chop argv[0] into words, and sort them. */ static char * func_sort (char *o, char **argv, const char *funcname UNUSED) { const char *t; char **words; int wordi; char *p; unsigned int len; /* Find the maximum number of words we'll have. */ t = argv[0]; wordi = 0; while ((p = find_next_token (&t, NULL)) != 0) { ++t; ++wordi; } words = xmalloc ((wordi == 0 ? 1 : wordi) * sizeof (char *)); /* Now assign pointers to each string in the array. */ t = argv[0]; wordi = 0; while ((p = find_next_token (&t, &len)) != 0) { ++t; p[len] = '\0'; words[wordi++] = p; } if (wordi) { int i; /* Now sort the list of words. */ qsort (words, wordi, sizeof (char *), alpha_compare); /* Now write the sorted list, uniquified. */ for (i = 0; i < wordi; ++i) { len = strlen (words[i]); if (i == wordi - 1 || strlen (words[i + 1]) != len || strcmp (words[i], words[i + 1])) { o = variable_buffer_output (o, words[i], len); o = variable_buffer_output (o, " ", 1); } } /* Kill the last space. */ --o; } free (words); return o; } /* $(if condition,true-part[,false-part]) CONDITION is false iff it evaluates to an empty string. White space before and after condition are stripped before evaluation. If CONDITION is true, then TRUE-PART is evaluated, otherwise FALSE-PART is evaluated (if it exists). Because only one of the two PARTs is evaluated, you can use $(if ...) to create side-effects (with $(shell ...), for example). */ static char * func_if (char *o, char **argv, const char *funcname UNUSED) { const char *begp = argv[0]; const char *endp = begp + strlen (argv[0]) - 1; int result = 0; /* Find the result of the condition: if we have a value, and it's not empty, the condition is true. If we don't have a value, or it's the empty string, then it's false. */ strip_whitespace (&begp, &endp); if (begp <= endp) { char *expansion = expand_argument (begp, endp+1); result = strlen (expansion); free (expansion); } /* If the result is true (1) we want to eval the first argument, and if it's false (0) we want to eval the second. If the argument doesn't exist we do nothing, otherwise expand it and add to the buffer. */ argv += 1 + !result; if (*argv) { char *expansion = expand_argument (*argv, NULL); o = variable_buffer_output (o, expansion, strlen (expansion)); free (expansion); } return o; } /* $(or condition1[,condition2[,condition3[...]]]) A CONDITION is false iff it evaluates to an empty string. White space before and after CONDITION are stripped before evaluation. CONDITION1 is evaluated. If it's true, then this is the result of expansion. If it's false, CONDITION2 is evaluated, and so on. If none of the conditions are true, the expansion is the empty string. Once a CONDITION is true no further conditions are evaluated (short-circuiting). */ static char * func_or (char *o, char **argv, const char *funcname UNUSED) { for ( ; *argv ; ++argv) { const char *begp = *argv; const char *endp = begp + strlen (*argv) - 1; char *expansion; int result = 0; /* Find the result of the condition: if it's false keep going. */ strip_whitespace (&begp, &endp); if (begp > endp) continue; expansion = expand_argument (begp, endp+1); result = strlen (expansion); /* If the result is false keep going. */ if (!result) { free (expansion); continue; } /* It's true! Keep this result and return. */ o = variable_buffer_output (o, expansion, result); free (expansion); break; } return o; } /* $(and condition1[,condition2[,condition3[...]]]) A CONDITION is false iff it evaluates to an empty string. White space before and after CONDITION are stripped before evaluation. CONDITION1 is evaluated. If it's false, then this is the result of expansion. If it's true, CONDITION2 is evaluated, and so on. If all of the conditions are true, the expansion is the result of the last condition. Once a CONDITION is false no further conditions are evaluated (short-circuiting). */ static char * func_and (char *o, char **argv, const char *funcname UNUSED) { char *expansion; while (1) { const char *begp = *argv; const char *endp = begp + strlen (*argv) - 1; int result; /* An empty condition is always false. */ strip_whitespace (&begp, &endp); if (begp > endp) return o; expansion = expand_argument (begp, endp+1); result = strlen (expansion); /* If the result is false, stop here: we're done. */ if (!result) break; /* Otherwise the result is true. If this is the last one, keep this result and quit. Otherwise go on to the next one! */ if (*(++argv)) free (expansion); else { o = variable_buffer_output (o, expansion, result); break; } } free (expansion); return o; } static char * func_wildcard (char *o, char **argv, const char *funcname UNUSED) { #ifdef _AMIGA o = wildcard_expansion (argv[0], o); #else char *p = string_glob (argv[0]); o = variable_buffer_output (o, p, strlen (p)); #endif return o; } /* $(eval ) Always resolves to the empty string. Treat the arguments as a segment of makefile, and parse them. */ char * func_eval (char *o, char **argv, const char *funcname UNUSED) { char *buf; unsigned int len; /* Eval the buffer. Pop the current variable buffer setting so that the eval'd code can use its own without conflicting. */ install_variable_buffer (&buf, &len); eval_buffer (argv[0], NULL); restore_variable_buffer (buf, len); return o; } /* $(debugger ) Always resolves to the empty string. Treat the arguments as a segment of makefile, and parse them. */ static char * func_debugger (char *o, char **argv UNUSED, const char *funcname UNUSED) { debug_return_t rc; static char buffer[10]; rc = enter_debugger(p_stack_top, NULL, 0, DEBUG_EXPLICIT_CALL); snprintf(buffer, sizeof(buffer), "%d", rc); o = buffer; return o; } static char * func_value (char *o, char **argv, const char *funcname UNUSED) { /* Look up the variable. */ struct variable *v = lookup_variable (argv[0], strlen (argv[0])); /* Copy its value into the output buffer without expanding it. */ if (v) o = variable_buffer_output (o, v->value, strlen (v->value)); return o; } /* \r is replaced on UNIX as well. Is this desirable? */ static void fold_newlines (char *buffer, unsigned int *length, int trim_newlines) { char *dst = buffer; char *src = buffer; char *last_nonnl = buffer - 1; src[*length] = 0; for (; *src != '\0'; ++src) { if (src[0] == '\r' && src[1] == '\n') continue; if (*src == '\n') { *dst++ = ' '; } else { last_nonnl = dst; *dst++ = *src; } } if (!trim_newlines && (last_nonnl < (dst - 2))) last_nonnl = dst - 2; *(++last_nonnl) = '\0'; *length = last_nonnl - buffer; } int shell_function_pid = 0, shell_function_completed; #ifdef WINDOWS32 /*untested*/ #include #include #include "sub_proc.h" int windows32_openpipe (int *pipedes, int errfd, pid_t *pid_p, char **command_argv, char **envp) { SECURITY_ATTRIBUTES saAttr; HANDLE hIn = INVALID_HANDLE_VALUE; HANDLE hErr = INVALID_HANDLE_VALUE; HANDLE hChildOutRd; HANDLE hChildOutWr; HANDLE hProcess, tmpIn, tmpErr; DWORD e; /* Set status for return. */ pipedes[0] = pipedes[1] = -1; *pid_p = (pid_t)-1; saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* Standard handles returned by GetStdHandle can be NULL or INVALID_HANDLE_VALUE if the parent process closed them. If that happens, we open the null device and pass its handle to process_begin below as the corresponding handle to inherit. */ tmpIn = GetStdHandle (STD_INPUT_HANDLE); if (DuplicateHandle (GetCurrentProcess (), tmpIn, GetCurrentProcess (), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { e = GetLastError (); if (e == ERROR_INVALID_HANDLE) { tmpIn = CreateFile ("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpIn != INVALID_HANDLE_VALUE && DuplicateHandle (GetCurrentProcess (), tmpIn, GetCurrentProcess (), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle (tmpIn); } if (hIn == INVALID_HANDLE_VALUE) { ON (error, NILF, _("windows32_openpipe: DuplicateHandle(In) failed (e=%ld)\n"), e); return -1; } } tmpErr = (HANDLE)_get_osfhandle (errfd); if (DuplicateHandle (GetCurrentProcess (), tmpErr, GetCurrentProcess (), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { e = GetLastError (); if (e == ERROR_INVALID_HANDLE) { tmpErr = CreateFile ("NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpErr != INVALID_HANDLE_VALUE && DuplicateHandle (GetCurrentProcess (), tmpErr, GetCurrentProcess (), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle (tmpErr); } if (hErr == INVALID_HANDLE_VALUE) { ON (error, NILF, _("windows32_openpipe: DuplicateHandle(Err) failed (e=%ld)\n"), e); return -1; } } if (! CreatePipe (&hChildOutRd, &hChildOutWr, &saAttr, 0)) { ON (error, NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError()); return -1; } hProcess = process_init_fd (hIn, hChildOutWr, hErr); if (!hProcess) { O (error, NILF, _("windows32_openpipe(): process_init_fd() failed\n")); return -1; } /* make sure that CreateProcess() has Path it needs */ sync_Path_environment (); /* 'sync_Path_environment' may realloc 'environ', so take note of the new value. */ envp = environ; if (! process_begin (hProcess, command_argv, envp, command_argv[0], NULL)) { /* register process for wait */ process_register (hProcess); /* set the pid for returning to caller */ *pid_p = (pid_t) hProcess; /* set up to read data from child */ pipedes[0] = _open_osfhandle ((intptr_t) hChildOutRd, O_RDONLY); /* this will be closed almost right away */ pipedes[1] = _open_osfhandle ((intptr_t) hChildOutWr, O_APPEND); return 0; } else { /* reap/cleanup the failed process */ process_cleanup (hProcess); /* close handles which were duplicated, they weren't used */ if (hIn != INVALID_HANDLE_VALUE) CloseHandle (hIn); if (hErr != INVALID_HANDLE_VALUE) CloseHandle (hErr); /* close pipe handles, they won't be used */ CloseHandle (hChildOutRd); CloseHandle (hChildOutWr); return -1; } } #endif #ifdef __MSDOS__ FILE * msdos_openpipe (int* pipedes, int *pidp, char *text) { FILE *fpipe=0; /* MSDOS can't fork, but it has 'popen'. */ struct variable *sh = lookup_variable ("SHELL", 5); int e; extern int dos_command_running, dos_status; /* Make sure not to bother processing an empty line. */ while (isblank ((unsigned char)*text)) ++text; if (*text == '\0') return 0; if (sh) { char buf[PATH_MAX + 7]; /* This makes sure $SHELL value is used by $(shell), even though the target environment is not passed to it. */ sprintf (buf, "SHELL=%s", sh->value); putenv (buf); } e = errno; errno = 0; dos_command_running = 1; dos_status = 0; /* If dos_status becomes non-zero, it means the child process was interrupted by a signal, like SIGINT or SIGQUIT. See fatal_error_signal in commands.c. */ fpipe = popen (text, "rt"); dos_command_running = 0; if (!fpipe || dos_status) { pipedes[0] = -1; *pidp = -1; if (dos_status) errno = EINTR; else if (errno == 0) errno = ENOMEM; shell_function_completed = -1; } else { pipedes[0] = fileno (fpipe); *pidp = 42; /* Yes, the Meaning of Life, the Universe, and Everything! */ errno = e; shell_function_completed = 1; } return fpipe; } #endif /* Do shell spawning, with the naughty bits for different OSes. */ #ifdef VMS /* VMS can't do $(shell ...) */ char * func_shell_base (char *o, char **argv, int trim_newlines) { fprintf (stderr, "This platform does not support shell\n"); die (MAKE_TROUBLE); return NULL; } #define func_shell 0 #else #ifndef _AMIGA char * func_shell_base (char *o, char **argv, int trim_newlines) { char *batch_filename = NULL; int errfd; #ifdef __MSDOS__ FILE *fpipe; #endif char **command_argv; const char *error_prefix; char **envp; int pipedes[2]; pid_t pid; #ifndef __MSDOS__ #ifdef WINDOWS32 /* Reset just_print_flag. This is needed on Windows when batch files are used to run the commands, because we normally refrain from creating batch files under -n. */ int j_p_f = just_print_flag; just_print_flag = 0; #endif /* Construct the argument list. */ command_argv = construct_command_argv (argv[0], NULL, NULL, 0, &batch_filename); if (command_argv == 0) { #ifdef WINDOWS32 just_print_flag = j_p_f; #endif return o; } #endif /* Using a target environment for 'shell' loses in cases like: export var = $(shell echo foobie) bad := $(var) because target_environment hits a loop trying to expand $(var) to put it in the environment. This is even more confusing when 'var' was not explicitly exported, but just appeared in the calling environment. See Savannah bug #10593. envp = target_environment (NULL); */ envp = environ; /* For error messages. */ if (reading_file && reading_file->filenm) { char *p = alloca (strlen (reading_file->filenm)+11+4); sprintf (p, "%s:%lu: ", reading_file->filenm, reading_file->lineno); error_prefix = p; } else error_prefix = ""; /* Set up the output in case the shell writes something. */ output_start (); errfd = (output_context && output_context->err >= 0 ? output_context->err : FD_STDERR); #if defined(__MSDOS__) fpipe = msdos_openpipe (pipedes, &pid, argv[0]); if (pipedes[0] < 0) { perror_with_name (error_prefix, "pipe"); return o; } #elif defined(WINDOWS32) windows32_openpipe (pipedes, errfd, &pid, command_argv, envp); /* Restore the value of just_print_flag. */ just_print_flag = j_p_f; if (pipedes[0] < 0) { /* Open of the pipe failed, mark as failed execution. */ shell_function_completed = -1; perror_with_name (error_prefix, "pipe"); return o; } else #else if (pipe (pipedes) < 0) { perror_with_name (error_prefix, "pipe"); return o; } # ifdef __EMX__ /* close some handles that are unnecessary for the child process */ CLOSE_ON_EXEC(pipedes[1]); CLOSE_ON_EXEC(pipedes[0]); /* Never use fork()/exec() here! Use spawn() instead in exec_command() */ pid = child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp); if (pid < 0) perror_with_name (error_prefix, "spawn"); # else /* ! __EMX__ */ pid = fork (); if (pid < 0) perror_with_name (error_prefix, "fork"); else if (pid == 0) { # ifdef SET_STACK_SIZE /* Reset limits, if necessary. */ if (stack_limit.rlim_cur) setrlimit (RLIMIT_STACK, &stack_limit); # endif child_execute_job (FD_STDIN, pipedes[1], errfd, command_argv, envp); } else # endif #endif { /* We are the parent. */ char *buffer; unsigned int maxlen, i; int cc; /* Record the PID for reap_children. */ shell_function_pid = pid; #ifndef __MSDOS__ shell_function_completed = 0; /* Free the storage only the child needed. */ free (command_argv[0]); free (command_argv); /* Close the write side of the pipe. We test for -1, since pipedes[1] is -1 on MS-Windows, and some versions of MS libraries barf when 'close' is called with -1. */ if (pipedes[1] >= 0) close (pipedes[1]); #endif /* Set up and read from the pipe. */ maxlen = 200; buffer = xmalloc (maxlen + 1); /* Read from the pipe until it gets EOF. */ for (i = 0; ; i += cc) { if (i == maxlen) { maxlen += 512; buffer = xrealloc (buffer, maxlen + 1); } EINTRLOOP (cc, read (pipedes[0], &buffer[i], maxlen - i)); if (cc <= 0) break; } buffer[i] = '\0'; /* Close the read side of the pipe. */ #ifdef __MSDOS__ if (fpipe) (void) pclose (fpipe); #else (void) close (pipedes[0]); #endif /* Loop until child_handler or reap_children() sets shell_function_completed to the status of our child shell. */ while (shell_function_completed == 0) reap_children (1, 0, NULL); if (batch_filename) { DB (DB_VERBOSE, (_("Cleaning up temporary batch file %s\n"), batch_filename)); remove (batch_filename); free (batch_filename); } shell_function_pid = 0; /* The child_handler function will set shell_function_completed to 1 when the child dies normally, or to -1 if it dies with status 127, which is most likely an exec fail. */ if (shell_function_completed == -1) { /* This likely means that the execvp failed, so we should just write the error message in the pipe from the child. */ fputs (buffer, stderr); fflush (stderr); } else { /* The child finished normally. Replace all newlines in its output with spaces, and put that in the variable output buffer. */ fold_newlines (buffer, &i, trim_newlines); o = variable_buffer_output (o, buffer, i); } free (buffer); } return o; } #else /* _AMIGA */ /* Do the Amiga version of func_shell. */ char * func_shell_base (char *o, char **argv, int trim_newlines) { /* Amiga can't fork nor spawn, but I can start a program with redirection of my choice. However, this means that we don't have an opportunity to reopen stdout to trap it. Thus, we save our own stdout onto a new descriptor and dup a temp file's descriptor onto our stdout temporarily. After we spawn the shell program, we dup our own stdout back to the stdout descriptor. The buffer reading is the same as above, except that we're now reading from a file. */ #include #include BPTR child_stdout; char tmp_output[FILENAME_MAX]; unsigned int maxlen = 200, i; int cc; char * buffer, * ptr; char ** aptr; int len = 0; char* batch_filename = NULL; /* Construct the argument list. */ command_argv = construct_command_argv (argv[0], NULL, NULL, 0, &batch_filename); if (command_argv == 0) return o; /* Note the mktemp() is a security hole, but this only runs on Amiga. Ideally we would use output_tmpfile(), but this uses a special Open(), not fopen(), and I'm not familiar enough with the code to mess with it. */ strcpy (tmp_output, "t:MakeshXXXXXXXX"); mktemp (tmp_output); child_stdout = Open (tmp_output, MODE_NEWFILE); for (aptr=command_argv; *aptr; aptr++) len += strlen (*aptr) + 1; buffer = xmalloc (len + 1); ptr = buffer; for (aptr=command_argv; *aptr; aptr++) { strcpy (ptr, *aptr); ptr += strlen (ptr) + 1; *ptr ++ = ' '; *ptr = 0; } ptr[-1] = '\n'; Execute (buffer, NULL, child_stdout); free (buffer); Close (child_stdout); child_stdout = Open (tmp_output, MODE_OLDFILE); buffer = xmalloc (maxlen); i = 0; do { if (i == maxlen) { maxlen += 512; buffer = xrealloc (buffer, maxlen + 1); } cc = Read (child_stdout, &buffer[i], maxlen - i); if (cc > 0) i += cc; } while (cc > 0); Close (child_stdout); fold_newlines (buffer, &i, trim_newlines); o = variable_buffer_output (o, buffer, i); free (buffer); return o; } #endif /* _AMIGA */ char * func_shell (char *o, char **argv, const char *funcname UNUSED) { return func_shell_base (o, argv, 1); } #endif /* !VMS */ #ifdef EXPERIMENTAL /* equality. Return is string-boolean, i.e., the empty string is false. */ static char * func_eq (char *o, char **argv, char *funcname UNUSED) { int result = ! strcmp (argv[0], argv[1]); o = variable_buffer_output (o, result ? "1" : "", result); return o; } /* string-boolean not operator. */ static char * func_not (char *o, char **argv, char *funcname UNUSED) { const char *s = argv[0]; int result = 0; while (isspace ((unsigned char)*s)) s++; result = ! (*s); o = variable_buffer_output (o, result ? "1" : "", result); return o; } #endif #ifdef HAVE_DOS_PATHS # ifdef __CYGWIN__ # define IS_ABSOLUTE(n) ((n[0] && n[1] == ':') || STOP_SET (n[0], MAP_DIRSEP)) # else # define IS_ABSOLUTE(n) (n[0] && n[1] == ':') # endif # define ROOT_LEN 3 #else #define IS_ABSOLUTE(n) (n[0] == '/') #define ROOT_LEN 1 #endif /* Return the absolute name of file NAME which does not contain any '.', '..' components nor any repeated path separators ('/'). */ static char * abspath (const char *name, char *apath) { char *dest; const char *start, *end, *apath_limit; unsigned long root_len = ROOT_LEN; if (name[0] == '\0' || apath == NULL) return NULL; apath_limit = apath + GET_PATH_MAX; if (!IS_ABSOLUTE(name)) { /* It is unlikely we would make it until here but just to make sure. */ if (!starting_directory) return NULL; strcpy (apath, starting_directory); #ifdef HAVE_DOS_PATHS if (STOP_SET (name[0], MAP_DIRSEP)) { if (STOP_SET (name[1], MAP_DIRSEP)) { /* A UNC. Don't prepend a drive letter. */ apath[0] = name[0]; apath[1] = name[1]; root_len = 2; } /* We have /foo, an absolute file name except for the drive letter. Assume the missing drive letter is the current drive, which we can get if we remove from starting_directory everything past the root directory. */ apath[root_len] = '\0'; } #endif dest = strchr (apath, '\0'); } else { #if defined(__CYGWIN__) && defined(HAVE_DOS_PATHS) if (STOP_SET (name[0], MAP_DIRSEP)) root_len = 1; #endif strncpy (apath, name, root_len); apath[root_len] = '\0'; dest = apath + root_len; /* Get past the root, since we already copied it. */ name += root_len; #ifdef HAVE_DOS_PATHS if (! STOP_SET (apath[root_len - 1], MAP_DIRSEP)) { /* Convert d:foo into d:./foo and increase root_len. */ apath[2] = '.'; apath[3] = '/'; dest++; root_len++; /* strncpy above copied one character too many. */ name--; } else apath[root_len - 1] = '/'; /* make sure it's a forward slash */ #endif } for (start = end = name; *start != '\0'; start = end) { unsigned long len; /* Skip sequence of multiple path-separators. */ while (STOP_SET (*start, MAP_DIRSEP)) ++start; /* Find end of path component. */ for (end = start; ! STOP_SET (*end, MAP_DIRSEP|MAP_NUL); ++end) ; len = end - start; if (len == 0) break; else if (len == 1 && start[0] == '.') /* nothing */; else if (len == 2 && start[0] == '.' && start[1] == '.') { /* Back up to previous component, ignore if at root already. */ if (dest > apath + root_len) for (--dest; ! STOP_SET (dest[-1], MAP_DIRSEP); --dest) ; } else { if (! STOP_SET (dest[-1], MAP_DIRSEP)) *dest++ = '/'; if (dest + len >= apath_limit) return NULL; dest = memcpy (dest, start, len); dest += len; *dest = '\0'; } } /* Unless it is root strip trailing separator. */ if (dest > apath + root_len && STOP_SET (dest[-1], MAP_DIRSEP)) --dest; *dest = '\0'; return apath; } static char * func_realpath (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ const char *p = argv[0]; const char *path = 0; int doneany = 0; unsigned int len = 0; while ((path = find_next_token (&p, &len)) != 0) { if (len < GET_PATH_MAX) { char *rp; struct stat st; PATH_VAR (in); PATH_VAR (out); strncpy (in, path, len); in[len] = '\0'; #ifdef HAVE_REALPATH ENULLLOOP (rp, realpath (in, out)); #else rp = abspath (in, out); #endif if (rp) { int r; EINTRLOOP (r, stat (out, &st)); if (r == 0) { o = variable_buffer_output (o, out, strlen (out)); o = variable_buffer_output (o, " ", 1); doneany = 1; } } } } /* Kill last space. */ if (doneany) --o; return o; } static char * func_file (char *o, char **argv, const char *funcname UNUSED) { char *fn = argv[0]; if (fn[0] == '>') { FILE *fp; const char *mode = "w"; /* We are writing a file. */ ++fn; if (fn[0] == '>') { mode = "a"; ++fn; } fn = next_token (fn); fp = fopen (fn, mode); if (fp == NULL) { const char *err = strerror (errno); OSS (fatal, reading_file, _("open: %s: %s"), fn, err); } if (argv[1]) { int l = strlen (argv[1]); int nl = l == 0 || argv[1][l-1] != '\n'; if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF)) { const char *err = strerror (errno); OSS (fatal, reading_file, _("write: %s: %s"), fn, err); } } fclose (fp); } else OS (fatal, reading_file, _("Invalid file operation: %s"), fn); return o; } static char * func_abspath (char *o, char **argv, const char *funcname UNUSED) { /* Expand the argument. */ const char *p = argv[0]; const char *path = 0; int doneany = 0; unsigned int len = 0; while ((path = find_next_token (&p, &len)) != 0) { if (len < GET_PATH_MAX) { PATH_VAR (in); PATH_VAR (out); strncpy (in, path, len); in[len] = '\0'; if (abspath (in, out)) { o = variable_buffer_output (o, out, strlen (out)); o = variable_buffer_output (o, " ", 1); doneany = 1; } } } /* Kill last space. */ if (doneany) --o; return o; } /* Lookup table for builtin functions. This doesn't have to be sorted; we use a straight lookup. We might gain some efficiency by moving most often used functions to the start of the table. If MAXIMUM_ARGS is 0, that means there is no maximum and all comma-separated values are treated as arguments. EXPAND_ARGS means that all arguments should be expanded before invocation. Functions that do namespace tricks (foreach) don't automatically expand. */ static char *func_call (char *o, char **argv, const char *funcname); #define FT_ENTRY(_name, _min, _max, _exp, _func) \ { { (_func) }, STRING_SIZE_TUPLE(_name), (_min), (_max), (_exp), 0 } static struct function_table_entry function_table_init[] = { /* Name MIN MAX EXP? Function */ FT_ENTRY ("abspath", 0, 1, 1, func_abspath), FT_ENTRY ("addprefix", 2, 2, 1, func_addsuffix_addprefix), FT_ENTRY ("addsuffix", 2, 2, 1, func_addsuffix_addprefix), FT_ENTRY ("basename", 0, 1, 1, func_basename_dir), FT_ENTRY ("dir", 0, 1, 1, func_basename_dir), FT_ENTRY ("notdir", 0, 1, 1, func_notdir_suffix), FT_ENTRY ("subst", 3, 3, 1, func_subst), FT_ENTRY ("suffix", 0, 1, 1, func_notdir_suffix), FT_ENTRY ("filter", 2, 2, 1, func_filter_filterout), FT_ENTRY ("filter-out", 2, 2, 1, func_filter_filterout), FT_ENTRY ("findstring", 2, 2, 1, func_findstring), FT_ENTRY ("firstword", 0, 1, 1, func_firstword), FT_ENTRY ("flavor", 0, 1, 1, func_flavor), FT_ENTRY ("join", 2, 2, 1, func_join), FT_ENTRY ("lastword", 0, 1, 1, func_lastword), FT_ENTRY ("patsubst", 3, 3, 1, func_patsubst), FT_ENTRY ("realpath", 0, 1, 1, func_realpath), FT_ENTRY ("shell", 0, 1, 1, func_shell), FT_ENTRY ("sort", 0, 1, 1, func_sort), FT_ENTRY ("strip", 0, 1, 1, func_strip), FT_ENTRY ("wildcard", 0, 1, 1, func_wildcard), FT_ENTRY ("word", 2, 2, 1, func_word), FT_ENTRY ("wordlist", 3, 3, 1, func_wordlist), FT_ENTRY ("words", 0, 1, 1, func_words), FT_ENTRY ("origin", 0, 1, 1, func_origin), FT_ENTRY ("foreach", 3, 3, 0, func_foreach), FT_ENTRY ("call", 1, 0, 1, func_call), FT_ENTRY ("info", 0, 1, 1, func_error), FT_ENTRY ("error", 0, 1, 1, func_error), FT_ENTRY ("warning", 0, 1, 1, func_error), FT_ENTRY ("if", 2, 3, 0, func_if), FT_ENTRY ("or", 1, 0, 0, func_or), FT_ENTRY ("and", 1, 0, 0, func_and), FT_ENTRY ("value", 0, 1, 1, func_value), FT_ENTRY ("eval", 0, 1, 1, func_eval), FT_ENTRY ("file", 1, 2, 1, func_file), FT_ENTRY ("debugger", 0, 1, 1, func_debugger), #ifdef EXPERIMENTAL FT_ENTRY ("eq", 2, 2, 1, func_eq), FT_ENTRY ("not", 0, 1, 1, func_not), #endif }; #define FUNCTION_TABLE_ENTRIES (sizeof (function_table_init) / sizeof (struct function_table_entry)) /* These must come after the definition of function_table. */ static char * expand_builtin_function (char *o, int argc, char **argv, const struct function_table_entry *entry_p) { char *p; if (argc < (int)entry_p->minimum_args) fatal (*expanding_var, strlen (entry_p->name), _("insufficient number of arguments (%d) to function '%s'"), argc, entry_p->name); /* I suppose technically some function could do something with no arguments, but so far no internal ones do, so just test it for all functions here rather than in each one. We can change it later if necessary. */ if (!argc && !entry_p->alloc_fn) return o; if (!entry_p->fptr.func_ptr) OS (fatal, *expanding_var, _("unimplemented on this platform: function '%s'"), entry_p->name); if (!entry_p->alloc_fn) return entry_p->fptr.func_ptr (o, argv, entry_p->name); /* This function allocates memory and returns it to us. Write it to the variable buffer, then free it. */ p = entry_p->fptr.alloc_func_ptr (entry_p->name, argc, argv); if (p) { o = variable_buffer_output (o, p, strlen (p)); free (p); } return o; } /* Check for a function invocation in *STRINGP. *STRINGP points at the opening ( or { and is not null-terminated. If a function invocation is found, expand it into the buffer at *OP, updating *OP, incrementing *STRINGP past the reference and returning nonzero. If not, return zero. */ int handle_function (char **op, const char **stringp) { const struct function_table_entry *entry_p; char openparen = (*stringp)[0]; char closeparen = openparen == '(' ? ')' : '}'; const char *beg; const char *end; int count = 0; char *abeg = NULL; char **argv, **argvp; int nargs; beg = *stringp + 1; entry_p = lookup_function (beg); if (!entry_p) return 0; /* We found a builtin function. Find the beginning of its arguments (skip whitespace after the name). */ beg = next_token (beg + entry_p->len); /* Find the end of the function invocation, counting nested use of whichever kind of parens we use. Since we're looking, count commas to get a rough estimate of how many arguments we might have. The count might be high, but it'll never be low. */ for (nargs=1, end=beg; *end != '\0'; ++end) if (*end == ',') ++nargs; else if (*end == openparen) ++count; else if (*end == closeparen && --count < 0) break; if (count >= 0) fatal (*expanding_var, strlen (entry_p->name), _("unterminated call to function '%s': missing '%c'"), entry_p->name, closeparen); *stringp = end; /* Get some memory to store the arg pointers. */ argvp = argv = alloca (sizeof (char *) * (nargs + 2)); /* Chop the string into arguments, then a nul. As soon as we hit MAXIMUM_ARGS (if it's >0) assume the rest of the string is part of the last argument. If we're expanding, store pointers to the expansion of each one. If not, make a duplicate of the string and point into that, nul-terminating each argument. */ if (entry_p->expand_args) { const char *p; for (p=beg, nargs=0; p <= end; ++argvp) { const char *next; ++nargs; if (nargs == entry_p->maximum_args || (! (next = find_next_argument (openparen, closeparen, p, end)))) next = end; *argvp = expand_argument (p, next); p = next + 1; } } else { int len = end - beg; char *p, *aend; abeg = xmalloc (len+1); memcpy (abeg, beg, len); abeg[len] = '\0'; aend = abeg + len; for (p=abeg, nargs=0; p <= aend; ++argvp) { char *next; ++nargs; if (nargs == entry_p->maximum_args || (! (next = find_next_argument (openparen, closeparen, p, aend)))) next = aend; *argvp = p; *next = '\0'; p = next + 1; } } *argvp = NULL; /* Finally! Run the function... */ *op = expand_builtin_function (*op, nargs, argv, entry_p); /* Free memory. */ if (entry_p->expand_args) for (argvp=argv; *argvp != 0; ++argvp) free (*argvp); else free (abeg); return 1; } /* User-defined functions. Expand the first argument as either a builtin function or a make variable, in the context of the rest of the arguments assigned to $1, $2, ... $N. $0 is the name of the function. */ static char * func_call (char *o, char **argv, const char *funcname UNUSED) { static int max_args = 0; char *fname; char *cp; char *body; int flen; int i; int saved_args; const struct function_table_entry *entry_p; struct variable *v; /* There is no way to define a variable with a space in the name, so strip leading and trailing whitespace as a favor to the user. */ fname = argv[0]; while (isspace ((unsigned char)*fname)) ++fname; cp = fname + strlen (fname) - 1; while (cp > fname && isspace ((unsigned char)*cp)) --cp; cp[1] = '\0'; /* Calling nothing is a no-op */ if (*fname == '\0') return o; /* Are we invoking a builtin function? */ entry_p = lookup_function (fname); if (entry_p) { /* How many arguments do we have? */ for (i=0; argv[i+1]; ++i) ; return expand_builtin_function (o, i, argv+1, entry_p); } /* Not a builtin, so the first argument is the name of a variable to be expanded and interpreted as a function. Find it. */ flen = strlen (fname); v = lookup_variable (fname, flen); if (v == 0) warn_undefined (fname, flen); if (v == 0 || *v->value == '\0') return o; body = alloca (flen + 4); body[0] = '$'; body[1] = '('; memcpy (body + 2, fname, flen); body[flen+2] = ')'; body[flen+3] = '\0'; /* Set up arguments $(1) .. $(N). $(0) is the function name. */ push_new_variable_scope (); for (i=0; *argv; ++i, ++argv) { char num[11]; sprintf (num, "%d", i); define_variable (num, strlen (num), *argv, o_automatic, 0); } /* If the number of arguments we have is < max_args, it means we're inside a recursive invocation of $(call ...). Fill in the remaining arguments in the new scope with the empty value, to hide them from this invocation. */ for (; i < max_args; ++i) { char num[11]; sprintf (num, "%d", i); define_variable (num, strlen (num), "", o_automatic, 0); } /* Expand the body in the context of the arguments, adding the result to the variable buffer. */ v->exp_count = EXP_COUNT_MAX; saved_args = max_args; max_args = i; o = variable_expand_string (o, body, flen+3); max_args = saved_args; v->exp_count = 0; pop_variable_scope (); return o + strlen (o); } void define_new_function (const gmk_floc *flocp, const char *name, unsigned int min, unsigned int max, unsigned int flags, gmk_func_ptr func) { const char *e = name; struct function_table_entry *ent; size_t len; while (STOP_SET (*e, MAP_USERFUNC)) e++; len = e - name; if (len == 0) O (fatal, flocp, _("Empty function name")); if (*name == '.' || *e != '\0') OS (fatal, flocp, _("Invalid function name: %s"), name); if (len > 255) OS (fatal, flocp, _("Function name too long: %s"), name); if (min > 255) ONS (fatal, flocp, _("Invalid minimum argument count (%d) for function %s"), min, name); if (max > 255 || (max && max < min)) ONS (fatal, flocp, _("Invalid maximum argument count (%d) for function %s"), max, name); ent = xmalloc (sizeof (struct function_table_entry)); ent->name = name; ent->len = len; ent->minimum_args = min; ent->maximum_args = max; ent->expand_args = ANY_SET(flags, GMK_FUNC_NOEXPAND) ? 0 : 1; ent->alloc_fn = 1; ent->fptr.alloc_func_ptr = func; hash_insert (&function_table, ent); } void hash_init_function_table (void) { hash_init (&function_table, FUNCTION_TABLE_ENTRIES * 2, function_table_entry_hash_1, function_table_entry_hash_2, function_table_entry_hash_cmp); hash_load (&function_table, function_table_init, FUNCTION_TABLE_ENTRIES, sizeof (struct function_table_entry)); } remake-4.1+dbg1.3~dfsg.1/function.h000066400000000000000000000035611317072305000167760ustar00rootroot00000000000000/* $Id: function.h,v 1.10 2007/01/04 12:03:20 rockyb Exp $ Copyright (C) 1988, 1989, 1991-1997, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2005 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file function.h * * \brief Builtin function expansion for GNU Make. */ #ifndef FUNCTION_H #define FUNCTION_H #include "make.h" /*! Replace all carriage returns and linefeeds with spaces. Carriage return is replaced on UNIX as well. Is this desirable? */ extern void fold_newlines (char *buffer, unsigned int *length); extern void hash_init_function_table (void); extern void hash_free_function_table (void); /*! Set begpp to point to the first non-whitespace character of the string, and endpp to point to the last non-whitespace character of the string. If the string is empty or contains nothing but whitespace, endpp will be begpp-1. */ extern char *strip_whitespace (const char **begpp, const char **endpp); /*! $(eval *makefile-string*) Always resolves to the empty string. Treat the arguments as a segment of makefile, and parse them. */ extern char *func_eval (char *o, char **argv, const char *funcname UNUSED); #endif /*FUNCTION_H*/ remake-4.1+dbg1.3~dfsg.1/getloadavg.c000066400000000000000000000626061317072305000172660ustar00rootroot00000000000000/* Get the system load averages. Copyright (C) 1985-2014 Free Software Foundation, Inc. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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.in file. FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. KERNEL_FILE Pathname of the kernel 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. NLIST_STRUCT Include nlist.h, not a.out.h, and the nlist n_name element is a pointer, not an array. HAVE_STRUCT_NLIST_N_UN_N_NAME struct nlist has an n_un member, not n_name. LINUX_LDAV_FILE [__linux__]: 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. convex DGUX eunice UNIX emulator under VMS. hpux __MSDOS__ No-op for MSDOS. NeXT sgi sequent Sequent Dynix 3.x.x (BSD) _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV) sony_news NEWS-OS (works at least for 4.1C) UMAX UMAX4_3 VMS WINDOWS32 No-op for Windows95/NT. __linux__ Linux: assumes /proc filesystem mounted. Support from Michael K. Johnson. __NetBSD__ NetBSD: assumes /kern filesystem 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. */ /* This should always be first. */ #ifdef HAVE_CONFIG_H # include #endif #include /* Both the Emacs and non-Emacs sections want this. Some configuration files' definitions for the LOAD_AVE_CVT macro (like sparc.h's) use macros like FSCALE, defined here. */ #if defined (unix) || defined (__unix) # include #endif /* Exclude all the code except the test program at the end if the system has its own 'getloadavg' function. The declaration of 'errno' is needed by the test program as well as the function itself, so it comes first. */ #include #ifndef errno extern int errno; #endif #if HAVE_LOCALE_H # include #endif #if !HAVE_SETLOCALE # define setlocale(Category, Locale) /* empty */ #endif #ifndef HAVE_GETLOADAVG /* The existing Emacs configuration files define a macro called LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and returns the load average multiplied by 100. What we actually want is a macro called LDAV_CVT, which returns the load average as an unmultiplied double. For backwards compatibility, we'll define LDAV_CVT in terms of LOAD_AVE_CVT, but future machine config files should just define LDAV_CVT directly. */ # if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT) # define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0) # endif # if !defined (BSD) && defined (ultrix) /* Ultrix behaves like BSD on Vaxen. */ # define BSD # 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(ultrix) && defined(mips) # define decstation # 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 # endif # if defined (__osf__) && (defined (mips) || defined (__mips__)) # define OSF_MIPS # include # endif /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by default, but _MACH_IND_SYS_TYPES is defined in . Combine that with a couple of other things and we'll have a unique match. */ # if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES) # define tek4300 /* Define by emacs, but not by other users. */ # endif /* AC_FUNC_GETLOADAVG thinks QNX is SVR4, but it isn't. */ # if defined(__QNX__) # undef SVR4 # 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 decstation # define LOAD_AVE_TYPE long # endif # ifdef _SEQUENT_ # define LOAD_AVE_TYPE long # endif # ifdef sgi # define LOAD_AVE_TYPE long # endif # ifdef SVR4 # define LOAD_AVE_TYPE long # endif # ifdef sony_news # define LOAD_AVE_TYPE long # endif # ifdef sequent # define LOAD_AVE_TYPE long # endif # ifdef OSF_ALPHA # define LOAD_AVE_TYPE long # endif # if defined (ardent) && defined (titan) # define LOAD_AVE_TYPE long # endif # ifdef tek4300 # define LOAD_AVE_TYPE long # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ # define LOAD_AVE_TYPE long # endif # ifdef _AIX # define LOAD_AVE_TYPE long # endif # ifdef convex # define LOAD_AVE_TYPE double # ifndef LDAV_CVT # define LDAV_CVT(n) (n) # endif # 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 # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ /* defines an incorrect value for FSCALE on an Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 100.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) || defined(decstation) # define FSCALE 256 # endif # if defined (sgi) || defined (sequent) /* 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 (ardent) && defined (titan) # define FSCALE 65536.0 # endif # ifdef tek4300 # define FSCALE 100.0 # endif # ifdef _AIX # define FSCALE 65536.0 # endif # endif /* Not FSCALE. */ # if !defined (LDAV_CVT) && defined (FSCALE) # define LDAV_CVT(n) (((double) (n)) / FSCALE) # 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 (sequent) # define KERNEL_FILE "/dynix" # endif # if !defined (KERNEL_FILE) && defined (hpux) # define KERNEL_FILE "/hp-ux" # endif # if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan))) # define KERNEL_FILE "/unix" # endif # if !defined (LDAV_SYMBOL) && defined (alliant) # define LDAV_SYMBOL "_Loadavg" # endif # if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX)) # define LDAV_SYMBOL "avenrun" # endif # ifdef HAVE_UNISTD_H # include # endif # include /* 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)) && !defined(__riscos__) # define LOAD_AVE_TYPE double # endif # ifdef LOAD_AVE_TYPE # ifndef VMS # ifndef __linux__ # ifdef HAVE_NLIST_H # include # else # include # endif # ifdef SUNOS_5 # include # 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__ */ # 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(__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 # 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(HAVE_FCNTL_H) || defined(_POSIX_VERSION) # include # else # include # endif /* Avoid static vars inside a function since in HPUX they dump as pure. */ # ifdef NeXT static processor_set_t default_set; static int 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; /* Nonzero iff channel is valid. */ static int 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__) static struct nlist nl[2]; #endif /* Not VMS or sgi */ #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 if an error occurred. */ int getloadavg (double loadavg[], int nelem) { int elem = 0; /* Return value. */ # ifdef NO_GET_LOAD_AVG # define LDAV_DONE /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; elem = -1; # endif # if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Use libkstat because we don't have to be root. */ # define LDAV_DONE kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; kc = kstat_open (); if (kc == 0) return -1; ksp = kstat_lookup (kc, "unix", 0, "system_misc"); if (ksp == 0 ) return -1; if (kstat_read (kc, ksp, 0) == -1) return -1; kn = kstat_data_lookup (ksp, "avenrun_1min"); if (kn == 0) { /* 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 != 0) { loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 3) { kn = kstat_data_lookup (ksp, "avenrun_15min"); if (kn != 0) loadavg[elem++] = (double) kn->value.ul/FSCALE; } } } kstat_close (kc); # endif /* HAVE_LIBKSTAT */ # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) /* 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 (__linux__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef LINUX_LDAV_FILE # define LINUX_LDAV_FILE "/proc/loadavg" # endif char ldavgbuf[40]; double load_ave[3]; int fd, count; fd = open (LINUX_LDAV_FILE, O_RDONLY); if (fd == -1) return -1; count = read (fd, ldavgbuf, 40); (void) close (fd); if (count <= 0) return -1; /* The following sscanf must use the C locale. */ setlocale (LC_NUMERIC, "C"); count = sscanf (ldavgbuf, "%lf %lf %lf", &load_ave[0], &load_ave[1], &load_ave[2]); setlocale (LC_NUMERIC, ""); if (count < 1) return -1; for (elem = 0; elem < nelem && elem < count; elem++) loadavg[elem] = load_ave[elem]; return elem; # endif /* __linux__ */ # if !defined (LDAV_DONE) && defined (__NetBSD__) # 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; FILE *fp; fp = fopen (NETBSD_LDAV_FILE, "r"); if (fp == NULL) return -1; count = fscanf (fp, "%lu %lu %lu %lu\n", &load_ave[0], &load_ave[1], &load_ave[2], &scale); (void) fclose (fp); if (count != 4) 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) # define LDAV_DONE /* The NeXT code was adapted from iscreen 3.2. */ host_t host; struct processor_set_basic_info info; unsigned 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 = 1; } 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 = 0; else { if (nelem > 0) loadavg[elem++] = (double) info.load_average / LOAD_SCALE; } } if (!getloadavg_initialized) 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)) # 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) # 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 specific code -- read from the Load Ave driver. */ LOAD_AVE_TYPE load_ave[3]; static int getloadavg_initialized = 0; # 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 = 1; } /* 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 = 0; } if (!getloadavg_initialized) return -1; # endif /* VMS */ # if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS) /* 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 # ifndef NLIST_STRUCT strcpy (nl[0].n_name, LDAV_SYMBOL); strcpy (nl[1].n_name, ""); # else /* NLIST_STRUCT */ # ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME nl[0].n_un.n_name = LDAV_SYMBOL; nl[1].n_un.n_name = 0; # else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ nl[0].n_name = LDAV_SYMBOL; nl[1].n_name = 0; # endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ # endif /* NLIST_STRUCT */ # ifndef SUNOS_5 if ( # if !(defined (_AIX) && !defined (ps2)) nlist (KERNEL_FILE, nl) # else /* _AIX */ knlist (nl, 1, sizeof (nl[0])) # endif >= 0) /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */ { # ifdef FIXUP_KERNEL_SYMBOL_ADDR FIXUP_KERNEL_SYMBOL_ADDR (nl); # endif offset = nl[0].n_value; } # endif /* !SUNOS_5 */ # else /* sgi */ int ldav_off; ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); if (ldav_off != -1) offset = (long) ldav_off & 0x7fffffff; # endif /* sgi */ } /* Make sure we have /dev/kmem open. */ if (!getloadavg_initialized) { # ifndef SUNOS_5 channel = open ("/dev/kmem", 0); if (channel >= 0) { /* Set the channel to close on exec, so it does not litter any child's descriptor table. */ # ifdef F_SETFD # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif (void) fcntl (channel, F_SETFD, FD_CLOEXEC); # endif getloadavg_initialized = 1; } # 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 != 0) { /* nlist the currently running kernel. */ kvm_nlist (kd, nl); offset = nl[0].n_value; getloadavg_initialized = 1; } # 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 = 0; } # else /* SUNOS_5 */ if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { kvm_close (kd); getloadavg_initialized = 0; } # endif /* SUNOS_5 */ } if (offset == 0 || !getloadavg_initialized) return -1; # endif /* LOAD_AVE_TYPE and not 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 */ # ifdef LDAV_DONE return elem; # else /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; return -1; # endif } #endif /* ! HAVE_GETLOADAVG */ #ifdef TEST #include "makeint.h" int main (int argc, char **argv) { int naptime = 0; if (argc > 1) naptime = atoi (argv[1]); while (1) { double avg[3]; int loads; errno = 0; /* Don't be misled if it doesn't set errno. */ loads = getloadavg (avg, 3); if (loads == -1) { perror ("Error getting load average"); exit (1); } if (loads > 0) printf ("1-minute: %f ", avg[0]); if (loads > 1) printf ("5-minute: %f ", avg[1]); if (loads > 2) printf ("15-minute: %f ", avg[2]); if (loads > 0) putchar ('\n'); if (naptime == 0) break; sleep (naptime); } exit (0); } #endif /* TEST */ remake-4.1+dbg1.3~dfsg.1/getopt.c000066400000000000000000000717741317072305000164610ustar00rootroot00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987-2014 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. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #include "gettext.h" #define _(msgid) gettext (msgid) /* This version of `getopt' appears to the caller like standard Unix 'getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else # if HAVE_STRING_H # include # else # include # endif /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (char **argv) { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only) { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option '%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option '--%s' doesn't allow an argument\n"), argv[0], pfound->name); else { /* +option or -option */ fprintf (stderr, _("%s: option '%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option '%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option '--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option '-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option '%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #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 */ remake-4.1+dbg1.3~dfsg.1/getopt.h000066400000000000000000000105701317072305000164510ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989-2014 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. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -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; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* getopt.h */ remake-4.1+dbg1.3~dfsg.1/getopt1.c000066400000000000000000000103131317072305000165200ustar00rootroot00000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987-1994, 1996-2014 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. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ #ifdef HAVE_CONFIG_H #include #endif #include "getopt.h" #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #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 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 */ remake-4.1+dbg1.3~dfsg.1/gettext.h000066400000000000000000000047271317072305000166420ustar00rootroot00000000000000/* Convenience header for conditional use of GNU . Copyright (C) 1995-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ # include #else /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define textdomain(Domainname) ((const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String #endif /* _LIBGETTEXT_H */ remake-4.1+dbg1.3~dfsg.1/git2cl000077500000000000000000000262631317072305000161160ustar00rootroot00000000000000#!/usr/bin/perl # Copyright (C) 2007, 2008 Simon Josefsson # Copyright (C) 2007 Luis Mondesi # * calls git directly. To use it just: # cd ~/Project/my_git_repo; git2cl > ChangeLog # * implements strptime() # * fixes bugs in $comment parsing # - copy input before we remove leading spaces # - skip "merge branch" statements as they don't # have information about files (i.e. we never # go into $state 2) # - behaves like a pipe/filter if input is given from the CLI # else it calls git log by itself # # The functions mywrap, last_line_len, wrap_log_entry are derived from # the cvs2cl tool, see : # Copyright (C) 2001,2002,2003,2004 Martyn J. Pearce # Copyright (C) 1999 Karl Fogel # # git2cl is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # git2cl is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with git2cl; see the file COPYING. If not, write to the Free # Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA. =head1 NAME git2cl - tool to convert git logs to GNU ChangeLog =head1 SYNOPSIS git2cl > ChangeLog If you don't want git2cl to invoke git log internally, you can use it as a pipe. It needs a git log generated with --pretty --numstat and --summary. You can use it as follows: git log --pretty --numstat --summary | git2cl > ChangeLog =head1 DESCRIPTION This is a quick'n'dirty tool to convert git logs to GNU ChangeLog format. The tool invokes `git log` internally unless you pipe a log to it. Thus, typically you would use it as follows: =head1 SEE ALSO Output format specification: =head1 AUTHORS git2cl is developed by Simon Josefsson and Luis Mondesi =cut use strict; use POSIX qw(strftime); use Text::Wrap qw(wrap); use FileHandle; use constant EMPTY_LOG_MESSAGE => '*** empty log message ***'; # this is a helper hash for stptime. # Assumes you are calling 'git log ...' with LC_ALL=C my %month = ( 'Jan'=>0, 'Feb'=>1, 'Mar'=>2, 'Apr'=>3, 'May'=>4, 'Jun'=>5, 'Jul'=>6, 'Aug'=>7, 'Sep'=>8, 'Oct'=>9, 'Nov'=>10, 'Dec'=>11, ); my $fh = new FileHandle; sub key_ready { my ($rin, $nfd); vec($rin, fileno(STDIN), 1) = 1; return $nfd = select($rin, undef, undef, 0); } sub strptime { my $str = shift; return undef if not defined $str; # we are parsing this format # Fri Oct 26 00:42:56 2007 -0400 # to these fields # sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1 # Luis Mondesi my @date; if ($str =~ /([[:alpha:]]{3})\s+([[:alpha:]]{3})\s+([[:digit:]]{1,2})\s+([[:digit:]]{1,2}):([[:digit:]]{1,2}):([[:digit:]]{1,2})\s+([[:digit:]]{4})/){ push(@date,$6,$5,$4,$3,$month{$2},($7 - 1900),-1,-1,-1); } else { die ("Cannot parse date '$str'\n'"); } return @date; } sub mywrap { my ($indent1, $indent2, @text) = @_; # If incoming text looks preformatted, don't get clever my $text = Text::Wrap::wrap($indent1, $indent2, @text); if ( grep /^\s+/m, @text ) { return $text; } my @lines = split /\n/, $text; $indent2 =~ s!^((?: {8})+)!"\t" x (length($1)/8)!e; $lines[0] =~ s/^$indent1\s+/$indent1/; s/^$indent2\s+/$indent2/ for @lines[1..$#lines]; my $newtext = join "\n", @lines; $newtext .= "\n" if substr($text, -1) eq "\n"; return $newtext; } sub last_line_len { my $files_list = shift; my @lines = split (/\n/, $files_list); my $last_line = pop (@lines); return length ($last_line); } # A custom wrap function, sensitive to some common constructs used in # log entries. sub wrap_log_entry { my $text = shift; # The text to wrap. my $left_pad_str = shift; # String to pad with on the left. # These do NOT take left_pad_str into account: my $length_remaining = shift; # Amount left on current line. my $max_line_length = shift; # Amount left for a blank line. my $wrapped_text = ''; # The accumulating wrapped entry. my $user_indent = ''; # Inherited user_indent from prev line. my $first_time = 1; # First iteration of the loop? my $suppress_line_start_match = 0; # Set to disable line start checks. my @lines = split (/\n/, $text); while (@lines) # Don't use `foreach' here, it won't work. { my $this_line = shift (@lines); chomp $this_line; if ($this_line =~ /^(\s+)/) { $user_indent = $1; } else { $user_indent = ''; } # If it matches any of the line-start regexps, print a newline now... if ($suppress_line_start_match) { $suppress_line_start_match = 0; } elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/) || ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/) || ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/) || ($this_line =~ /^(\s+)(\S+)/) || ($this_line =~ /^(\s*)- +/) || ($this_line =~ /^()\s*$/) || ($this_line =~ /^(\s*)\*\) +/) || ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/)) { $length_remaining = $max_line_length - (length ($user_indent)); } # Now that any user_indent has been preserved, strip off leading # whitespace, so up-folding has no ugly side-effects. $this_line =~ s/^\s*//; # Accumulate the line, and adjust parameters for next line. my $this_len = length ($this_line); if ($this_len == 0) { # Blank lines should cancel any user_indent level. $user_indent = ''; $length_remaining = $max_line_length; } elsif ($this_len >= $length_remaining) # Line too long, try breaking it. { # Walk backwards from the end. At first acceptable spot, break # a new line. my $idx = $length_remaining - 1; if ($idx < 0) { $idx = 0 }; while ($idx > 0) { if (substr ($this_line, $idx, 1) =~ /\s/) { my $line_now = substr ($this_line, 0, $idx); my $next_line = substr ($this_line, $idx); $this_line = $line_now; # Clean whitespace off the end. chomp $this_line; # The current line is ready to be printed. $this_line .= "\n${left_pad_str}"; # Make sure the next line is allowed full room. $length_remaining = $max_line_length - (length ($user_indent)); # Strip next_line, but then preserve any user_indent. $next_line =~ s/^\s*//; # Sneak a peek at the user_indent of the upcoming line, so # $next_line (which will now precede it) can inherit that # indent level. Otherwise, use whatever user_indent level # we currently have, which might be none. my $next_next_line = shift (@lines); if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) { $next_line = $1 . $next_line if (defined ($1)); # $length_remaining = $max_line_length - (length ($1)); $next_next_line =~ s/^\s*//; } else { $next_line = $user_indent . $next_line; } if (defined ($next_next_line)) { unshift (@lines, $next_next_line); } unshift (@lines, $next_line); # Our new next line might, coincidentally, begin with one of # the line-start regexps, so we temporarily turn off # sensitivity to that until we're past the line. $suppress_line_start_match = 1; last; } else { $idx--; } } if ($idx == 0) { # We bottomed out because the line is longer than the # available space. But that could be because the space is # small, or because the line is longer than even the maximum # possible space. Handle both cases below. if ($length_remaining == ($max_line_length - (length ($user_indent)))) { # The line is simply too long -- there is no hope of ever # breaking it nicely, so just insert it verbatim, with # appropriate padding. $this_line = "\n${left_pad_str}${this_line}"; } else { # Can't break it here, but may be able to on the next round... unshift (@lines, $this_line); $length_remaining = $max_line_length - (length ($user_indent)); $this_line = "\n${left_pad_str}"; } } } else # $this_len < $length_remaining, so tack on what we can. { # Leave a note for the next iteration. $length_remaining = $length_remaining - $this_len; if ($this_line =~ /\.$/) { $this_line .= " "; $length_remaining -= 2; } else # not a sentence end { $this_line .= " "; $length_remaining -= 1; } } # Unconditionally indicate that loop has run at least once. $first_time = 0; $wrapped_text .= "${user_indent}${this_line}"; } # One last bit of padding. $wrapped_text .= "\n"; return $wrapped_text; } # main my @date; my $author; my @files; my $comment; my $state; # 0-header 1-comment 2-files my $done = 0; $state = 0; # if reading from STDIN, we assume that we are # getting git log as input if (key_ready()) { #my $dummyfh; # don't care about writing #($fh,$dummyfh) = FileHandle::pipe; $fh->fdopen(*STDIN, 'r'); } else { $fh->open("LC_ALL=C git log --pretty --numstat --summary|") or die("Cannot execute git log...$!\n"); } while (my $_l = <$fh>) { #print STDERR "debug ($state, " . (@date ? (strftime "%Y-%m-%d", @date) : "") . "): `$_'\n"; if ($state == 0) { if ($_l =~ m,^Author: (.*),) { $author = $1; } if ($_l =~ m,^Date: (.*),) { @date = strptime($1); } $state = 1 if ($_l =~ m,^$, and $author and (@date+0>0)); } elsif ($state == 1) { # * modifying our input text is a bad choice # let's make a copy of it first, then we remove spaces # * if we meet a "merge branch" statement, we need to start # over and find a real entry # Luis Mondesi my $_s = $_l; $_s =~ s/^ //g; if ($_s =~ m/^Merge branch/) { $state=0; next; } $comment = $comment . $_s; $state = 2 if ($_l =~ m,^$,); } elsif ($state == 2) { if ($_l =~ m,^([0-9]+)\t([0-9]+)\t(.*)$,) { push @files, $3; } $done = 1 if ($_l =~ m,^$,); } if ($done) { print (strftime "%Y-%m-%d $author\n\n", @date); my $files = join (", ", @files); $files = mywrap ("\t", "\t", "* $files"), ": "; if (index($comment, EMPTY_LOG_MESSAGE) > -1 ) { $comment = "[no log message]\n"; } my $files_last_line_len = 0; $files_last_line_len = last_line_len($files) + 1; my $msg = wrap_log_entry($comment, "\t", 69-$files_last_line_len, 69); $msg =~ s/[ \t]+\n/\n/g; print "$files: $msg\n"; @date = (); $author = ""; @files = (); $comment = ""; $state = 0; $done = 0; } } if (@date + 0) { print (strftime "%Y-%m-%d $author\n\n", @date); my $msg = wrap_log_entry($comment, "\t", 69, 69); $msg =~ s/[ \t]+\n/\n/g; print "\t* $msg\n"; } remake-4.1+dbg1.3~dfsg.1/glob/000077500000000000000000000000001317072305000157165ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/glob/.cvsignore000066400000000000000000000000331317072305000177120ustar00rootroot00000000000000Makefile Makefile.in .deps remake-4.1+dbg1.3~dfsg.1/glob/.gitignore000066400000000000000000000000331317072305000177020ustar00rootroot00000000000000/*~ /Makefile /Makefile.in remake-4.1+dbg1.3~dfsg.1/glob/COPYING.LIB000066400000000000000000000612571317072305000173710ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! remake-4.1+dbg1.3~dfsg.1/glob/ChangeLog000066400000000000000000000154351317072305000175000ustar00rootroot000000000000002013-10-20 Paul Smith * glob.c (glob): Cherry-pick a471e96a5352a5f0bde6d32dd36d33524811a2b1 from git://sourceware.org/git/glibc.git to fix SV 18123, https://sourceware.org/bugzilla/show_bug.cgi?id=10278 2008-09-28 Juan Manuel Guerrero * glob.c (my_realloc) [__DJGPP__]: Don't define, and don't redefine realloc to call it, since the DJGPP's realloc handles NULL pointers correctly. 2007-12-22 Juan Manuel Guerrero (tiny change) * glob.c [__GNU_LIBRARY__ && __DJGPP__]: Add a realloc declaration that matches the one in the DJGPP libc. 2006-02-24 Eli Zaretskii * glob.c (my_malloc) [WINDOWS32]: Provide a full ISO C prototype, to avoid compiler warnings. 2005-06-25 Paul D. Smith * fnmatch.h, glob.h [WINDOWS32]: Fix ifdefs in headers. Fixes Savannah bug #13477. 2005-03-11 Paul D. Smith * glob.c (glob_in_dir): Change FNM_CASEFOLD to be enabled if HAVE_CASE_INSENSITIVE_FS is defined. 2003-01-30 Paul D. Smith * glob.h: Patch for FreeBSD by Mike Barcroft Reported by Gerald Pfeifer . On FreeBSD, declare __size_t to simply size_t. 2002-04-22 Paul D. Smith * Makefile.am: Use automake 1.6. Use new automake condition USE_LOCAL_GLOB to decide whether or not to build the local GNU glob library or use the system one. 1999-09-12 Paul D. Smith * fnmatch.c: Last GLIBC version wouldn't compile outside of GLIBC (undefined reference to internal_function). Update to the latest version 1999-09-11 Paul Eggert * glob.h (glob): If #defining to glob64, do this before declaring it, so that all declarations and uses match, and do not declare glob64, to avoid a declaration clash. (globfree): Likewise with globfree64. 1999-09-08 Eli Zaretskii * glob.c (prefix_array) [__MSDOS__,WINDOWS32]: Keep the trailing slash unless DIRNAME is just "x:/". 1999-09-06 Paul D. Smith * fnmatch.c: Update to latest version from GLIBC. 1999-07-21 Paul D. Smith * glob.c, glob.h, fnmatch.c, fnmatch.h: Update to latest version from GLIBC. * fnmatch.c (internal_fnmatch): Use K&R definition syntax, not ANSI. (__strchrnul): This won't exist outside GLIBC, so create one. * glob.c: Move getlogin{,_r} prototypes below glob.h to get __P() macro. 1998-08-05 Paul D. Smith * configure.in: Remove; configuration for glob is handled by the make configure.in. 1998-07-29 Paul D. Smith * glob.c, fnmatch.c: New versions from the GLIBC folks (Ulrich Drepper). Fixes a bug reported by Eli Zaretski. Integrates DOS/Windows32 support. 1998-07-27 Kaveh R. Ghazi * glob.c (glob): Cast away const on assignment of pattern to dirname. Cast the return type of __alloca() for traditional C compilers. 1998-07-23 Paul D. Smith * glob.c, fnmatch.c: New versions of these files from the GLIBC folks (Ulrich Drepper). Had to re-integrate some DOS/Windows code. 1998-07-10 Paul D. Smith * glob.c (glob_in_dir): If no meta chars exist in PATTERN and GLOB_NOCHECK is present, don't look for the file--whether it's found or not, we'll always return it, so why bother searching? Also, if we are searching and there are no meta chars, don't bother trying fnmatch() if the strcmp() fails. 1998-05-30 Eli Zaretskii * glob.c (glob) [__MSDOS__, WINDOWS32]: Compute the directory and filename parts of the pattern correctly when it includes a drive spec. Disallow wildcards in the drive spec. Prevent recursion when dirname is of the form "d:/" or "d:". (prefix_array) [__MSDOS__, WINDOWS32]: Don't append a slash to "d:/" and "d:". 1998-05-13 Paul D. Smith * SMakefile, Makefile.ami, glob.c, glob.h, fnmatch.c: Updated from the latest glibc version. 1998-04-17 Paul D. Smith * configure.in: Create a config.h file instead of setting things on the compile line. This is because when build.sh runs it merely passes -DHAVE_CONFIG_H to the glob files, just as it does to the make files. * config.h.in: Created by autoheader. Tue Aug 12 10:52:34 1997 Paul D. Smith * configure.in: Require autoconf 2.12. * glob: Updates from latest GNU libc glob code. * glob.c,glob.h,fnmatch.h: Change all WIN32 references to WINDOWS32. * glob.h: OSF4 defines macros in such a way that GLOB_ALTDIRFUNC is not defined. Added a test to the #if which defines it if _GNU_SOURCE is defined; that's set by both glob.c and GNU make. * glob.c: SunOS4 w/ cc needs #include , since assert.h requires stderr but doesn't include stdio.h :-/. (next_brace_sub): De-protoize function definition. (glob): Cast __alloca(); on SunOS4 it uses the default return type of int. (glob): Irix defines getlogin_r() to return a char*; move the extern for that into the _LIBC area since it isn't used except in LIBC anyway. Likewise, move extern getlogin() into the "else". Sat Jul 20 21:55:31 1996 Roland McGrath Win32 hacks from . * posix/glob.c [WIN32]: Don't include ; don't use d_ino; use void * for my_realloc; include for alloca. (glob) [WIN32]: Use "c:/users/default" for ~ if no HOME variable. * posix/fnmatch.h [WIN32]: Use prototypes even if [!__STDC__]. * posix/glob.h: Likewise. Fri Jul 19 16:56:41 1996 Roland McGrath * posix/glob.h [!_AMIGA && !VMS]: Check this instead of just [!_AMIGA] for `struct stat;' forward decl. Sat Jun 22 10:44:09 1996 Roland McGrath * posix/glob.c: Include only [HAVE_ALLOCA_H], not [sparc]. Fri Jun 21 00:27:51 1996 Roland McGrath * posix/fnmatch.c (fnmatch): Fix \*[*?]+ case to increment name ptr only for ?s, not for *s. Fix from Chet Ramey. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/glob/Makefile.am000066400000000000000000000021441317072305000177530ustar00rootroot00000000000000# -*-Makefile-*-, or close enough # Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . AUTOMAKE_OPTIONS = foreign # Only build the library when the system doesn't already have GNU glob. if USE_LOCAL_GLOB noinst_LIBRARIES = libglob.a endif libglob_a_SOURCES = glob.c glob.h fnmatch.c fnmatch.h EXTRA_DIST = COPYING.LIB Makefile.ami SCOPTIONS SMakefile \ configure.bat remake-4.1+dbg1.3~dfsg.1/glob/Makefile.ami000066400000000000000000000037761317072305000201400ustar00rootroot00000000000000# Makefile for standalone libglob.a (fnmatch, glob). -*-Makefile-*- # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc RM = delete CPPFLAGS = CFLAGS = # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c OUTPUT_OPTION = .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) glob.lib "#?.o" core distclean glob-realclean: clean -$(RM) TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ remake-4.1+dbg1.3~dfsg.1/glob/SCOPTIONS000066400000000000000000000003031317072305000172160ustar00rootroot00000000000000ERRORREXX OPTIMIZE NOVERSION OPTIMIZERTIME OPTIMIZERALIAS DEFINE INCLUDEDIR="include:" DEFINE LIBDIR="lib:" DEFINE NO_ALLOCA DEFINE NO_FLOAT DEFINE NO_ARCHIVES IGNORE=161 IGNORE=100 STARTUP=cres remake-4.1+dbg1.3~dfsg.1/glob/SMakefile000066400000000000000000000037631317072305000175120ustar00rootroot00000000000000# Makefile for standalone distribution of libglob.a (fnmatch, glob). # Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # Ultrix 2.2 make doesn't expand the value of VPATH. VPATH = /glob/ # This must repeat the value, because configure will remove `VPATH = .'. srcdir = /glob/ CC = sc CPPFLAGS = CFLAGS = MAKE = smake RM = delete # Information determined by configure. DEFS = Define HAVE_HEADER_STDC Define HAVE_UNISTD_H Define HAVE_STRING_H \ Define HAVE_DIRENT_H # How to invoke ar. AR = join ARFLAGS = as # How to invoke ranlib. RANLIB = ; .PHONY: all all: glob.lib glob.lib : glob.o fnmatch.o $(AR) $(ARFLAGS) $@ glob.o fnmatch.o $(RANLIB) $@ # For some reason, Unix make wants the dependencies on the source files. # Otherwise it refuses to use an implicit rule! # And, get this: it doesn't work to use $(srcdir)foo.c!! glob.o: $(srcdir)glob.h $(srcdir)fnmatch.h glob.c fnmatch.o: $(srcdir)fnmatch.h fnmatch.c .c.o: $(CC) IDir "" \ $(DEFS) $(CPPFLAGS) $(CFLAGS) $< $(OUTPUT_OPTION) .PHONY: clean realclean glob-clean glob-realclean distclean clean glob-clean: -$(RM) -f glob.lib *.o core distclean glob-realclean: clean -$(RM) -f TAGS tags Makefile config.status config.h config.log realcean: distclean # For inside the C library. glob.tar glob.tar.Z: $(MAKE) -C .. $@ remake-4.1+dbg1.3~dfsg.1/glob/configure.bat000066400000000000000000000033241317072305000203710ustar00rootroot00000000000000@echo off rem Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, rem 2004, 2005, 2006, 2007 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . echo Configuring glob for DJGPP rem This batch file assumes a unix-type "sed" program echo # Makefile generated by "configure.bat"> Makefile if exist config.sed del config.sed echo "s/@srcdir@/./ ">> config.sed echo "s/@CC@/gcc/ ">> config.sed echo "s/@CFLAGS@/-O2 -g/ ">> config.sed echo "s/@CPPFLAGS@/-DHAVE_CONFIG_H -I../ ">> config.sed echo "s/@AR@/ar/ ">> config.sed echo "s/@RANLIB@/ranlib/ ">> config.sed echo "s/@LDFLAGS@// ">> config.sed echo "s/@DEFS@// ">> config.sed echo "s/@ALLOCA@// ">> config.sed echo "s/@LIBS@// ">> config.sed echo "s/@LIBOBJS@// ">> config.sed echo "s/^Makefile *:/_Makefile:/ ">> config.sed echo "s/^config.h *:/_config.h:/ ">> config.sed sed -e "s/^\"//" -e "s/\"$//" -e "s/[ ]*$//" config.sed > config2.sed sed -f config2.sed Makefile.in >> Makefile del config.sed del config2.sed remake-4.1+dbg1.3~dfsg.1/glob/fnmatch.c000066400000000000000000000311221317072305000175010ustar00rootroot00000000000000/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #if HAVE_CONFIG_H # include #endif /* Enable GNU extensions in fnmatch.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include #if HAVE_STRING_H || defined _LIBC # include #else # include #endif #if defined STDC_HEADERS || defined _LIBC # include #endif /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* Solaris 2.5 has a bug: must be included before . */ # include # include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined _LIBC || !defined __GNU_LIBRARY__ # if defined STDC_HEADERS || !defined isascii # define ISASCII(c) 1 # else # define ISASCII(c) isascii(c) # endif # ifdef isblank # define ISBLANK(c) (ISASCII (c) && isblank (c)) # else # define ISBLANK(c) ((c) == ' ' || (c) == '\t') # endif # ifdef isgraph # define ISGRAPH(c) (ISASCII (c) && isgraph (c)) # else # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) # endif # define ISPRINT(c) (ISASCII (c) && isprint (c)) # define ISDIGIT(c) (ISASCII (c) && isdigit (c)) # define ISALNUM(c) (ISASCII (c) && isalnum (c)) # define ISALPHA(c) (ISASCII (c) && isalpha (c)) # define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) # define ISLOWER(c) (ISASCII (c) && islower (c)) # define ISPUNCT(c) (ISASCII (c) && ispunct (c)) # define ISSPACE(c) (ISASCII (c) && isspace (c)) # define ISUPPER(c) (ISASCII (c) && isupper (c)) # define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) # define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) /* The GNU C library provides support for user-defined character classes and the functions from ISO C amendement 1. */ # ifdef CHARCLASS_NAME_MAX # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX # else /* This shouldn't happen but some implementation might still have this problem. Use a reasonable default value. */ # define CHAR_CLASS_MAX_LENGTH 256 # endif # ifdef _LIBC # define IS_CHAR_CLASS(string) __wctype (string) # else # define IS_CHAR_CLASS(string) wctype (string) # endif # else # define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ # define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) # endif /* Avoid depending on library functions or files whose names are inconsistent. */ # if !defined _LIBC && !defined getenv extern char *getenv (); # endif # ifndef errno extern int errno; # endif /* This function doesn't exist on most systems. */ # if !defined HAVE___STRCHRNUL && !defined _LIBC static char * __strchrnul (s, c) const char *s; int c; { char *result = strchr (s, c); if (result == NULL) result = strchr (s, '\0'); return result; } # endif # ifndef internal_function /* Inside GNU libc we mark some function in a special way. In other environments simply ignore the marking. */ # define internal_function # endif /* Match STRING against the filename pattern PATTERN, returning zero if it matches, nonzero if not. */ static int internal_fnmatch __P ((const char *pattern, const char *string, int no_leading_period, int flags)) internal_function; static int internal_function internal_fnmatch (pattern, string, no_leading_period, flags) const char *pattern; const char *string; int no_leading_period; int flags; { register const char *p = pattern, *n = string; register unsigned char c; /* Note that this evaluates C many times. */ # ifdef _LIBC # define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) # else # define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) # endif while ((c = *p++) != '\0') { c = FOLD (c); switch (c) { case '?': if (*n == '\0') return FNM_NOMATCH; else if (*n == '/' && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; else if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; break; case '\\': if (!(flags & FNM_NOESCAPE)) { c = *p++; if (c == '\0') /* Trailing \ loses. */ return FNM_NOMATCH; c = FOLD (c); } if (FOLD ((unsigned char) *n) != c) return FNM_NOMATCH; break; case '*': if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; for (c = *p++; c == '?' || c == '*'; c = *p++) { if (*n == '/' && (flags & FNM_FILE_NAME)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else if (c == '?') { /* A ? needs to match one character. */ if (*n == '\0') /* There isn't another character; no match. */ return FNM_NOMATCH; else /* One character of the string is consumed in matching this ? wildcard, so *??? won't match if there are less than three characters. */ ++n; } } if (c == '\0') /* The wildcard(s) is/are the last element of the pattern. If the name is a file name and contains another slash this does mean it cannot match. */ return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL ? FNM_NOMATCH : 0); else { const char *endp; endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); if (c == '[') { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); for (--p; n < endp; ++n) if (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0) return 0; } else if (c == '/' && (flags & FNM_FILE_NAME)) { while (*n != '\0' && *n != '/') ++n; if (*n == '/' && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, flags) == 0)) return 0; } else { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); if (c == '\\' && !(flags & FNM_NOESCAPE)) c = *p; c = FOLD (c); for (--p; n < endp; ++n) if (FOLD ((unsigned char) *n) == c && (internal_fnmatch (p, n, (no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))), flags2) == 0)) return 0; } } /* If we come here no match is possible with the wildcard. */ return FNM_NOMATCH; case '[': { /* Nonzero if the sense of the character class is inverted. */ static int posixly_correct; register int not; char cold; if (posixly_correct == 0) posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; if (*n == '\0') return FNM_NOMATCH; if (*n == '.' && no_leading_period && (n == string || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) return FNM_NOMATCH; if (*n == '/' && (flags & FNM_FILE_NAME)) /* `/' cannot be matched. */ return FNM_NOMATCH; not = (*p == '!' || (posixly_correct < 0 && *p == '^')); if (not) ++p; c = *p++; for (;;) { unsigned char fn = FOLD ((unsigned char) *n); if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; c = FOLD ((unsigned char) *p); ++p; if (c == fn) goto matched; } else if (c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; size_t c1 = 0; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wctype_t wt; # endif const char *startp = p; for (;;) { if (c1 == CHAR_CLASS_MAX_LENGTH) /* The name is too long and therefore the pattern is ill-formed. */ return FNM_NOMATCH; c = *++p; if (c == ':' && p[1] == ']') { p += 2; break; } if (c < 'a' || c >= 'z') { /* This cannot possibly be a character class name. Match it as a normal range. */ p = startp; c = '['; goto normal_bracket; } str[c1++] = c; } str[c1] = '\0'; # if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) wt = IS_CHAR_CLASS (str); if (wt == 0) /* Invalid character class name. */ return FNM_NOMATCH; if (__iswctype (__btowc ((unsigned char) *n), wt)) goto matched; # else if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) goto matched; # endif } else if (c == '\0') /* [ (unterminated) loses. */ return FNM_NOMATCH; else { normal_bracket: if (FOLD (c) == fn) goto matched; cold = c; c = *p++; if (c == '-' && *p != ']') { /* It is a range. */ unsigned char cend = *p++; if (!(flags & FNM_NOESCAPE) && cend == '\\') cend = *p++; if (cend == '\0') return FNM_NOMATCH; if (cold <= fn && fn <= FOLD (cend)) goto matched; c = *p++; } } if (c == ']') break; } if (!not) return FNM_NOMATCH; break; matched: /* Skip the rest of the [...] that already matched. */ while (c != ']') { if (c == '\0') /* [... (unterminated) loses. */ return FNM_NOMATCH; c = *p++; if (!(flags & FNM_NOESCAPE) && c == '\\') { if (*p == '\0') return FNM_NOMATCH; /* XXX 1003.2d11 is unclear if this is right. */ ++p; } else if (c == '[' && *p == ':') { do if (*++p == '\0') return FNM_NOMATCH; while (*p != ':' || p[1] == ']'); p += 2; c = *p; } } if (not) return FNM_NOMATCH; } break; default: if (c != FOLD ((unsigned char) *n)) return FNM_NOMATCH; } ++n; } if (*n == '\0') return 0; if ((flags & FNM_LEADING_DIR) && *n == '/') /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ return 0; return FNM_NOMATCH; # undef FOLD } int fnmatch (pattern, string, flags) const char *pattern; const char *string; int flags; { return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); } #endif /* _LIBC or not __GNU_LIBRARY__. */ remake-4.1+dbg1.3~dfsg.1/glob/fnmatch.h000066400000000000000000000055631317072305000175200ustar00rootroot00000000000000/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999 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 Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _FNMATCH_H #define _FNMATCH_H 1 #ifdef __cplusplus extern "C" { #endif #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # define __P(protos) protos # endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () /* We can get away without defining `const' here only because in this file it is used only inside the prototype for `fnmatch', which is elided in non-ANSI C where `const' is problematical. */ #endif /* C++ or ANSI C. */ #ifndef const # if (defined __STDC__ && __STDC__) || defined __cplusplus || defined WINDOWS32 # define __const const # else # define __const # endif #endif /* We #undef these before defining them because some losing systems (HP-UX A.08.07 for example) define these in . */ #undef FNM_PATHNAME #undef FNM_NOESCAPE #undef FNM_PERIOD /* Bits set in the FLAGS argument to `fnmatch'. */ #define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ #define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ #define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ #if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE # define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ # define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ # define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ #endif /* Value returned by `fnmatch' if STRING does not match PATTERN. */ #define FNM_NOMATCH 1 /* This value is returned if the implementation does not support `fnmatch'. Since this is not the case here it will never be returned but the conformance test suites still require the symbol to be defined. */ #ifdef _XOPEN_SOURCE # define FNM_NOSYS (-1) #endif /* Match NAME against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ extern int fnmatch __P ((__const char *__pattern, __const char *__name, int __flags)); #ifdef __cplusplus } #endif #endif /* fnmatch.h */ remake-4.1+dbg1.3~dfsg.1/glob/glob.c000066400000000000000000001060371317072305000170140ustar00rootroot00000000000000/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ /* AIX requires this to be the first thing in the file. */ #if defined _AIX && !defined __GNUC__ #pragma alloca #endif #ifdef HAVE_CONFIG_H # include #endif /* Enable GNU extensions in glob.h. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif #include #include #include /* Outcomment the following line for production quality code. */ /* #define NDEBUG 1 */ #include #include /* Needed on stupid SunOS for assert. */ /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GLOB_INTERFACE_VERSION 1 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 # include # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include #endif #if defined HAVE_UNISTD_H || defined _LIBC # include # ifndef POSIX # ifdef _POSIX_VERSION # define POSIX # endif # endif #endif #if !defined _AMIGA && !defined VMS && !defined WINDOWS32 # include #endif #if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS extern int errno; #endif #ifndef __set_errno # define __set_errno(val) errno = (val) #endif #ifndef NULL # define NULL 0 #endif #if defined HAVE_DIRENT_H || defined __GNU_LIBRARY__ # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif # ifdef HAVE_VMSDIR_H # include "vmsdir.h" # endif /* HAVE_VMSDIR_H */ #endif /* In GNU systems, defines this macro for us. */ #ifdef _D_NAMLEN # undef NAMLEN # define NAMLEN(d) _D_NAMLEN(d) #endif /* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available if the `d_type' member for `struct dirent' is available. */ #ifdef _DIRENT_HAVE_D_TYPE # define HAVE_D_TYPE 1 #endif #if (defined POSIX || defined WINDOWS32) && !defined __GNU_LIBRARY__ /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 #else # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) #endif /* POSIX */ #if defined STDC_HEADERS || defined __GNU_LIBRARY__ # include # include # define ANSI_STRING #else /* No standard headers. */ extern char *getenv (); # ifdef HAVE_STRING_H # include # define ANSI_STRING # else # include # endif # ifdef HAVE_MEMORY_H # include # endif extern char *malloc (), *realloc (); extern void free (); extern void qsort (); extern void abort (), exit (); #endif /* Standard headers. */ #ifndef ANSI_STRING # ifndef bzero extern void bzero (); # endif # ifndef bcopy extern void bcopy (); # endif # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define strrchr rindex /* memset is only used for zero here, but let's be paranoid. */ # define memset(s, better_be_zero, n) \ ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0))) #endif /* Not ANSI_STRING. */ #if !defined HAVE_STRCOLL && !defined _LIBC # define strcoll strcmp #endif #if !defined HAVE_MEMPCPY && __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 # define HAVE_MEMPCPY 1 # undef mempcpy # define mempcpy(Dest, Src, Len) __mempcpy (Dest, Src, Len) #endif #if !defined __GNU_LIBRARY__ && !defined __DJGPP__ # ifdef __GNUC__ __inline # endif # ifndef __SASC # ifdef WINDOWS32 static void * my_realloc (void *p, unsigned int n) # else static char * my_realloc (p, n) char *p; unsigned int n; # endif { /* These casts are the for sake of the broken Ultrix compiler, which warns of illegal pointer combinations otherwise. */ if (p == NULL) return (char *) malloc (n); return (char *) realloc (p, n); } # define realloc my_realloc # endif /* __SASC */ #endif /* __GNU_LIBRARY__ || __DJGPP__ */ #if !defined __alloca && !defined __GNU_LIBRARY__ # ifdef __GNUC__ # undef alloca # define alloca(n) __builtin_alloca (n) # else /* Not GCC. */ # ifdef HAVE_ALLOCA_H # include # else /* Not HAVE_ALLOCA_H. */ # ifndef _AIX # ifdef WINDOWS32 # include # else extern char *alloca (); # endif /* WINDOWS32 */ # endif /* Not _AIX. */ # endif /* sparc or HAVE_ALLOCA_H. */ # endif /* GCC. */ # define __alloca alloca #endif #ifndef __GNU_LIBRARY__ # define __stat stat # ifdef STAT_MACROS_BROKEN # undef S_ISDIR # endif # ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) # endif #endif #ifdef _LIBC # undef strdup # define strdup(str) __strdup (str) # define sysconf(id) __sysconf (id) # define closedir(dir) __closedir (dir) # define opendir(name) __opendir (name) # define readdir(str) __readdir (str) # define getpwnam_r(name, bufp, buf, len, res) \ __getpwnam_r (name, bufp, buf, len, res) # ifndef __stat # define __stat(fname, buf) __xstat (_STAT_VER, fname, buf) # endif #endif #if !(defined STDC_HEADERS || defined __GNU_LIBRARY__) # undef size_t # define size_t unsigned int #endif /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef FNM_PATHNAME # undef FNM_NOESCAPE # undef FNM_PERIOD #endif #include /* Some system header files erroneously define these. We want our own definitions from to take precedence. */ #ifndef __GNU_LIBRARY__ # undef GLOB_ERR # undef GLOB_MARK # undef GLOB_NOSORT # undef GLOB_DOOFFS # undef GLOB_NOCHECK # undef GLOB_APPEND # undef GLOB_NOESCAPE # undef GLOB_PERIOD #endif #include #ifdef HAVE_GETLOGIN_R extern int getlogin_r __P ((char *, size_t)); #else extern char *getlogin __P ((void)); #endif static #if __GNUC__ - 0 >= 2 inline #endif const char *next_brace_sub __P ((const char *begin)); static int glob_in_dir __P ((const char *pattern, const char *directory, int flags, int (*errfunc) (const char *, int), glob_t *pglob)); static int prefix_array __P ((const char *prefix, char **array, size_t n)); static int collated_compare __P ((const __ptr_t, const __ptr_t)); #if !defined _LIBC || !defined NO_GLOB_PATTERN_P int __glob_pattern_p __P ((const char *pattern, int quote)); #endif /* Find the end of the sub-pattern in a brace expression. We define this as an inline function if the compiler permits. */ static #if __GNUC__ - 0 >= 2 inline #endif const char * next_brace_sub (begin) const char *begin; { unsigned int depth = 0; const char *cp = begin; while (1) { if (depth == 0) { if (*cp != ',' && *cp != '}' && *cp != '\0') { if (*cp == '{') ++depth; ++cp; continue; } } else { while (*cp != '\0' && (*cp != '}' || depth > 0)) { if (*cp == '}') --depth; ++cp; } if (*cp == '\0') /* An incorrectly terminated brace expression. */ return NULL; continue; } break; } return cp; } /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ int glob (pattern, flags, errfunc, pglob) const char *pattern; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { const char *filename; const char *dirname; size_t dirlen; int status; int oldcount; if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { __set_errno (EINVAL); return -1; } /* POSIX requires all slashes to be matched. This means that with a trailing slash we must match only directories. */ if (pattern[0] && pattern[strlen (pattern) - 1] == '/') flags |= GLOB_ONLYDIR; if (flags & GLOB_BRACE) { const char *begin = strchr (pattern, '{'); if (begin != NULL) { /* Allocate working buffer large enough for our work. Note that we have at least an opening and closing brace. */ int firstc; char *alt_start; const char *p; const char *next; const char *rest; size_t rest_len; #ifdef __GNUC__ char onealt[strlen (pattern) - 1]; #else char *onealt = (char *) malloc (strlen (pattern) - 1); if (onealt == NULL) { if (!(flags & GLOB_APPEND)) globfree (pglob); return GLOB_NOSPACE; } #endif /* We know the prefix for all sub-patterns. */ #ifdef HAVE_MEMPCPY alt_start = mempcpy (onealt, pattern, begin - pattern); #else memcpy (onealt, pattern, begin - pattern); alt_start = &onealt[begin - pattern]; #endif /* Find the first sub-pattern and at the same time find the rest after the closing brace. */ next = next_brace_sub (begin + 1); if (next == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } /* Now find the end of the whole brace expression. */ rest = next; while (*rest != '}') { rest = next_brace_sub (rest + 1); if (rest == NULL) { /* It is an illegal expression. */ #ifndef __GNUC__ free (onealt); #endif return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); } } /* Please note that we now can be sure the brace expression is well-formed. */ rest_len = strlen (++rest) + 1; /* We have a brace expression. BEGIN points to the opening {, NEXT points past the terminator of the first element, and END points past the final }. We will accumulate result names from recursive runs for each brace alternative in the buffer using GLOB_APPEND. */ if (!(flags & GLOB_APPEND)) { /* This call is to set a new vector, so clear out the vector so we can append to it. */ pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } firstc = pglob->gl_pathc; p = begin + 1; while (1) { int result; /* Construct the new glob expression. */ #ifdef HAVE_MEMPCPY mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); #else memcpy (alt_start, p, next - p); memcpy (&alt_start[next - p], rest, rest_len); #endif result = glob (onealt, ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC)) | GLOB_APPEND), errfunc, pglob); /* If we got an error, return it. */ if (result && result != GLOB_NOMATCH) { #ifndef __GNUC__ free (onealt); #endif if (!(flags & GLOB_APPEND)) globfree (pglob); return result; } if (*next == '}') /* We saw the last entry. */ break; p = next + 1; next = next_brace_sub (p); assert (next != NULL); } #ifndef __GNUC__ free (onealt); #endif if (pglob->gl_pathc != firstc) /* We found some entries. */ return 0; else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) return GLOB_NOMATCH; } } /* Find the filename. */ filename = strrchr (pattern, '/'); #if defined __MSDOS__ || defined WINDOWS32 /* The case of "d:pattern". Since `:' is not allowed in file names, we can safely assume that wherever it happens in pattern, it signals the filename part. This is so we could some day support patterns like "[a-z]:foo". */ if (filename == NULL) filename = strchr (pattern, ':'); #endif /* __MSDOS__ || WINDOWS32 */ if (filename == NULL) { /* This can mean two things: a simple name or "~name". The later case is nothing but a notation for a directory. */ if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') { dirname = pattern; dirlen = strlen (pattern); /* Set FILENAME to NULL as a special flag. This is ugly but other solutions would require much more code. We test for this special case below. */ filename = NULL; } else { filename = pattern; #ifdef _AMIGA dirname = ""; #else dirname = "."; #endif dirlen = 0; } } else if (filename == pattern) { /* "/pattern". */ dirname = "/"; dirlen = 1; ++filename; } else { char *newp; dirlen = filename - pattern; #if defined __MSDOS__ || defined WINDOWS32 if (*filename == ':' || (filename > pattern + 1 && filename[-1] == ':')) { char *drive_spec; ++dirlen; drive_spec = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; #else memcpy (drive_spec, pattern, dirlen); drive_spec[dirlen] = '\0'; #endif /* For now, disallow wildcards in the drive spec, to prevent infinite recursion in glob. */ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) return GLOB_NOMATCH; /* If this is "d:pattern", we need to copy `:' to DIRNAME as well. If it's "d:/pattern", don't remove the slash from "d:/", since "d:" and "d:/" are not the same.*/ } #endif newp = (char *) __alloca (dirlen + 1); #ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; #else memcpy (newp, pattern, dirlen); newp[dirlen] = '\0'; #endif dirname = newp; ++filename; if (filename[0] == '\0' #if defined __MSDOS__ || defined WINDOWS32 && dirname[dirlen - 1] != ':' && (dirlen < 3 || dirname[dirlen - 2] != ':' || dirname[dirlen - 1] != '/') #endif && dirlen > 1) /* "pattern/". Expand "pattern", appending slashes. */ { int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); if (val == 0) pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK)); return val; } } if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; } oldcount = pglob->gl_pathc; #ifndef VMS if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') { if (dirname[1] == '\0' || dirname[1] == '/') { /* Look up home directory. */ #ifdef VMS /* This isn't obvious, RTLs of DECC and VAXC know about "HOME" */ const char *home_dir = getenv ("SYS$LOGIN"); #else const char *home_dir = getenv ("HOME"); #endif # ifdef _AMIGA if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS:"; # else # ifdef WINDOWS32 if (home_dir == NULL || home_dir[0] == '\0') home_dir = "c:/users/default"; /* poor default */ # else # ifdef VMS /* Again, this isn't obvious, if "HOME" isn't known "SYS$LOGIN" should be set */ if (home_dir == NULL || home_dir[0] == '\0') home_dir = "SYS$DISK:[]"; # else if (home_dir == NULL || home_dir[0] == '\0') { int success; char *name; # if defined HAVE_GETLOGIN_R || defined _LIBC size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1; if (buflen == 0) /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try a moderate value. */ buflen = 20; name = (char *) __alloca (buflen); success = getlogin_r (name, buflen) >= 0; # else success = (name = getlogin ()) != NULL; # endif if (success) { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (pwbuflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ pwbuflen = 1024; pwtmpbuf = (char *) __alloca (pwbuflen); while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } pwbuflen *= 2; pwtmpbuf = (char *) __alloca (pwbuflen); __set_errno (save); } # else p = getpwnam (name); # endif if (p != NULL) home_dir = p->pw_dir; } } if (home_dir == NULL || home_dir[0] == '\0') { if (flags & GLOB_TILDE_CHECK) return GLOB_NOMATCH; else home_dir = "~"; /* No luck. */ } # endif /* VMS */ # endif /* WINDOWS32 */ # endif /* Now construct the full directory. */ if (dirname[1] == '\0') dirname = home_dir; else { char *newp; size_t home_len = strlen (home_dir); newp = (char *) __alloca (home_len + dirlen); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (newp, home_dir, home_len), &dirname[1], dirlen); # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], &dirname[1], dirlen); # endif dirname = newp; } } # if !defined _AMIGA && !defined WINDOWS32 && !defined VMS else { char *end_name = strchr (dirname, '/'); const char *user_name; const char *home_dir; if (end_name == NULL) user_name = dirname + 1; else { char *newp; newp = (char *) __alloca (end_name - dirname); # ifdef HAVE_MEMPCPY *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) = '\0'; # else memcpy (newp, dirname + 1, end_name - dirname); newp[end_name - dirname - 1] = '\0'; # endif user_name = newp; } /* Look up specific user's home directory. */ { struct passwd *p; # if defined HAVE_GETPWNAM_R || defined _LIBC size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *pwtmpbuf; struct passwd pwbuf; int save = errno; if (buflen == -1) /* `sysconf' does not support _SC_GETPW_R_SIZE_MAX. Try a moderate value. */ buflen = 1024; pwtmpbuf = (char *) __alloca (buflen); while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) { if (errno != ERANGE) { p = NULL; break; } buflen *= 2; pwtmpbuf = __alloca (buflen); __set_errno (save); } # else p = getpwnam (user_name); # endif if (p != NULL) home_dir = p->pw_dir; else home_dir = NULL; } /* If we found a home directory use this. */ if (home_dir != NULL) { char *newp; size_t home_len = strlen (home_dir); size_t rest_len = end_name == NULL ? 0 : strlen (end_name); newp = (char *) __alloca (home_len + rest_len + 1); # ifdef HAVE_MEMPCPY *((char *) mempcpy (mempcpy (newp, home_dir, home_len), end_name, rest_len)) = '\0'; # else memcpy (newp, home_dir, home_len); memcpy (&newp[home_len], end_name, rest_len); newp[home_len + rest_len] = '\0'; # endif dirname = newp; } else if (flags & GLOB_TILDE_CHECK) /* We have to regard it as an error if we cannot find the home directory. */ return GLOB_NOMATCH; } # endif /* Not Amiga && not WINDOWS32 && not VMS. */ } #endif /* Not VMS. */ /* Now test whether we looked for "~" or "~NAME". In this case we can give the answer now. */ if (filename == NULL) { struct stat st; /* Return the directory if we don't check for error or if it exists. */ if ((flags & GLOB_NOCHECK) || (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dirname, &st) : __stat (dirname, &st)) == 0 && S_ISDIR (st.st_mode))) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + 1 + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; #if defined HAVE_STRDUP || defined _LIBC pglob->gl_pathv[pglob->gl_pathc] = strdup (dirname); #else { size_t len = strlen (dirname) + 1; char *dircopy = malloc (len); if (dircopy != NULL) pglob->gl_pathv[pglob->gl_pathc] = memcpy (dircopy, dirname, len); } #endif if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { free (pglob->gl_pathv); return GLOB_NOSPACE; } pglob->gl_pathv[++pglob->gl_pathc] = NULL; pglob->gl_flags = flags; return 0; } /* Not found. */ return GLOB_NOMATCH; } if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) { /* The directory name contains metacharacters, so we have to glob for the directory, and then glob for the pattern in each directory found. */ glob_t dirs; register int i; status = glob (dirname, ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); if (status != 0) return status; /* We have successfully globbed the preceding directory name. For each name we found, call glob_in_dir on it and FILENAME, appending the results to PGLOB. */ for (i = 0; i < dirs.gl_pathc; ++i) { int old_pathc; #ifdef SHELL { /* Make globbing interruptible in the bash shell. */ extern int interrupt_state; if (interrupt_state) { globfree (&dirs); globfree (&files); return GLOB_ABORTED; } } #endif /* SHELL. */ old_pathc = pglob->gl_pathc; status = glob_in_dir (filename, dirs.gl_pathv[i], ((flags | GLOB_APPEND) & ~(GLOB_NOCHECK | GLOB_ERR)), errfunc, pglob); if (status == GLOB_NOMATCH) /* No matches in this directory. Try the next. */ continue; if (status != 0) { globfree (&dirs); globfree (pglob); return status; } /* Stick the directory on the front of each name. */ if (prefix_array (dirs.gl_pathv[i], &pglob->gl_pathv[old_pathc], pglob->gl_pathc - old_pathc)) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } } flags |= GLOB_MAGCHAR; /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. But if we have not found any matching entry and thie GLOB_NOCHECK flag was set we must return the list consisting of the disrectory names followed by the filename. */ if (pglob->gl_pathc == oldcount) { /* No matches. */ if (flags & GLOB_NOCHECK) { size_t filename_len = strlen (filename) + 1; char **new_pathv; struct stat st; /* This is an pessimistic guess about the size. */ pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + dirs.gl_pathc + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) { globfree (&dirs); return GLOB_NOSPACE; } if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (i = 0; i < dirs.gl_pathc; ++i) { const char *dir = dirs.gl_pathv[i]; size_t dir_len = strlen (dir); /* First check whether this really is a directory. */ if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (dir, &st) : __stat (dir, &st)) != 0 || !S_ISDIR (st.st_mode)) /* No directory, ignore this entry. */ continue; pglob->gl_pathv[pglob->gl_pathc] = malloc (dir_len + 1 + filename_len); if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { globfree (&dirs); globfree (pglob); return GLOB_NOSPACE; } #ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len), "/", 1), filename, filename_len); #else memcpy (pglob->gl_pathv[pglob->gl_pathc], dir, dir_len); pglob->gl_pathv[pglob->gl_pathc][dir_len] = '/'; memcpy (&pglob->gl_pathv[pglob->gl_pathc][dir_len + 1], filename, filename_len); #endif ++pglob->gl_pathc; } pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; /* Now we know how large the gl_pathv vector must be. */ new_pathv = (char **) realloc (pglob->gl_pathv, ((pglob->gl_pathc + 1) * sizeof (char *))); if (new_pathv != NULL) pglob->gl_pathv = new_pathv; } else return GLOB_NOMATCH; } globfree (&dirs); } else { status = glob_in_dir (filename, dirname, flags, errfunc, pglob); if (status != 0) return status; if (dirlen > 0) { /* Stick the directory on the front of each name. */ int ignore = oldcount; if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs) ignore = pglob->gl_offs; if (prefix_array (dirname, &pglob->gl_pathv[ignore], pglob->gl_pathc - ignore)) { globfree (pglob); return GLOB_NOSPACE; } } } if (flags & GLOB_MARK) { /* Append slashes to directory names. */ int i; struct stat st; for (i = oldcount; i < pglob->gl_pathc; ++i) if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) : __stat (pglob->gl_pathv[i], &st)) == 0 && S_ISDIR (st.st_mode)) { size_t len = strlen (pglob->gl_pathv[i]) + 2; char *new = realloc (pglob->gl_pathv[i], len); if (new == NULL) { globfree (pglob); return GLOB_NOSPACE; } strcpy (&new[len - 2], "/"); pglob->gl_pathv[i] = new; } } if (!(flags & GLOB_NOSORT)) { /* Sort the vector. */ int non_sort = oldcount; if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount) non_sort = pglob->gl_offs; qsort ((__ptr_t) &pglob->gl_pathv[non_sort], pglob->gl_pathc - non_sort, sizeof (char *), collated_compare); } return 0; } /* Free storage allocated in PGLOB by a previous `glob' call. */ void globfree (pglob) register glob_t *pglob; { if (pglob->gl_pathv != NULL) { register int i; for (i = 0; i < pglob->gl_pathc; ++i) if (pglob->gl_pathv[i] != NULL) free ((__ptr_t) pglob->gl_pathv[i]); free ((__ptr_t) pglob->gl_pathv); } } /* Do a collated comparison of A and B. */ static int collated_compare (a, b) const __ptr_t a; const __ptr_t b; { const char *const s1 = *(const char *const * const) a; const char *const s2 = *(const char *const * const) b; if (s1 == s2) return 0; if (s1 == NULL) return 1; if (s2 == NULL) return -1; return strcoll (s1, s2); } /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's elements in place. Return nonzero if out of memory, zero if successful. A slash is inserted between DIRNAME and each elt of ARRAY, unless DIRNAME is just "/". Each old element of ARRAY is freed. */ static int prefix_array (dirname, array, n) const char *dirname; char **array; size_t n; { register size_t i; size_t dirlen = strlen (dirname); #if defined __MSDOS__ || defined WINDOWS32 int sep_char = '/'; # define DIRSEP_CHAR sep_char #else # define DIRSEP_CHAR '/' #endif if (dirlen == 1 && dirname[0] == '/') /* DIRNAME is just "/", so normal prepending would get us "//foo". We want "/foo" instead, so don't prepend any chars from DIRNAME. */ dirlen = 0; #if defined __MSDOS__ || defined WINDOWS32 else if (dirlen > 1) { if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ --dirlen; else if (dirname[dirlen - 1] == ':') { /* DIRNAME is "d:". Use `:' instead of `/'. */ --dirlen; sep_char = ':'; } } #endif for (i = 0; i < n; ++i) { size_t eltlen = strlen (array[i]) + 1; char *new = (char *) malloc (dirlen + 1 + eltlen); if (new == NULL) { while (i > 0) free ((__ptr_t) array[--i]); return 1; } #ifdef HAVE_MEMPCPY { char *endp = (char *) mempcpy (new, dirname, dirlen); *endp++ = DIRSEP_CHAR; mempcpy (endp, array[i], eltlen); } #else memcpy (new, dirname, dirlen); new[dirlen] = DIRSEP_CHAR; memcpy (&new[dirlen + 1], array[i], eltlen); #endif free ((__ptr_t) array[i]); array[i] = new; } return 0; } /* We must not compile this function twice. */ #if !defined _LIBC || !defined NO_GLOB_PATTERN_P /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ int __glob_pattern_p (pattern, quote) const char *pattern; int quote; { register const char *p; int open = 0; for (p = pattern; *p != '\0'; ++p) switch (*p) { case '?': case '*': return 1; case '\\': if (quote && p[1] != '\0') ++p; break; case '[': open = 1; break; case ']': if (open) return 1; break; } return 0; } # ifdef _LIBC weak_alias (__glob_pattern_p, glob_pattern_p) # endif #endif /* Like `glob', but PATTERN is a final pathname component, and matches are searched for in DIRECTORY. The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. The GLOB_APPEND flag is assumed to be set (always appends). */ static int glob_in_dir (pattern, directory, flags, errfunc, pglob) const char *pattern; const char *directory; int flags; int (*errfunc) __P ((const char *, int)); glob_t *pglob; { __ptr_t stream = NULL; struct globlink { struct globlink *next; char *name; }; struct globlink *names = NULL; size_t nfound; int meta; int save; #ifdef VMS if (*directory == 0) directory = "[]"; #endif meta = __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); if (meta == 0) { if (flags & (GLOB_NOCHECK|GLOB_NOMAGIC)) /* We need not do any tests. The PATTERN contains no meta characters and we must not return an error therefore the result will always contain exactly one name. */ flags |= GLOB_NOCHECK; else { /* Since we use the normal file functions we can also use stat() to verify the file is there. */ struct stat st; size_t patlen = strlen (pattern); size_t dirlen = strlen (directory); char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); # ifdef HAVE_MEMPCPY mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), "/", 1), pattern, patlen + 1); # else memcpy (fullname, directory, dirlen); fullname[dirlen] = '/'; memcpy (&fullname[dirlen + 1], pattern, patlen + 1); # endif if (((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_stat) (fullname, &st) : __stat (fullname, &st)) == 0) /* We found this file to be existing. Now tell the rest of the function to copy this name into the result. */ flags |= GLOB_NOCHECK; } nfound = 0; } else { if (pattern[0] == '\0') { /* This is a special case for matching directories like in "*a/". */ names = (struct globlink *) __alloca (sizeof (struct globlink)); names->name = (char *) malloc (1); if (names->name == NULL) goto memory_error; names->name[0] = '\0'; names->next = NULL; nfound = 1; meta = 0; } else { stream = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_opendir) (directory) : (__ptr_t) opendir (directory)); if (stream == NULL) { if (errno != ENOTDIR && ((errfunc != NULL && (*errfunc) (directory, errno)) || (flags & GLOB_ERR))) return GLOB_ABORTED; nfound = 0; meta = 0; } else { int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) #if defined HAVE_CASE_INSENSITIVE_FS | FNM_CASEFOLD #endif ); nfound = 0; flags |= GLOB_MAGCHAR; while (1) { const char *name; size_t len; struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ? (*pglob->gl_readdir) (stream) : readdir ((DIR *) stream)); if (d == NULL) break; if (! REAL_DIR_ENTRY (d)) continue; #ifdef HAVE_D_TYPE /* If we shall match only directories use the information provided by the dirent call if possible. */ if ((flags & GLOB_ONLYDIR) && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) continue; #endif name = d->d_name; if (fnmatch (pattern, name, fnm_flags) == 0) { struct globlink *new = (struct globlink *) __alloca (sizeof (struct globlink)); len = NAMLEN (d); new->name = (char *) malloc (len + 1); if (new->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy ((__ptr_t) new->name, name, len)) = '\0'; #else memcpy ((__ptr_t) new->name, name, len); new->name[len] = '\0'; #endif new->next = names; names = new; ++nfound; } } } } } if (nfound == 0 && (flags & GLOB_NOCHECK)) { size_t len = strlen (pattern); nfound = 1; names = (struct globlink *) __alloca (sizeof (struct globlink)); names->next = NULL; names->name = (char *) malloc (len + 1); if (names->name == NULL) goto memory_error; #ifdef HAVE_MEMPCPY *((char *) mempcpy (names->name, pattern, len)) = '\0'; #else memcpy (names->name, pattern, len); names->name[len] = '\0'; #endif } if (nfound != 0) { pglob->gl_pathv = (char **) realloc (pglob->gl_pathv, (pglob->gl_pathc + ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) + nfound + 1) * sizeof (char *)); if (pglob->gl_pathv == NULL) goto memory_error; if (flags & GLOB_DOOFFS) while (pglob->gl_pathc < pglob->gl_offs) pglob->gl_pathv[pglob->gl_pathc++] = NULL; for (; names != NULL; names = names->next) pglob->gl_pathv[pglob->gl_pathc++] = names->name; pglob->gl_pathv[pglob->gl_pathc] = NULL; pglob->gl_flags = flags; } save = errno; if (stream != NULL) { if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); } __set_errno (save); return nfound == 0 ? GLOB_NOMATCH : 0; memory_error: { int save = errno; if (flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir) (stream); else closedir ((DIR *) stream); __set_errno (save); } while (names != NULL) { if (names->name != NULL) free ((__ptr_t) names->name); names = names->next; } return GLOB_NOSPACE; } #endif /* Not ELIDE_CODE. */ remake-4.1+dbg1.3~dfsg.1/glob/glob.h000066400000000000000000000164471317072305000170260ustar00rootroot00000000000000/* Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _GLOB_H #define _GLOB_H 1 #ifdef __cplusplus extern "C" { #endif #undef __ptr_t #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ # undef __P # undef __PMT # define __P(protos) protos # define __PMT(protos) protos # if !defined __GNUC__ || __GNUC__ < 2 # undef __const # define __const const # endif # endif # define __ptr_t void * #else /* Not C++ or ANSI C. */ # undef __P # undef __PMT # define __P(protos) () # define __PMT(protos) () # undef __const # define __const # define __ptr_t char * #endif /* C++ or ANSI C. */ /* We need `size_t' for the following definitions. */ #ifndef __size_t # if defined __FreeBSD__ # define __size_t size_t # else # if defined __GNUC__ && __GNUC__ >= 2 typedef __SIZE_TYPE__ __size_t; # else /* This is a guess. */ /*hb * Conflicts with DECCs already defined type __size_t. * Defining an own type with a name beginning with '__' is no good. * Anyway if DECC is used and __SIZE_T is defined then __size_t is * already defined (and I hope it's exactly the one we need here). */ # if !(defined __DECC && defined __SIZE_T) typedef unsigned long int __size_t; # endif # endif # endif #else /* The GNU CC stddef.h version defines __size_t as empty. We need a real definition. */ # undef __size_t # define __size_t size_t #endif /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ #define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ #define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ #define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ #define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ #define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ #define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ #if (!defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _BSD_SOURCE \ || defined _GNU_SOURCE) # define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ # define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ # define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ # define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ # define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ # define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ # define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error if the user name is not available. */ # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) #else # define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ GLOB_PERIOD) #endif /* Error returns from `glob'. */ #define GLOB_NOSPACE 1 /* Ran out of memory. */ #define GLOB_ABORTED 2 /* Read error. */ #define GLOB_NOMATCH 3 /* No matches found. */ #define GLOB_NOSYS 4 /* Not implemented. */ #ifdef _GNU_SOURCE /* Previous versions of this file defined GLOB_ABEND instead of GLOB_ABORTED. Provide a compatibility definition here. */ # define GLOB_ABEND GLOB_ABORTED #endif /* Structure describing a globbing run. */ #if !defined _AMIGA && !defined VMS /* Buggy compiler. */ struct stat; #endif typedef struct { __size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat *)); #if defined(VMS) && defined(__DECC) && !defined(_POSIX_C_SOURCE) int (*gl_stat) __PMT ((__const char *, struct stat *, ...)); #else int (*gl_stat) __PMT ((__const char *, struct stat *)); #endif } glob_t; #ifdef _LARGEFILE64_SOURCE struct stat64; typedef struct { __size_t gl_pathc; char **gl_pathv; __size_t gl_offs; int gl_flags; /* If the GLOB_ALTDIRFUNC flag is set, the following functions are used instead of the normal file access functions. */ void (*gl_closedir) __PMT ((void *)); struct dirent64 *(*gl_readdir) __PMT ((void *)); __ptr_t (*gl_opendir) __PMT ((__const char *)); int (*gl_lstat) __PMT ((__const char *, struct stat64 *)); int (*gl_stat) __PMT ((__const char *, struct stat64 *)); } glob64_t; #endif #if _FILE_OFFSET_BITS == 64 && __GNUC__ < 2 # define glob glob64 # define globfree globfree64 #else # ifdef _LARGEFILE64_SOURCE extern int glob64 __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob64_t *__pglob)); extern void globfree64 __P ((glob64_t *__pglob)); # endif #endif /* Do glob searching for PATTERN, placing results in PGLOB. The bits defined above may be set in FLAGS. If a directory cannot be opened or read and ERRFUNC is not nil, it is called with the pathname that caused the error, and the `errno' value from the failing call; if it returns non-zero `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. Otherwise, `glob' returns zero. */ #if _FILE_OFFSET_BITS != 64 || __GNUC__ < 2 extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)); /* Free storage allocated in PGLOB by a previous `glob' call. */ extern void globfree __P ((glob_t *__pglob)); #else extern int glob __P ((__const char *__pattern, int __flags, int (*__errfunc) (__const char *, int), glob_t *__pglob)) __asm__ ("glob64"); extern void globfree __P ((glob_t *__pglob)) __asm__ ("globfree64"); #endif #ifdef _GNU_SOURCE /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. This function is not part of the interface specified by POSIX.2 but several programs want to use it. */ extern int glob_pattern_p __P ((__const char *__pattern, int __quote)); #endif #ifdef __cplusplus } #endif #endif /* glob.h */ remake-4.1+dbg1.3~dfsg.1/globals.c000066400000000000000000000073651317072305000165750ustar00rootroot00000000000000#include "types.h" #include "globals.h" int env_overrides = 0; /* Nonzero means ignore status codes returned by commands executed to remake files. Just treat them all as successful (-i). */ int ignore_errors_flag = 0; /* Nonzero means don't remake anything, just print the data base that results from reading the makefile (-p). */ int print_data_base_flag = 0; /* Nonzero means don't remake anything; just return a nonzero status if the specified targets are not up to date (-q). */ int question_flag = 0; /* Nonzero means do not use any of the builtin rules (-r) / variables (-R). */ int no_builtin_rules_flag = 0; int no_builtin_variables_flag = 0; /* Nonzero means check symlink mtimes. */ int check_symlink_flag = 0; /* Nonzero means print directory before starting and when done (-w). */ int print_directory_flag = 0; /* Nonzero means print version information. */ int print_version_flag = 0; /*! Nonzero means --trace and shell trace with input. */ int shell_trace = 0; /* Nonzero means profile calls (option --profile). */ int profile_flag = 0; /* Nonzero means do extra verification (that may slow things down). */ int verify_flag; /* Nonzero means do not print commands to be executed (-s). */ int silent_flag; /* Nonzero means just touch the files that would appear to need remaking (-t) */ int touch_flag; /* Nonzero means just print what commands would need to be executed, don't actually execute them (-n). */ int just_print_flag; /*! If 1, we don't give additional error reporting information. */ int no_extended_errors = 0; int db_level = 0; /*! Value of the MAKELEVEL variable at startup (or 0). */ unsigned int makelevel; /*! Nonzero gives a list of explicit target names and exits. Set by option --targets */ int show_targets_flag = 0; /*! Nonzero gives a list of explicit target names that have commands associated with them and exits. Set by option --tasks */ int show_tasks_flag = 0; /*! If 1, same as --debugger=preaction */ int debugger_flag; /* If nonzero, we should print a warning message for each reference to an undefined variable. */ int warn_undefined_variables_flag; /** True if we are inside the debugger, false otherwise. */ int in_debugger = false; /*! Nonzero if we have seen the magic '.POSIX' target. This turns on pedantic compliance with POSIX.2. */ int posix_pedantic; /*! If nonzero, we are debugging after each "step" for that many times. When we have a value 1, then we actually run the debugger read loop. Otherwise we decrement the step count. */ unsigned int i_debugger_stepping = 0; /*! If nonzero, we are debugging after each "next" for that many times. When we have a value 1, then we actually run the debugger read loop. Otherwise we decrement the step count. */ unsigned int i_debugger_nexting = 0; /*! If nonzero, enter the debugger if we hit a fatal error. */ unsigned int debugger_on_error = 0; /*! If nonzero, we have requested some sort of debugging. */ unsigned int debugger_enabled; /*! If true, enter the debugger before reading any makefiles. */ bool b_debugger_preread = false; /* This character introduces a command: it's the first char on the line. */ char cmd_prefix = '\t'; /*! Our current directory after processing all -C options. */ char *starting_directory; /* One of OUTPUT_SYNC_* if the "--output-sync" option was given. This attempts to synchronize the output of parallel jobs such that the results of each job stay together. */ int output_sync = OUTPUT_SYNC_NONE; const char *default_shell; char *remote_description = 0; /* Remember the original value of the SHELL variable, from the environment. */ struct variable shell_var; /* The filename and pointer to line number of the makefile currently being read in. */ const gmk_floc *reading_file = 0; remake-4.1+dbg1.3~dfsg.1/globals.h000066400000000000000000000050261317072305000165720ustar00rootroot00000000000000#ifndef GLOBALS_H #define GLOBALS_H #include "types.h" #include "variable.h" #define OUTPUT_SYNC_NONE 0 #define OUTPUT_SYNC_LINE 1 #define OUTPUT_SYNC_TARGET 2 #define OUTPUT_SYNC_RECURSE 3 extern int env_overrides; /* Nonzero means ignore status codes returned by commands executed to remake files. Just treat them all as successful (-i). */ extern int ignore_errors_flag; /* Nonzero means don't remake anything, just print the data base that results from reading the makefile (-p). */ extern int print_data_base_flag; /* Nonzero means don't remake anything; just return a nonzero status if the specified targets are not up to date (-q). */ extern int question_flag; /* Nonzero means do not use any of the builtin rules (-r) / variables (-R). */ extern int no_builtin_rules_flag; extern int no_builtin_variables_flag; /* Nonzero means check symlink mtimes. */ extern int check_symlink_flag; /* Nonzero means print directory before starting and when done (-w). */ extern int print_directory_flag; /* Nonzero means print version information. */ extern int print_version_flag; /*! Nonzero means --trace and shell trace with input. */ extern int shell_trace; /* Nonzero means profile calls (option --profile). */ extern int profile_flag; /* Nonzero means do extra verification (that may slow things down). */ extern int verify_flag; /* Nonzero means do not print commands to be executed (-s). */ extern int silent_flag; /* Nonzero means just touch the files that would appear to need remaking (-t) */ extern int touch_flag; /* Nonzero means just print what commands would need to be executed, don't actually execute them (-n). */ extern int just_print_flag; /*! If 1, we don't give additional error reporting information. */ extern int no_extended_errors; extern int db_level; /*! Value of the MAKELEVEL variable at startup (or 0). */ extern unsigned int makelevel; /*! Nonzero gives a list of explicit target names and exits. Set by option --targets */ extern int show_targets_flag; /*! Nonzero gives a list of explicit target names that have commands associated with them and exits. Set by option --tasks */ extern int show_tasks_flag; /*! If 1, same as --debugger=preaction */ extern int debugger_flag; /** True if we are inside the debugger, false otherwise. */ extern int in_debugger; /*! If true, enter the debugger before reading any makefiles. */ extern bool b_debugger_preread; /* Remember the original value of the SHELL variable, from the environment. */ struct variable shell_var; #endif /*GLOBALS_H*/ remake-4.1+dbg1.3~dfsg.1/gmk-default.h000066400000000000000000000015101317072305000173410ustar00rootroot00000000000000static const char *const GUILE_module_defn = " \ (define (to-string-maybe x) \ (cond \ ((or (not x) \ (unspecified? x) \ (variable? x) \ (null? x) \ (and (string? x) (string-null? x))) \ #f) \ ((eq? x #t) \"#t\") \ ((or (symbol? x) (number? x)) \ (object->string x)) \ ((char? x) \ (string x)) \ ((and (string? x) (string-every char-set:printing x)) \ x) \ (else (error \"Unknown object:\" x)))) \ (define (obj-to-str x) \ (let ((acc '())) \ (define (walk x) \ (cond ((pair? x) (walk (car x)) (walk (cdr x))) \ ((to-string-maybe x) => (lambda (s) (set! acc (cons s acc)))))) \ (walk x) \ (string-join (reverse! acc)))) \ (define (gmk-var v) \ (gmk-expand (format #f \"$(~a)\" (obj-to-str v)))) \ (export gmk-expand gmk-eval gmk-var) \ "; remake-4.1+dbg1.3~dfsg.1/gmk-default.scm000066400000000000000000000033551317072305000177050ustar00rootroot00000000000000;; Contents of the (gnu make) Guile module ;; Copyright (C) 2011-2014 Free Software Foundation, Inc. ;; This file is part of GNU Make. ;; ;; GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ;; FOR A PARTICULAR PURPOSE. See the GNU 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 (to-string-maybe x) (cond ;; In GNU make, "false" is the empty string ((or (not x) (unspecified? x) (variable? x) (null? x) (and (string? x) (string-null? x))) #f) ;; We want something not false... not sure about this ((eq? x #t) "#t") ;; Basics ((or (symbol? x) (number? x)) (object->string x)) ((char? x) (string x)) ;; Printable string (no special characters) ((and (string? x) (string-every char-set:printing x)) x) ;; No idea: fail (else (error "Unknown object:" x)))) (define (obj-to-str x) (let ((acc '())) (define (walk x) (cond ((pair? x) (walk (car x)) (walk (cdr x))) ((to-string-maybe x) => (lambda (s) (set! acc (cons s acc)))))) (walk x) (string-join (reverse! acc)))) ;; Return the value of the GNU make variable V (define (gmk-var v) (gmk-expand (format #f "$(~a)" (obj-to-str v)))) ;; Export the public interfaces (export gmk-expand gmk-eval gmk-var) remake-4.1+dbg1.3~dfsg.1/gnumake.h000066400000000000000000000055651317072305000166060ustar00rootroot00000000000000/* External interfaces usable by dynamic objects loaded into GNU Make. --THIS API IS A "TECHNOLOGY PREVIEW" ONLY. IT IS NOT A STABLE INTERFACE-- Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _REMAKE_GNUMAKE_H_ #define _REMAKE_GNUMAKE_H_ /* Specify the location of elements read from makefiles. */ typedef struct { const char *filenm; unsigned long lineno; } gmk_floc; typedef char *(*gmk_func_ptr)(const char *nm, unsigned int argc, char **argv); #ifdef _WIN32 # ifdef GMK_BUILDING_MAKE # define GMK_EXPORT __declspec(dllexport) # else # define GMK_EXPORT __declspec(dllimport) # endif #else # define GMK_EXPORT #endif /* Free memory returned by the gmk_expand() function. */ GMK_EXPORT void gmk_free (char *str); /* Allocate memory in GNU make's context. */ GMK_EXPORT char *gmk_alloc (unsigned int len); /* Run $(eval ...) on the provided string BUFFER. */ GMK_EXPORT void gmk_eval (const char *buffer, const gmk_floc *floc); /* Run GNU make expansion on the provided string STR. Returns an allocated buffer that the caller must free with gmk_free(). */ GMK_EXPORT char *gmk_expand (const char *str); /* Register a new GNU make function NAME (maximum of 255 chars long). When the function is expanded in the makefile, FUNC will be invoked with the appropriate arguments. The return value of FUNC must be either NULL, in which case it expands to the empty string, or a pointer to the result of the expansion in a string created by gmk_alloc(). GNU make will free the memory when it's done. MIN_ARGS is the minimum number of arguments the function requires. MAX_ARGS is the maximum number of arguments (or 0 if there's no maximum). MIN_ARGS and MAX_ARGS may not exceed 255. The FLAGS value may be GMK_FUNC_DEFAULT, or one or more of the following flags OR'd together: GMK_FUNC_NOEXPAND: the arguments to the function will be not be expanded before FUNC is called. */ GMK_EXPORT void gmk_add_function (const char *name, gmk_func_ptr func, unsigned int min_args, unsigned int max_args, unsigned int flags); #define GMK_FUNC_DEFAULT 0x00 #define GMK_FUNC_NOEXPAND 0x01 #endif /* _REMAKE_GNUMAKE_H_ */ remake-4.1+dbg1.3~dfsg.1/guile.c000066400000000000000000000076571317072305000162630ustar00rootroot00000000000000/* GNU Guile interface for GNU Make. Copyright (C) 2011-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #ifdef HAVE_GUILE #include "gnumake.h" #include "debug.h" #include "filedef.h" #include "dep.h" #include "variable.h" #include /* Pre-2.0 versions of Guile don't have a typedef for gsubr function types. */ #if SCM_MAJOR_VERSION < 2 # define GSUBR_TYPE SCM (*) () /* Guile 1.x doesn't really support i18n. */ # define EVAL_STRING(_s) scm_c_eval_string (_s) #else # define GSUBR_TYPE scm_t_subr # define EVAL_STRING(_s) scm_eval_string (scm_from_utf8_string (_s)) #endif static SCM make_mod = SCM_EOL; static SCM obj_to_str = SCM_EOL; /* Convert an SCM object into a string. */ static char * cvt_scm_to_str (SCM obj) { return scm_to_locale_string (scm_call_1 (obj_to_str, obj)); } /* Perform the GNU make expansion function. */ static SCM guile_expand_wrapper (SCM obj) { char *str = cvt_scm_to_str (obj); SCM ret; char *res; DB (DB_BASIC, (_("guile: Expanding '%s'\n"), str)); res = gmk_expand (str); ret = scm_from_locale_string (res); free (str); free (res); return ret; } /* Perform the GNU make eval function. */ static SCM guile_eval_wrapper (SCM obj) { char *str = cvt_scm_to_str (obj); DB (DB_BASIC, (_("guile: Evaluating '%s'\n"), str)); gmk_eval (str, 0); return SCM_BOOL_F; } /* Invoked by scm_c_define_module(), in the context of the GNU make module. */ static void guile_define_module (void *data UNUSED) { /* Ingest the predefined Guile module for GNU make. */ #include "gmk-default.h" /* Register a subr for GNU make's eval capability. */ scm_c_define_gsubr ("gmk-expand", 1, 0, 0, (GSUBR_TYPE) guile_expand_wrapper); /* Register a subr for GNU make's eval capability. */ scm_c_define_gsubr ("gmk-eval", 1, 0, 0, (GSUBR_TYPE) guile_eval_wrapper); /* Define the rest of the module. */ scm_c_eval_string (GUILE_module_defn); } /* Initialize the GNU make Guile module. */ static void * guile_init (void *arg UNUSED) { /* Define the module. */ make_mod = scm_c_define_module ("gnu make", guile_define_module, NULL); /* Get a reference to the object-to-string translator, for later. */ obj_to_str = scm_variable_ref (scm_c_module_lookup (make_mod, "obj-to-str")); /* Import the GNU make module exports into the generic space. */ scm_c_eval_string ("(use-modules (gnu make))"); return NULL; } static void * internal_guile_eval (void *arg) { return cvt_scm_to_str (EVAL_STRING (arg)); } /* This is the function registered with make */ static char * func_guile (const char *funcname UNUSED, unsigned int argc UNUSED, char **argv) { static int init = 0; if (! init) { /* Initialize the Guile interpreter. */ scm_with_guile (guile_init, NULL); init = 1; } if (argv[0] && argv[0][0] != '\0') return scm_with_guile (internal_guile_eval, argv[0]); return NULL; } /* ----- Public interface ----- */ /* We could send the flocp to define_new_function(), but since guile is "kind of" built-in, that didn't seem so useful. */ int guile_gmake_setup (const gmk_floc *flocp UNUSED) { /* Create a make function "guile". */ gmk_add_function ("guile", func_guile, 0, 1, GMK_FUNC_DEFAULT); return 1; } #else int guile_gmake_setup (const gmk_floc *flocp UNUSED) { return 1; } #endif remake-4.1+dbg1.3~dfsg.1/hash.c000066400000000000000000000200661317072305000160660ustar00rootroot00000000000000/* hash.c -- hash table maintenance Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "hash.h" #define CALLOC(t, n) ((t *) xcalloc (sizeof (t) * (n))) #define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n))) #define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n))) #define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n))) static void hash_rehash __P((struct hash_table* ht)); static unsigned long round_up_2 __P((unsigned long rough)); /* Implement double hashing with open addressing. The table size is always a power of two. The secondary ('increment') hash function is forced to return an odd-value, in order to be relatively prime to the table size. This guarantees that the increment can potentially hit every slot in the table during collision resolution. */ void *hash_deleted_item = &hash_deleted_item; /* Force the table size to be a power of two, possibly rounding up the given size. */ void hash_init (struct hash_table *ht, unsigned long size, hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp) { ht->ht_size = round_up_2 (size); ht->ht_empty_slots = ht->ht_size; ht->ht_vec = (void**) CALLOC (struct token *, ht->ht_size); if (ht->ht_vec == 0) { fprintf (stderr, _("can't allocate %lu bytes for hash table: memory exhausted"), ht->ht_size * (unsigned long) sizeof (struct token *)); exit (MAKE_TROUBLE); } ht->ht_capacity = ht->ht_size - (ht->ht_size / 16); /* 93.75% loading factor */ ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_hash_1 = hash_1; ht->ht_hash_2 = hash_2; ht->ht_compare = hash_cmp; } /* Load an array of items into 'ht'. */ void hash_load (struct hash_table *ht, void *item_table, unsigned long cardinality, unsigned long size) { char *items = (char *) item_table; while (cardinality--) { hash_insert (ht, items); items += size; } } /* Returns the address of the table slot matching 'key'. If 'key' is not found, return the address of an empty slot suitable for inserting 'key'. The caller is responsible for incrementing ht_fill on insertion. */ void ** hash_find_slot (struct hash_table *ht, const void *key) { void **slot; void **deleted_slot = 0; unsigned int hash_2 = 0; unsigned int hash_1 = (*ht->ht_hash_1) (key); ht->ht_lookups++; for (;;) { hash_1 &= (ht->ht_size - 1); slot = &ht->ht_vec[hash_1]; if (*slot == 0) return (deleted_slot ? deleted_slot : slot); if (*slot == hash_deleted_item) { if (deleted_slot == 0) deleted_slot = slot; } else { if (key == *slot) return slot; if ((*ht->ht_compare) (key, *slot) == 0) return slot; ht->ht_collisions++; } if (!hash_2) hash_2 = (*ht->ht_hash_2) (key) | 1; hash_1 += hash_2; } } void * hash_find_item (struct hash_table *ht, const void *key) { void **slot = hash_find_slot (ht, key); return ((HASH_VACANT (*slot)) ? 0 : *slot); } void * hash_insert (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); const void *old_item = *slot; hash_insert_at (ht, item, slot); return (void *)((HASH_VACANT (old_item)) ? 0 : old_item); } void * hash_insert_at (struct hash_table *ht, const void *item, const void *slot) { const void *old_item = *(void **) slot; if (HASH_VACANT (old_item)) { ht->ht_fill++; if (old_item == 0) ht->ht_empty_slots--; old_item = item; } *(void const **) slot = item; if (ht->ht_empty_slots < ht->ht_size - ht->ht_capacity) { hash_rehash (ht); return (void *) hash_find_slot (ht, item); } else return (void *) slot; } void * hash_delete (struct hash_table *ht, const void *item) { void **slot = hash_find_slot (ht, item); return hash_delete_at (ht, slot); } void * hash_delete_at (struct hash_table *ht, const void *slot) { void *item = *(void **) slot; if (!HASH_VACANT (item)) { *(void const **) slot = hash_deleted_item; ht->ht_fill--; return item; } else return 0; } void hash_free_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) { void *item = *vec; if (!HASH_VACANT (item)) free (item); *vec = 0; } ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } void hash_delete_items (struct hash_table *ht) { void **vec = ht->ht_vec; void **end = &vec[ht->ht_size]; for (; vec < end; vec++) *vec = 0; ht->ht_fill = 0; ht->ht_collisions = 0; ht->ht_lookups = 0; ht->ht_rehashes = 0; ht->ht_empty_slots = ht->ht_size; } void hash_free (struct hash_table *ht, int free_items) { if (free_items) hash_free_items (ht); else { ht->ht_fill = 0; ht->ht_empty_slots = ht->ht_size; } free (ht->ht_vec); ht->ht_vec = 0; ht->ht_capacity = 0; } void hash_map (struct hash_table *ht, hash_map_func_t map) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot); } } void hash_map_arg (struct hash_table *ht, hash_map_arg_func_t map, void *arg) { void **slot; void **end = &ht->ht_vec[ht->ht_size]; for (slot = ht->ht_vec; slot < end; slot++) { if (!HASH_VACANT (*slot)) (*map) (*slot, arg); } } /* Double the size of the hash table in the event of overflow... */ static void hash_rehash (struct hash_table *ht) { unsigned long old_ht_size = ht->ht_size; void **old_vec = ht->ht_vec; void **ovp; if (ht->ht_fill >= ht->ht_capacity) { ht->ht_size *= 2; ht->ht_capacity = ht->ht_size - (ht->ht_size >> 4); } ht->ht_rehashes++; ht->ht_vec = (void **) CALLOC (struct token *, ht->ht_size); for (ovp = old_vec; ovp < &old_vec[old_ht_size]; ovp++) { if (! HASH_VACANT (*ovp)) { void **slot = hash_find_slot (ht, *ovp); *slot = *ovp; } } ht->ht_empty_slots = ht->ht_size - ht->ht_fill; free (old_vec); } void hash_print_stats (struct hash_table *ht, FILE *out_FILE) { /* GKM FIXME: honor NO_FLOAT */ fprintf (out_FILE, _("Load=%ld/%ld=%.0f%%, "), ht->ht_fill, ht->ht_size, 100.0 * (double) ht->ht_fill / (double) ht->ht_size); fprintf (out_FILE, _("Rehash=%d, "), ht->ht_rehashes); fprintf (out_FILE, _("Collisions=%ld/%ld=%.0f%%"), ht->ht_collisions, ht->ht_lookups, (ht->ht_lookups ? (100.0 * (double) ht->ht_collisions / (double) ht->ht_lookups) : 0)); } /* Dump all items into a NULL-terminated vector. Use the user-supplied vector, or malloc one. */ void ** hash_dump (struct hash_table *ht, void **vector_0, qsort_cmp_t compare) { void **vector; void **slot; void **end = &ht->ht_vec[ht->ht_size]; if (vector_0 == 0) vector_0 = MALLOC (void *, ht->ht_fill + 1); vector = vector_0; for (slot = ht->ht_vec; slot < end; slot++) if (!HASH_VACANT (*slot)) *vector++ = *slot; *vector = 0; if (compare) qsort (vector_0, ht->ht_fill, sizeof (void *), compare); return vector_0; } /* Round a given number up to the nearest power of 2. */ static unsigned long round_up_2 (unsigned long n) { n |= (n >> 1); n |= (n >> 2); n |= (n >> 4); n |= (n >> 8); n |= (n >> 16); #if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295 /* We only need this on systems where unsigned long is >32 bits. */ n |= (n >> 32); #endif return n + 1; } remake-4.1+dbg1.3~dfsg.1/hash.h000066400000000000000000000205511317072305000160720ustar00rootroot00000000000000/* hash.h -- decls for hash table Copyright (C) 1995, 1999, 2002, 2010 Free Software Foundation, Inc. Written by Greg McGary GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _hash_h_ #define _hash_h_ #include #include #if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 # if !defined __GLIBC__ || !defined __P # undef __P # define __P(protos) protos # endif #else /* Not C++ or ANSI C. */ # undef __P # define __P(protos) () /* We can get away without defining 'const' here only because in this file it is used only inside the prototype for 'fnmatch', which is elided in non-ANSI C where 'const' is problematical. */ #endif /* C++ or ANSI C. */ typedef unsigned long (*hash_func_t) __P((void const *key)); typedef int (*hash_cmp_func_t) __P((void const *x, void const *y)); typedef void (*hash_map_func_t) __P((void const *item)); typedef void (*hash_map_arg_func_t) __P((void const *item, void *arg)); struct hash_table { void **ht_vec; hash_func_t ht_hash_1; /* primary hash function */ hash_func_t ht_hash_2; /* secondary hash function */ hash_cmp_func_t ht_compare; /* comparison function */ unsigned long ht_size; /* total number of slots (power of 2) */ unsigned long ht_capacity; /* usable slots, limited by loading-factor */ unsigned long ht_fill; /* items in table */ unsigned long ht_empty_slots; /* empty slots not including deleted slots */ unsigned long ht_collisions; /* # of failed calls to comparison function */ unsigned long ht_lookups; /* # of queries */ unsigned int ht_rehashes; /* # of times we've expanded table */ }; typedef int (*qsort_cmp_t) __P((void const *, void const *)); void hash_init __P((struct hash_table *ht, unsigned long size, hash_func_t hash_1, hash_func_t hash_2, hash_cmp_func_t hash_cmp)); void hash_load __P((struct hash_table *ht, void *item_table, unsigned long cardinality, unsigned long size)); void **hash_find_slot __P((struct hash_table *ht, void const *key)); void *hash_find_item __P((struct hash_table *ht, void const *key)); void *hash_insert __P((struct hash_table *ht, const void *item)); void *hash_insert_at __P((struct hash_table *ht, const void *item, void const *slot)); void *hash_delete __P((struct hash_table *ht, void const *item)); void *hash_delete_at __P((struct hash_table *ht, void const *slot)); void hash_delete_items __P((struct hash_table *ht)); void hash_free_items __P((struct hash_table *ht)); void hash_free __P((struct hash_table *ht, int free_items)); void hash_map __P((struct hash_table *ht, hash_map_func_t map)); void hash_map_arg __P((struct hash_table *ht, hash_map_arg_func_t map, void *arg)); void hash_print_stats __P((struct hash_table *ht, FILE *out_FILE)); void **hash_dump __P((struct hash_table *ht, void **vector_0, qsort_cmp_t compare)); extern void *hash_deleted_item; #define HASH_VACANT(item) ((item) == 0 || (void *) (item) == hash_deleted_item) /* hash and comparison macros for case-sensitive string keys. */ /* Due to the strcache, it's not uncommon for the string pointers to be identical. Take advantage of that to short-circuit string compares. */ #define STRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0xf)); \ } while (0) #define return_STRING_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ STRING_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define STRING_HASH_2(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0x7)); \ } while (0) #define return_STRING_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ STRING_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define STRING_COMPARE(X, Y, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) #define return_STRING_COMPARE(X, Y) do { \ return (X) == (Y) ? 0 : strcmp ((X), (Y)); \ } while (0) #define STRING_N_HASH_1(KEY, N, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ int _n_ = (N); \ if (_n_) \ while (--_n_ && *++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0xf)); \ (RESULT) += *++_key_; \ } while (0) #define return_STRING_N_HASH_1(KEY, N) do { \ unsigned long _result_ = 0; \ STRING_N_HASH_1 ((KEY), (N), _result_); \ return _result_; \ } while (0) #define STRING_N_HASH_2(KEY, N, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ int _n_ = (N); \ if (_n_) \ while (--_n_ && *++_key_) \ (RESULT) += (*_key_ << (_key_[1] & 0x7)); \ (RESULT) += *++_key_; \ } while (0) #define return_STRING_N_HASH_2(KEY, N) do { \ unsigned long _result_ = 0; \ STRING_N_HASH_2 ((KEY), (N), _result_); \ return _result_; \ } while (0) #define STRING_N_COMPARE(X, Y, N, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #define return_STRING_N_COMPARE(X, Y, N) do { \ return (X) == (Y) ? 0 : strncmp ((X), (Y), (N)); \ } while (0) #ifdef HAVE_CASE_INSENSITIVE_FS /* hash and comparison macros for case-insensitive string _key_s. */ #define ISTRING_HASH_1(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0xf)); \ } while (0) #define return_ISTRING_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ ISTRING_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define ISTRING_HASH_2(KEY, RESULT) do { \ unsigned char const *_key_ = (unsigned char const *) (KEY) - 1; \ while (*++_key_) \ (RESULT) += ((isupper (*_key_) ? tolower (*_key_) : *_key_) << (_key_[1] & 0x7)); \ } while (0) #define return_ISTRING_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ ISTRING_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define ISTRING_COMPARE(X, Y, RESULT) do { \ RESULT = (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #define return_ISTRING_COMPARE(X, Y) do { \ return (X) == (Y) ? 0 : strcasecmp ((X), (Y)); \ } while (0) #else #define ISTRING_HASH_1(KEY, RESULT) STRING_HASH_1 ((KEY), (RESULT)) #define return_ISTRING_HASH_1(KEY) return_STRING_HASH_1 (KEY) #define ISTRING_HASH_2(KEY, RESULT) STRING_HASH_2 ((KEY), (RESULT)) #define return_ISTRING_HASH_2(KEY) return_STRING_HASH_2 (KEY) #define ISTRING_COMPARE(X, Y, RESULT) STRING_COMPARE ((X), (Y), (RESULT)) #define return_ISTRING_COMPARE(X, Y) return_STRING_COMPARE ((X), (Y)) #endif /* hash and comparison macros for integer _key_s. */ #define INTEGER_HASH_1(KEY, RESULT) do { \ (RESULT) += ((unsigned long)(KEY)); \ } while (0) #define return_INTEGER_HASH_1(KEY) do { \ unsigned long _result_ = 0; \ INTEGER_HASH_1 ((KEY), _result_); \ return _result_; \ } while (0) #define INTEGER_HASH_2(KEY, RESULT) do { \ (RESULT) += ~((unsigned long)(KEY)); \ } while (0) #define return_INTEGER_HASH_2(KEY) do { \ unsigned long _result_ = 0; \ INTEGER_HASH_2 ((KEY), _result_); \ return _result_; \ } while (0) #define INTEGER_COMPARE(X, Y, RESULT) do { \ (RESULT) = X - Y; \ } while (0) #define return_INTEGER_COMPARE(X, Y) do { \ int _result_; \ INTEGER_COMPARE (X, Y, _result_); \ return _result_; \ } while (0) /* hash and comparison macros for address keys. */ #define ADDRESS_HASH_1(KEY, RESULT) INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3, (RESULT)) #define ADDRESS_HASH_2(KEY, RESULT) INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3, (RESULT)) #define ADDRESS_COMPARE(X, Y, RESULT) INTEGER_COMPARE ((X), (Y), (RESULT)) #define return_ADDRESS_HASH_1(KEY) return_INTEGER_HASH_1 (((unsigned long)(KEY)) >> 3) #define return_ADDRESS_HASH_2(KEY) return_INTEGER_HASH_2 (((unsigned long)(KEY)) >> 3) #define return_ADDRESS_COMPARE(X, Y) return_INTEGER_COMPARE ((X), (Y)) #endif /* not _hash_h_ */ remake-4.1+dbg1.3~dfsg.1/htdocs/000077500000000000000000000000001317072305000162575ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/htdocs/.gitignore000066400000000000000000000000041317072305000202410ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/htdocs/index.html000066400000000000000000000123341317072305000202570ustar00rootroot00000000000000 http://bashdb.sourceforge.net/remake/remake.html/ Remake - GNU Make with comprehensible tracing and a debugger

Remake – GNU Make with comprehensible tracing and a debugger

remake is a patched version of GNU Make that adds improved error reporting, the ability to trace execution in a comprehensible way, and a debugger.

The latest version is based off of the GNU Make 3.82 source. We also have a some cool debuggers for Ruby 1.9, Ruby 1.8 (Rubinius), Python, GNU Bash, Z-Shell, and K-Shell.

 

Source Code

Excerpts

Valid HTML 4.01 Transitional Valid CSS! SourceForge Logo

remake-4.1+dbg1.3~dfsg.1/htdocs/remake/000077500000000000000000000000001317072305000175235ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/htdocs/remake/.gitignore000066400000000000000000000000041317072305000215050ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/htdocs/remake/mdb.html000066400000000000000000000003621317072305000211540ustar00rootroot00000000000000 Your Page Title remake-4.1+dbg1.3~dfsg.1/implicit.c000066400000000000000000001030471317072305000167560ustar00rootroot00000000000000/* Implicit rule searching for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "rule.h" #include "dep.h" #include "debug.h" #include "variable.h" #include "job.h" /* struct child, used inside commands.h */ #include "commands.h" /* set_file_variables */ static int pattern_search (struct file *file, int archive, unsigned int depth, unsigned int recursions); /* For a FILE which has no commands specified, try to figure out some from the implicit pattern rules. Returns 1 if a suitable implicit rule was found, after modifying FILE to contain the appropriate commands and deps, or returns 0 if no implicit rule was found. */ int try_implicit_rule (struct file *file, unsigned int depth) { DBF (DB_IMPLICIT, _("Looking for an implicit rule for '%s'.\n")); /* The order of these searches was previously reversed. My logic now is that since the non-archive search uses more information in the target (the archive search omits the archive name), it is more specific and should come first. */ if (pattern_search (file, 0, depth, 0)) return 1; #ifndef NO_ARCHIVES /* If this is an archive member reference, use just the archive member name to search for implicit rules. */ if (ar_name (file->name)) { DBF (DB_IMPLICIT, _("Looking for archive-member implicit rule for '%s'.\n")); if (pattern_search (file, 1, depth, 0)) return 1; } #endif return 0; } /* Scans the BUFFER for the next word with whitespace as a separator. Returns the pointer to the beginning of the word. LENGTH hold the length of the word. */ static const char * get_next_word (const char *buffer, unsigned int *length) { const char *p = buffer, *beg; char c; /* Skip any leading whitespace. */ while (isblank ((unsigned char)*p)) ++p; beg = p; c = *(p++); if (c == '\0') return 0; /* We already found the first value of "c", above. */ while (1) { char closeparen; int count; switch (c) { case '\0': case ' ': case '\t': goto done_word; case '$': c = *(p++); if (c == '$') break; /* This is a variable reference, so read it to the matching close paren. */ if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else /* This is a single-letter variable reference. */ break; for (count = 0; *p != '\0'; ++p) { if (*p == c) ++count; else if (*p == closeparen && --count < 0) { ++p; break; } } break; case '|': goto done; default: break; } c = *(p++); } done_word: --p; done: if (length) *length = p - beg; return beg; } /* This structure stores information about the expanded prerequisites for a pattern rule. NAME is always set to the strcache'd name of the prereq. FILE and PATTERN will be set for intermediate files only. IGNORE_MTIME is copied from the prerequisite we expanded. */ struct patdeps { const char *name; const char *pattern; struct file *file; unsigned int ignore_mtime : 1; }; /* This structure stores information about pattern rules that we need to try. */ struct tryrule { struct rule *rule; /* Index of the target in this rule that matched the file. */ unsigned int matches; /* Stem length for this match. */ unsigned int stemlen; /* Definition order of this rule. Used to implement stable sort.*/ unsigned int order; /* Nonzero if the LASTSLASH logic was used in matching this rule. */ char checked_lastslash; }; int stemlen_compare (const void *v1, const void *v2) { const struct tryrule *r1 = v1; const struct tryrule *r2 = v2; int r = r1->stemlen - r2->stemlen; return r != 0 ? r : (int)(r1->order - r2->order); } /* Search the pattern rules for a rule with an existing dependency to make FILE. If a rule is found, the appropriate commands and deps are put in FILE and 1 is returned. If not, 0 is returned. If ARCHIVE is nonzero, FILE->name is of the form "LIB(MEMBER)". A rule for "(MEMBER)" will be searched for, and "(MEMBER)" will not be chopped up into directory and filename parts. If an intermediate file is found by pattern search, the intermediate file is set up as a target by the recursive call and is also made a dependency of FILE. DEPTH is used for debugging messages. */ static int pattern_search (struct file *file, int archive, unsigned int depth, unsigned int recursions) { /* Filename we are searching for a rule for. */ const char *filename = archive ? strchr (file->name, '(') : file->name; /* Length of FILENAME. */ unsigned int namelen = strlen (filename); /* The last slash in FILENAME (or nil if there is none). */ const char *lastslash; /* This is a file-object used as an argument in recursive calls. It never contains any data except during a recursive call. */ struct file *int_file = 0; /* List of dependencies found recursively. */ unsigned int max_deps = max_pattern_deps; struct patdeps *deplist = xmalloc (max_deps * sizeof (struct patdeps)); struct patdeps *pat = deplist; /* Names of possible dependencies are constructed in this buffer. */ char *depname = alloca (namelen + max_pattern_dep_length); /* The start and length of the stem of FILENAME for the current rule. */ const char *stem = 0; unsigned int stemlen = 0; unsigned int fullstemlen = 0; /* Buffer in which we store all the rules that are possibly applicable. */ struct tryrule *tryrules = xmalloc (num_pattern_rules * max_pattern_targets * sizeof (struct tryrule)); /* Number of valid elements in TRYRULES. */ unsigned int nrules; /* The index in TRYRULES of the rule we found. */ unsigned int foundrule; /* Nonzero if should consider intermediate files as dependencies. */ int intermed_ok; /* Nonzero if we have initialized file variables for this target. */ int file_vars_initialized = 0; /* Nonzero if we have matched a pattern-rule target that is not just '%'. */ int specific_rule_matched = 0; unsigned int ri; /* uninit checks OK */ struct rule *rule; char *pathdir = NULL; unsigned long pathlen; PATH_VAR (stem_str); /* @@ Need to get rid of stem, stemlen, etc. */ #ifndef NO_ARCHIVES if (archive || ar_name (filename)) lastslash = 0; else #endif { /* Set LASTSLASH to point at the last slash in FILENAME but not counting any slash at the end. (foo/bar/ counts as bar/ in directory foo/, not empty in directory foo/bar/.) */ #ifdef VMS lastslash = strrchr (filename, ']'); if (lastslash == 0) lastslash = strrchr (filename, ':'); #else lastslash = strrchr (filename, '/'); #ifdef HAVE_DOS_PATHS /* Handle backslashes (possibly mixed with forward slashes) and the case of "d:file". */ { char *bslash = strrchr (filename, '\\'); if (lastslash == 0 || bslash > lastslash) lastslash = bslash; if (lastslash == 0 && filename[0] && filename[1] == ':') lastslash = filename + 1; } #endif #endif if (lastslash != 0 && lastslash[1] == '\0') lastslash = 0; } pathlen = lastslash - filename + 1; /* First see which pattern rules match this target and may be considered. Put them in TRYRULES. */ nrules = 0; for (rule = pattern_rules; rule != 0; rule = rule->next) { unsigned int ti; /* If the pattern rule has deps but no commands, ignore it. Users cancel built-in rules by redefining them without commands. */ if (rule->deps != 0 && rule->cmds == 0) continue; /* If this rule is in use by a parent pattern_search, don't use it here. */ if (rule->in_use) { DBS (DB_IMPLICIT, (_("Avoiding implicit rule recursion.\n"))); continue; } for (ti = 0; ti < rule->num; ++ti) { const char *target = rule->targets[ti]; const char *suffix = rule->suffixes[ti]; int check_lastslash; /* Rules that can match any filename and are not terminal are ignored if we're recursing, so that they cannot be intermediate files. */ if (recursions > 0 && target[1] == '\0' && !rule->terminal) continue; if (rule->lens[ti] > namelen) /* It can't possibly match. */ continue; /* From the lengths of the filename and the pattern parts, find the stem: the part of the filename that matches the %. */ stem = filename + (suffix - target - 1); stemlen = namelen - rule->lens[ti] + 1; /* Set CHECK_LASTSLASH if FILENAME contains a directory prefix and the target pattern does not contain a slash. */ check_lastslash = 0; if (lastslash) { #ifdef VMS check_lastslash = (strchr (target, ']') == 0 && strchr (target, ':') == 0); #else check_lastslash = strchr (target, '/') == 0; #ifdef HAVE_DOS_PATHS /* Didn't find it yet: check for DOS-type directories. */ if (check_lastslash) { char *b = strchr (target, '\\'); check_lastslash = !(b || (target[0] && target[1] == ':')); } #endif #endif } if (check_lastslash) { /* If so, don't include the directory prefix in STEM here. */ if (pathlen > stemlen) continue; stemlen -= pathlen; stem += pathlen; } /* Check that the rule pattern matches the text before the stem. */ if (check_lastslash) { if (stem > (lastslash + 1) && !strneq (target, lastslash + 1, stem - lastslash - 1)) continue; } else if (stem > filename && !strneq (target, filename, stem - filename)) continue; /* Check that the rule pattern matches the text after the stem. We could test simply use streq, but this way we compare the first two characters immediately. This saves time in the very common case where the first character matches because it is a period. */ if (*suffix != stem[stemlen] || (*suffix != '\0' && !streq (&suffix[1], &stem[stemlen + 1]))) continue; /* Record if we match a rule that not all filenames will match. */ if (target[1] != '\0') specific_rule_matched = 1; /* A rule with no dependencies and no commands exists solely to set specific_rule_matched when it matches. Don't try to use it. */ if (rule->deps == 0 && rule->cmds == 0) continue; /* Record this rule in TRYRULES and the index of the matching target in MATCHES. If several targets of the same rule match, that rule will be in TRYRULES more than once. */ tryrules[nrules].rule = rule; tryrules[nrules].matches = ti; tryrules[nrules].stemlen = stemlen + (check_lastslash ? pathlen : 0); tryrules[nrules].order = nrules; tryrules[nrules].checked_lastslash = check_lastslash; ++nrules; } } /* Bail out early if we haven't found any rules. */ if (nrules == 0) goto done; /* Sort the rules to place matches with the shortest stem first. This way the most specific rules will be tried first. */ if (nrules > 1) qsort (tryrules, nrules, sizeof (struct tryrule), stemlen_compare); /* If we have found a matching rule that won't match all filenames, retroactively reject any non-"terminal" rules that do always match. */ if (specific_rule_matched) for (ri = 0; ri < nrules; ++ri) if (!tryrules[ri].rule->terminal) { unsigned int j; for (j = 0; j < tryrules[ri].rule->num; ++j) if (tryrules[ri].rule->targets[j][1] == '\0') { tryrules[ri].rule = 0; break; } } /* Try each rule once without intermediate files, then once with them. */ for (intermed_ok = 0; intermed_ok < 2; ++intermed_ok) { pat = deplist; /* Try each pattern rule till we find one that applies. If it does, expand its dependencies (as substituted) and chain them in DEPS. */ for (ri = 0; ri < nrules; ri++) { struct dep *dep; int check_lastslash; unsigned int failed = 0; int file_variables_set = 0; unsigned int deps_found = 0; /* NPTR points to the part of the prereq we haven't processed. */ const char *nptr = 0; const char *dir = NULL; int order_only = 0; unsigned int matches; rule = tryrules[ri].rule; /* RULE is nil when we discover that a rule, already placed in TRYRULES, should not be applied. */ if (rule == 0) continue; /* Reject any terminal rules if we're looking to make intermediate files. */ if (intermed_ok && rule->terminal) continue; /* From the lengths of the filename and the matching pattern parts, find the stem: the part of the filename that matches the %. */ matches = tryrules[ri].matches; stem = filename + (rule->suffixes[matches] - rule->targets[matches]) - 1; stemlen = (namelen - rule->lens[matches]) + 1; check_lastslash = tryrules[ri].checked_lastslash; if (check_lastslash) { stem += pathlen; stemlen -= pathlen; /* We need to add the directory prefix, so set it up. */ if (! pathdir) { pathdir = alloca (pathlen + 1); memcpy (pathdir, filename, pathlen); pathdir[pathlen] = '\0'; } dir = pathdir; } if (stemlen > GET_PATH_MAX) { DBS (DB_IMPLICIT, (_("Stem too long: '%.*s'.\n"), (int) stemlen, stem)); continue; } DBS (DB_IMPLICIT, (_("Trying pattern rule with stem '%.*s'.\n"), (int) stemlen, stem)); strncpy (stem_str, stem, stemlen); stem_str[stemlen] = '\0'; /* If there are no prerequisites, then this rule matches. */ if (rule->deps == 0) break; /* Temporary assign STEM to file->stem (needed to set file variables below). */ file->stem = stem_str; /* Mark this rule as in use so a recursive pattern_search won't try to use it. */ rule->in_use = 1; /* Try each prerequisite; see if it exists or can be created. We'll build a list of prereq info in DEPLIST. Due to 2nd expansion we may have to process multiple prereqs for a single dep entry. */ pat = deplist; dep = rule->deps; nptr = dep_name (dep); while (1) { struct dep *dl, *d; char *p; /* If we're out of name to parse, start the next prereq. */ if (! nptr) { dep = dep->next; if (dep == 0) break; nptr = dep_name (dep); } /* If we don't need a second expansion, just replace the %. */ if (! dep->need_2nd_expansion) { p = strchr (nptr, '%'); if (p == 0) strcpy (depname, nptr); else { char *o = depname; if (check_lastslash) { memcpy (o, filename, pathlen); o += pathlen; } memcpy (o, nptr, p - nptr); o += p - nptr; memcpy (o, stem_str, stemlen); o += stemlen; strcpy (o, p + 1); } /* Parse the expanded string. It might have wildcards. */ p = depname; dl = PARSE_SIMPLE_SEQ (&p, struct dep); for (d = dl; d != NULL; d = d->next) { ++deps_found; d->ignore_mtime = dep->ignore_mtime; } /* We've used up this dep, so next time get a new one. */ nptr = 0; } /* We have to perform second expansion on this prereq. In an ideal world we would take the dependency line, substitute the stem, re-expand the whole line and chop it into individual prerequisites. Unfortunately this won't work because of the "check_lastslash" twist. Instead, we will have to go word by word, taking $()'s into account. For each word we will substitute the stem, re-expand, chop it up, and, if check_lastslash != 0, add the directory part to each resulting prerequisite. */ else { int add_dir = 0; unsigned int len; struct dep **dptr; nptr = get_next_word (nptr, &len); if (nptr == 0) continue; /* See this is a transition to order-only prereqs. */ if (! order_only && len == 1 && nptr[0] == '|') { order_only = 1; nptr += len; continue; } /* If the dependency name has %, substitute the stem. If we just replace % with the stem value then later, when we do the 2nd expansion, we will re-expand this stem value again. This is not good if you have certain characters in your stem (like $). Instead, we will replace % with $* and allow the second expansion to take care of it for us. This way (since $* is a simple variable) there won't be additional re-expansion of the stem. */ p = lindex (nptr, nptr + len, '%'); if (p == 0) { memcpy (depname, nptr, len); depname[len] = '\0'; } else { unsigned int i = p - nptr; memcpy (depname, nptr, i); memcpy (depname + i, "$*", 2); memcpy (depname + i + 2, p + 1, len - i - 1); depname[len + 2 - 1] = '\0'; if (check_lastslash) add_dir = 1; } /* Set up for the next word. */ nptr += len; /* Initialize and set file variables if we haven't already done so. */ if (!file_vars_initialized) { initialize_file_variables (file, 0); set_file_variables (file); file_vars_initialized = 1; } /* Update the stem value in $* for this rule. */ else if (!file_variables_set) { define_variable_for_file ( "*", 1, file->stem, o_automatic, 0, file); file_variables_set = 1; } /* Perform the 2nd expansion. */ p = variable_expand_for_file (depname, file); dptr = &dl; /* Parse the results into a deps list. */ do { /* Parse the expanded string. */ struct dep *dp = PARSE_FILE_SEQ (&p, struct dep, order_only ? MAP_NUL : MAP_PIPE, add_dir ? dir : NULL, PARSEFS_NONE); *dptr = dp; for (d = dp; d != NULL; d = d->next) { ++deps_found; if (order_only) d->ignore_mtime = 1; dptr = &d->next; } /* If we stopped due to an order-only token, note it. */ if (*p == '|') { order_only = 1; ++p; } } while (*p != '\0'); } /* If there are more than max_pattern_deps prerequisites (due to 2nd expansion), reset it and realloc the arrays. */ if (deps_found > max_deps) { unsigned int l = pat - deplist; /* This might have changed due to recursion. */ max_pattern_deps = MAX(max_pattern_deps, deps_found); max_deps = max_pattern_deps; deplist = xrealloc (deplist, max_deps * sizeof (struct patdeps)); pat = deplist + l; } /* Go through the nameseq and handle each as a prereq name. */ for (d = dl; d != 0; d = d->next) { struct dep *expl_d; int is_rule = d->name == dep_name (dep); if (file_impossible_p (d->name)) { /* If this prereq has already been ruled "impossible", then the rule fails. Don't bother trying it on the second pass either since we know that will fail. */ DBS (DB_IMPLICIT, (is_rule ? _("Rejecting impossible rule prerequisite '%s'.\n") : _("Rejecting impossible implicit prerequisite '%s'.\n"), d->name)); tryrules[ri].rule = 0; failed = 1; break; } memset (pat, '\0', sizeof (struct patdeps)); pat->ignore_mtime = d->ignore_mtime; DBS (DB_IMPLICIT, (is_rule ? _("Trying rule prerequisite '%s'.\n") : _("Trying implicit prerequisite '%s'.\n"), d->name)); /* If this prereq is also explicitly mentioned for FILE, skip all tests below since it must be built no matter which implicit rule we choose. */ for (expl_d = file->deps; expl_d != 0; expl_d = expl_d->next) if (streq (dep_name (expl_d), d->name)) break; if (expl_d != 0) { (pat++)->name = d->name; continue; } /* The DEP->changed flag says that this dependency resides in a nonexistent directory. So we normally can skip looking for the file. However, if CHECK_LASTSLASH is set, then the dependency file we are actually looking for is in a different directory (the one gotten by prepending FILENAME's directory), so it might actually exist. */ /* @@ dep->changed check is disabled. */ if (lookup_file (d->name) != 0 /*|| ((!dep->changed || check_lastslash) && */ || file_exists_p (d->name)) { (pat++)->name = d->name; continue; } /* This code, given FILENAME = "lib/foo.o", dependency name "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */ { const char *vname = vpath_search (d->name, 0, NULL, NULL); if (vname) { DBS (DB_IMPLICIT, (_("Found prerequisite '%s' as VPATH '%s'\n"), d->name, vname)); (pat++)->name = d->name; continue; } } /* We could not find the file in any place we should look. Try to make this dependency as an intermediate file, but only on the second pass. */ if (intermed_ok) { DBS (DB_IMPLICIT, (_("Looking for a rule with intermediate file '%s'.\n"), d->name)); if (int_file == 0) int_file = alloca (sizeof (struct file)); memset (int_file, '\0', sizeof (struct file)); int_file->name = d->name; if (pattern_search (int_file, 0, depth + 1, recursions + 1)) { pat->pattern = int_file->name; int_file->name = d->name; pat->file = int_file; int_file = 0; (pat++)->name = d->name; continue; } /* If we have tried to find P as an intermediate file and failed, mark that name as impossible so we won't go through the search again later. */ if (int_file->variables) free_variable_set (int_file->variables); if (int_file->pat_variables) free_variable_set (int_file->pat_variables); file_impossible (d->name); } /* A dependency of this rule does not exist. Therefore, this rule fails. */ failed = 1; break; } /* Free the ns chain. */ free_dep_chain (dl); if (failed) break; } /* Reset the stem in FILE. */ file->stem = 0; /* This rule is no longer 'in use' for recursive searches. */ rule->in_use = 0; if (! failed) /* This pattern rule does apply. Stop looking for one. */ break; /* This pattern rule does not apply. Keep looking. */ } /* If we found an applicable rule without intermediate files, don't try with them. */ if (ri < nrules) break; rule = 0; } /* RULE is nil if the loop went through the list but everything failed. */ if (rule == 0) goto done; foundrule = ri; /* If we are recursing, store the pattern that matched FILENAME in FILE->name for use in upper levels. */ if (recursions > 0) /* Kludge-o-matic */ file->name = rule->targets[tryrules[foundrule].matches]; /* DEPLIST lists the prerequisites for the rule we found. This includes the intermediate files, if any. Convert them into entries on the deps-chain of FILE. */ while (pat-- > deplist) { struct dep *dep; const char *s; if (pat->file != 0) { /* If we need to use an intermediate file, make sure it is entered as a target, with the info that was found for it in the recursive pattern_search call. We know that the intermediate file did not already exist as a target; therefore we can assume that the deps and cmds of F below are null before we change them. */ struct file *imf = pat->file; struct file *f = lookup_file (imf->name); /* We don't want to delete an intermediate file that happened to be a prerequisite of some (other) target. Mark it as precious. */ if (f != 0) f->precious = 1; else f = enter_file (imf->name); f->deps = imf->deps; f->cmds = imf->cmds; f->stem = imf->stem; f->variables = imf->variables; f->pat_variables = imf->pat_variables; f->pat_searched = imf->pat_searched; f->also_make = imf->also_make; f->is_target = 1; f->intermediate = 1; f->tried_implicit = 1; imf = lookup_file (pat->pattern); if (imf != 0 && imf->precious) f->precious = 1; for (dep = f->deps; dep != 0; dep = dep->next) { dep->file = enter_file (dep->name); dep->name = 0; dep->file->tried_implicit |= dep->changed; } } dep = alloc_dep (); dep->ignore_mtime = pat->ignore_mtime; s = strcache_add (pat->name); if (recursions) dep->name = s; else { dep->file = lookup_file (s); if (dep->file == 0) dep->file = enter_file (s); } if (pat->file == 0 && tryrules[foundrule].rule->terminal) { /* If the file actually existed (was not an intermediate file), and the rule that found it was a terminal one, then we want to mark the found file so that it will not have implicit rule search done for it. If we are not entering a 'struct file' for it now, we indicate this with the 'changed' flag. */ if (dep->file == 0) dep->changed = 1; else dep->file->tried_implicit = 1; } dep->next = file->deps; file->deps = dep; } if (!tryrules[foundrule].checked_lastslash) { /* Always allocate new storage, since STEM might be on the stack for an intermediate file. */ file->stem = strcache_add_len (stem, stemlen); fullstemlen = stemlen; } else { int dirlen = (lastslash + 1) - filename; char *sp; /* We want to prepend the directory from the original FILENAME onto the stem. */ fullstemlen = dirlen + stemlen; sp = alloca (fullstemlen + 1); memcpy (sp, filename, dirlen); memcpy (sp + dirlen, stem, stemlen); sp[fullstemlen] = '\0'; file->stem = strcache_add (sp); } file->cmds = rule->cmds; file->is_target = 1; /* Set precious flag. */ { struct file *f = lookup_file (rule->targets[tryrules[foundrule].matches]); if (f && f->precious) file->precious = 1; } /* If this rule builds other targets, too, put the others into FILE's 'also_make' member. */ if (rule->num > 1) for (ri = 0; ri < rule->num; ++ri) if (ri != tryrules[foundrule].matches) { char *nm = alloca (rule->lens[ri] + fullstemlen + 1); char *p = nm; struct file *f; struct dep *new = alloc_dep (); /* GKM FIMXE: handle '|' here too */ memcpy (p, rule->targets[ri], rule->suffixes[ri] - rule->targets[ri] - 1); p += rule->suffixes[ri] - rule->targets[ri] - 1; memcpy (p, file->stem, fullstemlen); p += fullstemlen; memcpy (p, rule->suffixes[ri], rule->lens[ri] - (rule->suffixes[ri] - rule->targets[ri])+1); new->name = strcache_add (nm); new->file = enter_file (new->name); new->next = file->also_make; /* Set precious flag. */ f = lookup_file (rule->targets[ri]); if (f && f->precious) new->file->precious = 1; /* Set the is_target flag so that this file is not treated as intermediate by the pattern rule search algorithm and file_exists_p cannot pick it up yet. */ new->file->is_target = 1; file->also_make = new; } done: free (tryrules); free (deplist); return rule != 0; } remake-4.1+dbg1.3~dfsg.1/implicit.h000066400000000000000000000007461317072305000167650ustar00rootroot00000000000000/** \file implicit.h * * \brief header for impilict.c */ #ifndef REMAKE_IMPLICIT_H #define REMAKE_IMPLICIT_H #include "types.h" /* For a FILE which has no commands specified, try to figure out some from the implicit pattern rules. Returns 1 if a suitable implicit rule was found, after modifying FILE to contain the appropriate commands and deps, or returns 0 if no implicit rule was found. */ extern int try_implicit_rule (file_t *file, unsigned int depth); #endif remake-4.1+dbg1.3~dfsg.1/job.c000066400000000000000000003434311317072305000157210ustar00rootroot00000000000000/* Job execution and handling for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "types.h" #include "makeint.h" #include "globals.h" #include "debugger/cmd.h" #include #include "job.h" #include "print.h" #include "debug.h" #include "filedef.h" #include "commands.h" #include "variable.h" #include "debug.h" #include #if defined (HAVE_LINUX_BINFMTS_H) && defined (HAVE_SYS_USER_H) #include #include #endif #ifndef PAGE_SIZE # define PAGE_SIZE (sysconf(_SC_PAGESIZE)) #endif /* Default shell to use. */ #ifdef WINDOWS32 #include const char *default_shell = "sh.exe"; int no_default_sh_exe = 1; int batch_mode_shell = 1; HANDLE main_thread; #elif defined (_AMIGA) const char *default_shell = ""; extern int MyExecute (char **); int batch_mode_shell = 0; #elif defined (__MSDOS__) /* The default shell is a pointer so we can change it if Makefile says so. It is without an explicit path so we get a chance to search the $PATH for it (since MSDOS doesn't have standard directories we could trust). */ const char *default_shell = "command.com"; int batch_mode_shell = 0; #elif defined (__EMX__) const char *default_shell = "/bin/sh"; int batch_mode_shell = 0; #elif defined (VMS) # include const char *default_shell = ""; int batch_mode_shell = 0; #elif defined (__riscos__) const char *default_shell = ""; int batch_mode_shell = 0; #else const char *default_shell = "/bin/sh"; int batch_mode_shell = 0; #endif #ifdef __MSDOS__ # include static int execute_by_shell; static int dos_pid = 123; int dos_status; int dos_command_running; #endif /* __MSDOS__ */ #ifdef _AMIGA # include static int amiga_pid = 123; static int amiga_status; static char amiga_bname[32]; static int amiga_batch_file; #endif /* Amiga. */ #ifdef VMS # ifndef __GNUC__ # include # endif # include # include static void vmsWaitForChildren (int *); #endif #ifdef WINDOWS32 # include # include # include # include "sub_proc.h" # include "w32err.h" # include "pathstuff.h" # define WAIT_NOHANG 1 #endif /* WINDOWS32 */ #ifdef __EMX__ # include #endif #if defined (HAVE_SYS_WAIT_H) || defined (HAVE_UNION_WAIT) # include #endif #ifdef HAVE_WAITPID # define WAIT_NOHANG(status) waitpid (-1, (status), WNOHANG) #else /* Don't have waitpid. */ # ifdef HAVE_WAIT3 # ifndef wait3 extern int wait3 (); # endif # define WAIT_NOHANG(status) wait3 ((status), WNOHANG, (struct rusage *) 0) # endif /* Have wait3. */ #endif /* Have waitpid. */ #if !defined (wait) && !defined (POSIX) int wait (); #endif #ifndef HAVE_UNION_WAIT # define WAIT_T int # ifndef WTERMSIG # define WTERMSIG(x) ((x) & 0x7f) # endif # ifndef WCOREDUMP # define WCOREDUMP(x) ((x) & 0x80) # endif # ifndef WEXITSTATUS # define WEXITSTATUS(x) (((x) >> 8) & 0xff) # endif # ifndef WIFSIGNALED # define WIFSIGNALED(x) (WTERMSIG (x) != 0) # endif # ifndef WIFEXITED # define WIFEXITED(x) (WTERMSIG (x) == 0) # endif #else /* Have 'union wait'. */ # define WAIT_T union wait # ifndef WTERMSIG # define WTERMSIG(x) ((x).w_termsig) # endif # ifndef WCOREDUMP # define WCOREDUMP(x) ((x).w_coredump) # endif # ifndef WEXITSTATUS # define WEXITSTATUS(x) ((x).w_retcode) # endif # ifndef WIFSIGNALED # define WIFSIGNALED(x) (WTERMSIG(x) != 0) # endif # ifndef WIFEXITED # define WIFEXITED(x) (WTERMSIG(x) == 0) # endif #endif /* Don't have 'union wait'. */ #if !defined(HAVE_UNISTD_H) && !defined(WINDOWS32) int dup2 (); int execve (); void _exit (); # ifndef VMS int geteuid (); int getegid (); int setgid (); int getgid (); # endif #endif /* Different systems have different requirements for pid_t. Plus we have to support gettext string translation... Argh. */ static const char * pid2str (pid_t pid) { static char pidstring[100]; #if defined(WINDOWS32) && (__GNUC__ > 3 || _MSC_VER > 1300) /* %Id is only needed for 64-builds, which were not supported by older versions of Windows compilers. */ sprintf (pidstring, "%Id", pid); #else sprintf (pidstring, "%lu", (unsigned long) pid); #endif return pidstring; } int getloadavg (double loadavg[], int nelem); int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote, int *id_ptr, int *used_stdin); int start_remote_job_p (int); int remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr, int block); RETSIGTYPE child_handler (int); static void free_child (struct child *); static void start_job_command (struct child *child, target_stack_node_t *p_call_stack); static int load_too_high (void); static int job_next_command (struct child *); static int start_waiting_job (child_t *c, target_stack_node_t *p_call_stack); /* Chain of all live (or recently deceased) children. */ struct child *children = 0; /* Number of children currently running. */ unsigned int job_slots_used = 0; /* Nonzero if the 'good' standard input is in use. */ static int good_stdin_used = 0; /* Chain of children waiting to run until the load average goes down. */ static struct child *waiting_jobs = 0; /* Non-zero if we use a *real* shell (always so on Unix). */ int unixy_shell = 1; /* Number of jobs started in the current second. */ unsigned long job_counter = 0; /* Number of jobserver tokens this instance is currently using. */ unsigned int jobserver_tokens = 0; #ifdef WINDOWS32 /* * The macro which references this function is defined in makeint.h. */ int w32_kill (pid_t pid, int sig) { return ((process_kill ((HANDLE)pid, sig) == TRUE) ? 0 : -1); } /* This function creates a temporary file name with an extension specified * by the unixy arg. * Return an xmalloc'ed string of a newly created temp file and its * file descriptor, or die. */ static char * create_batch_file (char const *base, int unixy, int *fd) { const char *const ext = unixy ? "sh" : "bat"; const char *error_string = NULL; char temp_path[MAXPATHLEN]; /* need to know its length */ unsigned path_size = GetTempPath (sizeof temp_path, temp_path); int path_is_dot = 0; /* The following variable is static so we won't try to reuse a name that was generated a little while ago, because that file might not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below, which tells the OS it doesn't need to flush the cache to disk. If the file is not yet on disk, we might think the name is available, while it really isn't. This happens in parallel builds, where Make doesn't wait for one job to finish before it launches the next one. */ static unsigned uniq = 0; static int second_loop = 0; const unsigned sizemax = strlen (base) + strlen (ext) + 10; if (path_size == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } ++uniq; if (uniq >= 0x10000 && !second_loop) { /* If we already had 64K batch files in this process, make a second loop through the numbers, looking for free slots, i.e. files that were deleted in the meantime. */ second_loop = 1; uniq = 1; } while (path_size > 0 && path_size + sizemax < sizeof temp_path && !(uniq >= 0x10000 && second_loop)) { unsigned size = sprintf (temp_path + path_size, "%s%s-%x.%s", temp_path[path_size - 1] == '\\' ? "" : "\\", base, uniq, ext); HANDLE h = CreateFile (temp_path, /* file name */ GENERIC_READ | GENERIC_WRITE, /* desired access */ 0, /* no share mode */ NULL, /* default security attributes */ CREATE_NEW, /* creation disposition */ FILE_ATTRIBUTE_NORMAL | /* flags and attributes */ FILE_ATTRIBUTE_TEMPORARY, /* we'll delete it */ NULL); /* no template file */ if (h == INVALID_HANDLE_VALUE) { const DWORD er = GetLastError (); if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS) { ++uniq; if (uniq == 0x10000 && !second_loop) { second_loop = 1; uniq = 1; } } /* the temporary path is not guaranteed to exist */ else if (path_is_dot == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } else { error_string = map_windows32_error_to_string (er); break; } } else { const unsigned final_size = path_size + size + 1; char *const path = xmalloc (final_size); memcpy (path, temp_path, final_size); *fd = _open_osfhandle ((intptr_t)h, 0); if (unixy) { char *p; int ch; for (p = path; (ch = *p) != 0; ++p) if (ch == '\\') *p = '/'; } return path; /* good return */ } } *fd = -1; if (error_string == NULL) error_string = _("Cannot create a temporary file\n"); O (fatal, NILF, error_string); /* not reached */ return NULL; } #endif /* WINDOWS32 */ #ifdef __EMX__ /* returns whether path is assumed to be a unix like shell. */ int _is_unixy_shell (const char *path) { /* list of non unix shells */ const char *known_os2shells[] = { "cmd.exe", "cmd", "4os2.exe", "4os2", "4dos.exe", "4dos", "command.com", "command", NULL }; /* find the rightmost '/' or '\\' */ const char *name = strrchr (path, '/'); const char *p = strrchr (path, '\\'); unsigned i; if (name && p) /* take the max */ name = (name > p) ? name : p; else if (p) /* name must be 0 */ name = p; else if (!name) /* name and p must be 0 */ name = path; if (*name == '/' || *name == '\\') name++; i = 0; while (known_os2shells[i] != NULL) { if (strcasecmp (name, known_os2shells[i]) == 0) return 0; /* not a unix shell */ i++; } /* in doubt assume a unix like shell */ return 1; } #endif /* __EMX__ */ /* determines whether path looks to be a Bourne-like shell. */ int is_bourne_compatible_shell (const char *path) { /* List of known POSIX (or POSIX-ish) shells. */ static const char *unix_shells[] = { "sh", "bash", "ksh", "rksh", "zsh", "ash", "dash", NULL }; const char **s; /* find the rightmost '/' or '\\' */ const char *name = strrchr (path, '/'); char *p = strrchr (path, '\\'); if (name && p) /* take the max */ name = (name > p) ? name : p; else if (p) /* name must be 0 */ name = p; else if (!name) /* name and p must be 0 */ name = path; if (*name == '/' || *name == '\\') ++name; /* this should be able to deal with extensions on Windows-like systems */ for (s = unix_shells; *s != NULL; ++s) { #if defined(WINDOWS32) || defined(__MSDOS__) unsigned int len = strlen (*s); if ((strlen (name) >= len && STOP_SET (name[len], MAP_DOT|MAP_NUL)) && strncasecmp (name, *s, len) == 0) #else if (strcmp (name, *s) == 0) #endif return 1; /* a known unix-style shell */ } /* if not on the list, assume it's not a Bourne-like shell */ return 0; } /* Write an error message describing the exit status given in EXIT_CODE, EXIT_SIG, and COREDUMP, for the target TARGET_NAME. Append "(ignored)" if IGNORED is nonzero. */ static void child_error (child_t *p_child, target_stack_node_t *p_call_stack, int exit_code, int exit_sig, int coredump, int ignored) { const char *pre = "*** "; const char *post = ""; const char *dump = ""; const struct file *f = p_child->file; const gmk_floc *flocp = &f->cmds->fileinfo; const char *nm; size_t l = strlen (f->name); if (ignored && silent_flag) return; if (exit_sig && coredump) dump = _(" (core dumped)"); if (ignored) { pre = ""; post = _(" (ignored)"); } if (! flocp->filenm) nm = _(""); else { char *a = alloca (strlen (flocp->filenm) + 1 + 11 + 1); sprintf (a, "%s:%lu", flocp->filenm, flocp->lineno); nm = a; } OUTPUT_SET (&p_child->output); message (0, l + strlen (nm), _("%s: recipe for target '%s' failed"), nm, f->name); l += strlen (pre) + strlen (post); #ifdef VMS if ((exit_code & 1) != 0) { OUTPUT_UNSET (); return; } /* Check for a Posix compatible VMS style exit code: decode and print the Posix exit code */ if ((exit_code & 0x35a000) == 0x35a000) error(NILF, l + INTSTR_LENGTH, _("%s[%s] Error %d%s"), pre, f->name, ((exit_code & 0x7f8) >> 3), post); else error(NILF, l + INTSTR_LENGTH, _("%s[%s] Error 0x%x%s"), pre, f->name, exit_code, post); #else if (exit_sig == 0) err_with_stack(p_call_stack, ignored ? _("[%s] Error %d%s") : _("*** [%s] Error %d"), f->name, exit_code, post); else err_with_stack(p_call_stack, "*** [%s] %s%s", f->name, strsignal (exit_sig), dump); #endif /* VMS */ OUTPUT_UNSET (); /* If have enabled debugging but haven't entered the debugger above because we haven't set to debug on error, enter the debugger now. FIXME: Add be another variable/option to control entry here as well? */ if (! (debugger_on_error & DEBUGGER_ON_ERROR) && debugger_enabled ) enter_debugger(p_call_stack, p_child->file, exit_code, DEBUG_ERROR_HIT); } /* Handle a dead child. This handler may or may not ever be installed. If we're using the jobserver feature, we need it. First, installing it ensures the read will interrupt on SIGCHLD. Second, we close the dup'd read FD to ensure we don't enter another blocking read without reaping all the dead children. In this case we don't need the dead_children count. If we don't have either waitpid or wait3, then make is unreliable, but we use the dead_children count to reap children as best we can. */ static unsigned int dead_children = 0; RETSIGTYPE child_handler (int sig UNUSED) { ++dead_children; if (job_rfd >= 0) { close (job_rfd); job_rfd = -1; } #ifdef __EMX__ /* The signal handler must called only once! */ signal (SIGCHLD, SIG_DFL); #endif /* This causes problems if the SIGCHLD interrupts a printf(). DB (DB_JOBS, (_("Got a SIGCHLD; %u unreaped children.\n"), dead_children)); */ } extern int shell_function_pid, shell_function_completed; /* Reap all dead children, storing the returned status and the new command state ('cs_finished') in the 'file' member of the 'struct child' for the dead child, and removing the child from the chain. In addition, if BLOCK nonzero, we block in this function until we've reaped at least one complete child, waiting for it to die if necessary. If ERR is nonzero, print an error message first. */ void reap_children (int block, int err, target_stack_node_t *p_call_stack) { #ifndef WINDOWS32 WAIT_T status; #endif /* Initially, assume we have some. */ int reap_more = 1; #ifdef WAIT_NOHANG # define REAP_MORE reap_more #else # define REAP_MORE dead_children #endif /* As long as: We have at least one child outstanding OR a shell function in progress, AND We're blocking for a complete child OR there are more children to reap we'll keep reaping children. */ while ((children != 0 || shell_function_pid != 0) && (block || REAP_MORE)) { int remote = 0; pid_t pid; int exit_code, exit_sig, coredump; struct child *lastc, *c; int child_failed; int any_remote, any_local; int dontcare; if (err && block) { static int printed = 0; /* We might block for a while, so let the user know why. Only print this message once no matter how many jobs are left. */ fflush (stdout); if (!printed) O (error, NILF, _("*** Waiting for unfinished jobs....")); printed = 1; } /* We have one less dead child to reap. As noted in child_handler() above, this count is completely unimportant for all modern, POSIX-y systems that support wait3() or waitpid(). The rest of this comment below applies only to early, broken pre-POSIX systems. We keep the count only because... it's there... The test and decrement are not atomic; if it is compiled into: register = dead_children - 1; dead_children = register; a SIGCHLD could come between the two instructions. child_handler increments dead_children. The second instruction here would lose that increment. But the only effect of dead_children being wrong is that we might wait longer than necessary to reap a child, and lose some parallelism; and we might print the "Waiting for unfinished jobs" message above when not necessary. */ if (dead_children > 0) --dead_children; any_remote = 0; any_local = shell_function_pid != 0; for (c = children; c != 0; c = c->next) { any_remote |= c->remote; any_local |= ! c->remote; DB (DB_JOBS, (_("Live child %p (%s) PID %s %s\n"), c, c->file->name, pid2str (c->pid), c->remote ? _(" (remote)") : "")); #ifdef VMS break; #endif } /* First, check for remote children. */ if (any_remote) pid = remote_status (&exit_code, &exit_sig, &coredump, 0); else pid = 0; if (pid > 0) /* We got a remote child. */ remote = 1; else if (pid < 0) { /* A remote status command failed miserably. Punt. */ remote_status_lose: pfatal_with_name ("remote_status"); } else { /* No remote children. Check for local children. */ #if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) if (any_local) { #ifdef VMS vmsWaitForChildren (&status); pid = c->pid; #else #ifdef WAIT_NOHANG if (!block) pid = WAIT_NOHANG (&status); else #endif EINTRLOOP(pid, wait (&status)); #endif /* !VMS */ } else pid = 0; if (pid < 0) { /* The wait*() failed miserably. Punt. */ pfatal_with_name ("wait"); } else if (pid > 0) { /* We got a child exit; chop the status word up. */ exit_code = WEXITSTATUS (status); exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0; coredump = WCOREDUMP (status); /* If we have started jobs in this second, remove one. */ if (job_counter) --job_counter; } else { /* No local children are dead. */ reap_more = 0; if (!block || !any_remote) break; /* Now try a blocking wait for a remote child. */ pid = remote_status (&exit_code, &exit_sig, &coredump, 1); if (pid < 0) goto remote_status_lose; else if (pid == 0) /* No remote children either. Finally give up. */ break; /* We got a remote child. */ remote = 1; } #endif /* !__MSDOS__, !Amiga, !WINDOWS32. */ #ifdef __MSDOS__ /* Life is very different on MSDOS. */ pid = dos_pid - 1; status = dos_status; exit_code = WEXITSTATUS (status); if (exit_code == 0xff) exit_code = -1; exit_sig = WIFSIGNALED (status) ? WTERMSIG (status) : 0; coredump = 0; #endif /* __MSDOS__ */ #ifdef _AMIGA /* Same on Amiga */ pid = amiga_pid - 1; status = amiga_status; exit_code = amiga_status; exit_sig = 0; coredump = 0; #endif /* _AMIGA */ #ifdef WINDOWS32 { HANDLE hPID; HANDLE hcTID, hcPID; DWORD dwWaitStatus = 0; exit_code = 0; exit_sig = 0; coredump = 0; /* Record the thread ID of the main process, so that we could suspend it in the signal handler. */ if (!main_thread) { hcTID = GetCurrentThread (); hcPID = GetCurrentProcess (); if (!DuplicateHandle (hcPID, hcTID, hcPID, &main_thread, 0, FALSE, DUPLICATE_SAME_ACCESS)) { DWORD e = GetLastError (); fprintf (stderr, "Determine main thread ID (Error %ld: %s)\n", e, map_windows32_error_to_string (e)); } else DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread)); } /* wait for anything to finish */ hPID = process_wait_for_any (block, &dwWaitStatus); if (hPID) { /* was an error found on this process? */ int werr = process_last_err (hPID); /* get exit data */ exit_code = process_exit_code (hPID); if (werr) fprintf (stderr, "make (e=%d): %s", exit_code, map_windows32_error_to_string (exit_code)); /* signal */ exit_sig = process_signal (hPID); /* cleanup process */ process_cleanup (hPID); coredump = 0; } else if (dwWaitStatus == WAIT_FAILED) { /* The WaitForMultipleObjects() failed miserably. Punt. */ pfatal_with_name ("WaitForMultipleObjects"); } else if (dwWaitStatus == WAIT_TIMEOUT) { /* No child processes are finished. Give up waiting. */ reap_more = 0; break; } pid = (pid_t) hPID; } #endif /* WINDOWS32 */ } /* Check if this is the child of the 'shell' function. */ if (!remote && pid == shell_function_pid) { /* It is. Leave an indicator for the 'shell' function. */ if (exit_sig == 0 && exit_code == 127) shell_function_completed = -1; else shell_function_completed = 1; break; } child_failed = exit_sig != 0 || exit_code != 0; /* Search for a child matching the deceased one. */ lastc = 0; for (c = children; c != 0; lastc = c, c = c->next) if (c->pid == pid && c->remote == remote) break; if (c == 0) /* An unknown child died. Ignore it; it was inherited from our invoker. */ continue; DB (DB_JOBS, (child_failed ? _("Reaping losing child %p PID %s %s\n") : _("Reaping winning child %p PID %s %s\n"), c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); if (c->sh_batch_file) { int rm_status; DB (DB_JOBS, (_("Cleaning up temp batch file %s\n"), c->sh_batch_file)); errno = 0; rm_status = remove (c->sh_batch_file); if (rm_status) DB (DB_JOBS, (_("Cleaning up temp batch file %s failed (%d)\n"), c->sh_batch_file, errno)); /* all done with memory */ free (c->sh_batch_file); c->sh_batch_file = NULL; } /* If this child had the good stdin, say it is now free. */ if (c->good_stdin) good_stdin_used = 0; dontcare = c->dontcare; if (exit_code == DEBUGGER_QUIT_RC && debugger_enabled) { if (job_slots_used > 0) --job_slots_used; c->file->update_status = 0; free_child (c); in_debugger = DEBUGGER_QUIT_RC; die(DEBUGGER_QUIT_RC); } if (child_failed && !c->noerror && !ignore_errors_flag) { /* The commands failed. Write an error message, delete non-precious targets, and abort. */ static int delete_on_error = -1; if (!dontcare) child_error (c, p_call_stack, exit_code, exit_sig, coredump, 0); c->file->update_status = us_failed; if (delete_on_error == -1) { struct file *f = lookup_file (".DELETE_ON_ERROR"); delete_on_error = f != 0 && f->is_target; } if (exit_sig != 0 || delete_on_error) delete_child_targets (c); } else { if (child_failed) { /* The commands failed, but we don't care. */ child_error (c, p_call_stack, exit_code, exit_sig, coredump, 1); child_failed = 0; } /* If there are more commands to run, try to start them. */ if (job_next_command (c)) { if (handling_fatal_signal) { /* Never start new commands while we are dying. Since there are more commands that wanted to be run, the target was not completely remade. So we treat this as if a command had failed. */ c->file->update_status = us_failed; } else { #ifndef NO_OUTPUT_SYNC /* If we're sync'ing per line, write the previous line's output before starting the next one. */ if (output_sync == OUTPUT_SYNC_LINE) output_dump (&c->output); #endif /* Check again whether to start remotely. Whether or not we want to changes over time. Also, start_remote_job may need state set up by start_remote_job_p. */ c->remote = start_remote_job_p (0); start_job_command (c, p_call_stack); /* Fatal signals are left blocked in case we were about to put that child on the chain. But it is already there, so it is safe for a fatal signal to arrive now; it will clean up this child's targets. */ unblock_sigs (); if (c->file->command_state == cs_running) /* We successfully started the new command. Loop to reap more children. */ continue; } if (c->file->update_status != us_success) /* We failed to start the commands. */ delete_child_targets (c); } else /* There are no more commands. We got through them all without an unignored error. Now the target has been successfully updated. */ c->file->update_status = us_success; } /* When we get here, all the commands for c->file are finished. */ #ifndef NO_OUTPUT_SYNC /* Synchronize any remaining parallel output. */ output_dump (&c->output); #endif /* At this point c->file->update_status is success or failed. But c->file->command_state is still cs_running if all the commands ran; notice_finish_file looks for cs_running to tell it that it's interesting to check the file's modtime again now. */ if (! handling_fatal_signal) /* Notice if the target of the commands has been changed. This also propagates its values for command_state and update_status to its also_make files. */ notice_finished_file (c->file); DB (DB_JOBS, (_("Removing child %p PID %s%s from chain.\n"), c, pid2str (c->pid), c->remote ? _(" (remote)") : "")); /* Block fatal signals while frobnicating the list, so that children and job_slots_used are always consistent. Otherwise a fatal signal arriving after the child is off the chain and before job_slots_used is decremented would believe a child was live and call reap_children again. */ block_sigs (); /* There is now another slot open. */ if (job_slots_used > 0) --job_slots_used; /* Remove the child from the chain and free it. */ if (lastc == 0) children = c->next; else lastc->next = c->next; { /* Save file info in case we need to use it in the debugger */ file_t file; memcpy(&file, c->file, sizeof(file_t)); free_child (c); unblock_sigs (); /* Debugger "quit" takes precedence over --ignore-errors --keep-going, etc. */ if (exit_code == DEBUGGER_QUIT_RC && debugger_enabled) { if (job_slots_used > 0) --job_slots_used; in_debugger = DEBUGGER_QUIT_RC; die(DEBUGGER_QUIT_RC); } /* If the job failed, and the -k flag was not given, die, unless we are already in the process of dying. */ if (!err && child_failed && !dontcare && !keep_going_flag && /* fatal_error_signal will die with the right signal. */ !handling_fatal_signal) { if ( (debugger_on_error & DEBUGGER_ON_FATAL) || i_debugger_stepping || i_debugger_nexting ) enter_debugger(p_call_stack, &file, 2, DEBUG_ERROR_HIT); die (MAKE_FAILURE); } } /* Only block for one child. */ block = 0; } return; } /* Free the storage allocated for CHILD. */ static void free_child (struct child *child) { output_close (&child->output); if (!jobserver_tokens) ONS (fatal, NILF, "INTERNAL: Freeing child %p (%s) but no tokens left!\n", child, child->file->name); /* If we're using the jobserver and this child is not the only outstanding job, put a token back into the pipe for it. */ #ifdef WINDOWS32 if (has_jobserver_semaphore () && jobserver_tokens > 1) { if (! release_jobserver_semaphore ()) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); ONS (fatal, NILF, _("release jobserver semaphore: (Error %ld: %s)"), err, estr); } DB (DB_JOBS, (_("Released token for child %p (%s).\n"), child, child->file->name)); } #else if (job_fds[1] >= 0 && jobserver_tokens > 1) { char token = '+'; int r; /* Write a job token back to the pipe. */ EINTRLOOP (r, write (job_fds[1], &token, 1)); if (r != 1) pfatal_with_name (_("write jobserver")); DB (DB_JOBS, (_("Released token for child %p (%s).\n"), child, child->file->name)); } #endif --jobserver_tokens; if (handling_fatal_signal) /* Don't bother free'ing if about to die. */ return; if (child->command_lines != 0) { register unsigned int i; for (i = 0; i < child->file->cmds->ncommand_lines; ++i) free (child->command_lines[i]); free (child->command_lines); } if (child->environment != 0) { register char **ep = child->environment; while (*ep != 0) free (*ep++); free (child->environment); } free (child); } #ifdef POSIX extern sigset_t fatal_signal_set; #endif void block_sigs (void) { #ifdef POSIX (void) sigprocmask (SIG_BLOCK, &fatal_signal_set, (sigset_t *) 0); #else # ifdef HAVE_SIGSETMASK (void) sigblock (fatal_signal_mask); # endif #endif } #ifdef POSIX void unblock_sigs (void) { sigset_t empty; sigemptyset (&empty); sigprocmask (SIG_SETMASK, &empty, (sigset_t *) 0); } #endif #if defined(MAKE_JOBSERVER) && !defined(WINDOWS32) RETSIGTYPE job_noop (int sig UNUSED) { } /* Set the child handler action flags to FLAGS. */ static void set_child_handler_action_flags (int set_handler, int set_alarm) { struct sigaction sa; #ifdef __EMX__ /* The child handler must be turned off here. */ signal (SIGCHLD, SIG_DFL); #endif memset (&sa, '\0', sizeof sa); sa.sa_handler = child_handler; sa.sa_flags = set_handler ? 0 : SA_RESTART; #if defined SIGCHLD sigaction (SIGCHLD, &sa, NULL); #endif #if defined SIGCLD && SIGCLD != SIGCHLD sigaction (SIGCLD, &sa, NULL); #endif #if defined SIGALRM if (set_alarm) { /* If we're about to enter the read(), set an alarm to wake up in a second so we can check if the load has dropped and we can start more work. On the way out, turn off the alarm and set SIG_DFL. */ if (set_handler) { sa.sa_handler = job_noop; sa.sa_flags = 0; sigaction (SIGALRM, &sa, NULL); alarm (1); } else { alarm (0); sa.sa_handler = SIG_DFL; sa.sa_flags = 0; sigaction (SIGALRM, &sa, NULL); } } #endif } #endif /* Start a job to run the commands specified in CHILD. CHILD is updated to reflect the commands and ID of the child process. NOTE: On return fatal signals are blocked! The caller is responsible for calling 'unblock_sigs', once the new child is safely on the chain so it can be cleaned up in the event of a fatal signal. */ static void start_job_command (child_t *child, target_stack_node_t *p_call_stack) { #if !defined(_AMIGA) && !defined(WINDOWS32) static int bad_stdin = -1; #endif int flags; char *p; #ifdef VMS char *argv; #else char **argv; int outfd = FD_STDOUT; int errfd = FD_STDERR; #endif /* If we have a completely empty commandset, stop now. */ if (!child->command_ptr) goto next_command; /* Combine the flags parsed for the line itself with the flags specified globally for this target. */ flags = (child->file->command_flags | child->file->cmds->lines_flags[child->command_line - 1]); p = child->command_ptr; child->noerror = ((flags & COMMANDS_NOERROR) != 0); while (*p != '\0') { if (*p == '@') flags |= COMMANDS_SILENT; else if (*p == '+') flags |= COMMANDS_RECURSE; else if (*p == '-') child->noerror = 1; else if (!isblank ((unsigned char)*p)) break; ++p; } /* Update the file's command flags with any new ones we found. We only keep the COMMANDS_RECURSE setting. Even this isn't 100% correct; we are now marking more commands recursive than should be in the case of multiline define/endef scripts where only one line is marked "+". In order to really fix this, we'll have to keep a lines_flags for every actual line, after expansion. */ child->file->cmds->lines_flags[child->command_line - 1] |= flags & COMMANDS_RECURSE; /* POSIX requires that a recipe prefix after a backslash-newline should be ignored. Remove it now so the output is correct. */ { char prefix = child->file->cmds->recipe_prefix; char *p1, *p2; p1 = p2 = p; while (*p1 != '\0') { *(p2++) = *p1; if (p1[0] == '\n' && p1[1] == prefix) ++p1; ++p1; } *p2 = *p1; } /* Figure out an argument list from this command line. */ { char *end = 0; #ifdef VMS argv = p; /* Although construct_command_argv contains some code for VMS, it was/is not called/used. Please note, for VMS argv is a string (not an array of strings) which contains the complete command line, which for multi-line variables still includes the newlines. So detect newlines and set 'end' (which is used for child->command_ptr) instead of (re-)writing construct_command_argv */ if (!one_shell) { char *s = p; int instring = 0; while (*s) { if (*s == '"') instring = !instring; else if (*s == '\\' && !instring && *(s+1) != 0) s++; else if (*s == '\n' && !instring) { end = s; break; } ++s; } } #else argv = construct_command_argv (p, &end, child->file, child->file->cmds->lines_flags[child->command_line - 1], &child->sh_batch_file); #endif if (end == NULL) child->command_ptr = NULL; else { *end++ = '\0'; child->command_ptr = end; } } /* If -q was given, say that updating 'failed' if there was any text on the command line, or 'succeeded' otherwise. The exit status of 1 tells the user that -q is saying 'something to do'; the exit status for a random error is 2. */ if (argv != 0 && question_flag && !(flags & COMMANDS_RECURSE)) { #ifndef VMS free (argv[0]); free (argv); #endif child->file->update_status = us_question; notice_finished_file (child->file); return; } if (touch_flag && !(flags & COMMANDS_RECURSE)) { /* Go on to the next command. It might be the recursive one. We construct ARGV only to find the end of the command line. */ #ifndef VMS if (argv) { free (argv[0]); free (argv); } #endif argv = 0; } if (argv == 0) { next_command: #ifdef __MSDOS__ execute_by_shell = 0; /* in case construct_command_argv sets it */ #endif /* This line has no commands. Go to the next. */ if (job_next_command (child)) start_job_command (child, p_call_stack); else { /* No more commands. Make sure we're "running"; we might not be if (e.g.) all commands were skipped due to -n. */ set_command_state (child->file, cs_running); child->file->update_status = us_success; notice_finished_file (child->file); } OUTPUT_UNSET(); return; } /* Are we going to synchronize this command's output? Do so if either we're in SYNC_RECURSE mode or this command is not recursive. We'll also check output_sync separately below in case it changes due to error. */ child->output.syncout = output_sync && (output_sync == OUTPUT_SYNC_RECURSE || !(flags & COMMANDS_RECURSE)); OUTPUT_SET (&child->output); #ifndef NO_OUTPUT_SYNC if (! child->output.syncout) /* We don't want to sync this command: to avoid misordered output ensure any already-synced content is written. */ output_dump (&child->output); #endif /* Print the command if appropriate. */ { bool print_it = (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag) || (db_level & DB_SHELL)); if (print_it) { if (db_level & DB_SHELL) { char pid_str[20] = ">>"; if (job_slots != 1) snprintf(pid_str, sizeof(pid_str), "%d", child->pid); OS (message, 0, "##>>>>>>>>>>>>>>>>>>>>>>>>>>%s>>>>>>>>>>>>>>>>>>>>>>>>>>>>", pid_str); OS (message, 0, "%s", p); OS (message, 0, "##<<<<<<<<<<<<<<<<<<<<<<<<<<%s<<<<<<<<<<<<<<<<<<<<<<<<<<<<", job_slots != 1 ? pid_str : "<<"); } else OS (message, 0, "%s", p); } } /* Tell update_goal_chain that a command has been started on behalf of this target. It is important that this happens here and not in reap_children (where we used to do it), because reap_children might be reaping children from a different target. We want this increment to guaranteedly indicate that a command was started for the dependency chain (i.e., update_file recursion chain) we are processing. */ ++commands_started; /* Optimize an empty command. People use this for timestamp rules, so avoid forking a useless shell. Do this after we increment commands_started so make still treats this special case as if it performed some action (makes a difference as to what messages are printed, etc. */ #if !defined(VMS) && !defined(_AMIGA) if ( #if defined __MSDOS__ || defined (__EMX__) unixy_shell /* the test is complicated and we already did it */ #else (argv[0] && is_bourne_compatible_shell (argv[0])) #endif && (argv[1] && argv[1][0] == '-' && ((argv[1][1] == 'c' && argv[1][2] == '\0') || (argv[1][1] == 'e' && argv[1][2] == 'c' && argv[1][3] == '\0'))) && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0') && argv[3] == NULL) { free (argv[0]); free (argv); goto next_command; } #endif /* !VMS && !_AMIGA */ /* If -n was given, recurse to get the next line in the sequence. */ if (just_print_flag && !(flags & COMMANDS_RECURSE)) { #ifndef VMS free (argv[0]); free (argv); #endif goto next_command; } /* We're sure we're going to invoke a command: set up the output. */ output_start (); p_stack_top = p_call_stack; if (i_debugger_stepping) enter_debugger(p_call_stack, child->file, 0, DEBUG_STEP_COMMAND); /* Flush the output streams so they won't have things written twice. */ fflush (stdout); fflush (stderr); #ifndef VMS #if !defined(WINDOWS32) && !defined(_AMIGA) && !defined(__MSDOS__) /* Set up a bad standard input that reads from a broken pipe. */ if (bad_stdin == -1) { /* Make a file descriptor that is the read end of a broken pipe. This will be used for some children's standard inputs. */ int pd[2]; if (pipe (pd) == 0) { /* Close the write side. */ (void) close (pd[1]); /* Save the read side. */ bad_stdin = pd[0]; /* Set the descriptor to close on exec, so it does not litter any child's descriptor table. When it is dup2'd onto descriptor 0, that descriptor will not close on exec. */ CLOSE_ON_EXEC (bad_stdin); } } #endif /* !WINDOWS32 && !_AMIGA && !__MSDOS__ */ /* Decide whether to give this child the 'good' standard input (one that points to the terminal or whatever), or the 'bad' one that points to the read side of a broken pipe. */ child->good_stdin = !good_stdin_used; if (child->good_stdin) good_stdin_used = 1; #endif /* !VMS */ child->deleted = 0; #ifndef _AMIGA /* Set up the environment for the child. */ if (child->environment == 0) child->environment = target_environment (child->file); #endif #if !defined(__MSDOS__) && !defined(_AMIGA) && !defined(WINDOWS32) #ifndef VMS /* start_waiting_job has set CHILD->remote if we can start a remote job. */ if (child->remote) { int is_remote, id, used_stdin; if (start_remote_job (argv, child->environment, child->good_stdin ? 0 : bad_stdin, &is_remote, &id, &used_stdin)) /* Don't give up; remote execution may fail for various reasons. If so, simply run the job locally. */ goto run_local; else { if (child->good_stdin && !used_stdin) { child->good_stdin = 0; good_stdin_used = 0; } child->remote = is_remote; child->pid = id; } } else #endif /* !VMS */ { /* Fork the child process. */ char **parent_environ; run_local: block_sigs (); child->remote = 0; #ifdef VMS if (!child_execute_job (argv, child)) { /* Fork failed! */ perror_with_name ("fork", ""); goto error; } #else parent_environ = environ; #ifndef NO_OUTPUT_SYNC /* Divert child output if output_sync in use. */ if (child->output.syncout) { if (child->output.out >= 0) outfd = child->output.out; if (child->output.err >= 0) errfd = child->output.err; } #endif # ifdef __EMX__ /* If we aren't running a recursive command and we have a jobserver pipe, close it before exec'ing. */ if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { CLOSE_ON_EXEC (job_fds[0]); CLOSE_ON_EXEC (job_fds[1]); } if (job_rfd >= 0) CLOSE_ON_EXEC (job_rfd); /* Never use fork()/exec() here! Use spawn() instead in exec_command() */ child->pid = child_execute_job (child->good_stdin ? FD_STDIN : bad_stdin, outfd, errfd, argv, child->environment); if (child->pid < 0) { /* spawn failed! */ unblock_sigs (); perror_with_name ("spawn", ""); goto error; } /* undo CLOSE_ON_EXEC() after the child process has been started */ if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { fcntl (job_fds[0], F_SETFD, 0); fcntl (job_fds[1], F_SETFD, 0); } if (job_rfd >= 0) fcntl (job_rfd, F_SETFD, 0); #else /* !__EMX__ */ child->pid = fork (); environ = parent_environ; /* Restore value child may have clobbered. */ if (child->pid == 0) { /* We are the child side. */ unblock_sigs (); /* If we aren't running a recursive command and we have a jobserver pipe, close it before exec'ing. */ if (!(flags & COMMANDS_RECURSE) && job_fds[0] >= 0) { close (job_fds[0]); close (job_fds[1]); } if (job_rfd >= 0) close (job_rfd); #ifdef SET_STACK_SIZE /* Reset limits, if necessary. */ if (stack_limit.rlim_cur) setrlimit (RLIMIT_STACK, &stack_limit); #endif child_execute_job (child->good_stdin ? FD_STDIN : bad_stdin, outfd, errfd, argv, child->environment); } else if (child->pid < 0) { /* Fork failed! */ unblock_sigs (); perror_with_name ("fork", ""); goto error; } # endif /* !__EMX__ */ #endif /* !VMS */ } #else /* __MSDOS__ or Amiga or WINDOWS32 */ #ifdef __MSDOS__ { int proc_return; block_sigs (); dos_status = 0; /* We call 'system' to do the job of the SHELL, since stock DOS shell is too dumb. Our 'system' knows how to handle long command lines even if pipes/redirection is needed; it will only call COMMAND.COM when its internal commands are used. */ if (execute_by_shell) { char *cmdline = argv[0]; /* We don't have a way to pass environment to 'system', so we need to save and restore ours, sigh... */ char **parent_environ = environ; environ = child->environment; /* If we have a *real* shell, tell 'system' to call it to do everything for us. */ if (unixy_shell) { /* A *real* shell on MSDOS may not support long command lines the DJGPP way, so we must use 'system'. */ cmdline = argv[2]; /* get past "shell -c" */ } dos_command_running = 1; proc_return = system (cmdline); environ = parent_environ; execute_by_shell = 0; /* for the next time */ } else { dos_command_running = 1; proc_return = spawnvpe (P_WAIT, argv[0], argv, child->environment); } /* Need to unblock signals before turning off dos_command_running, so that child's signals will be treated as such (see fatal_error_signal). */ unblock_sigs (); dos_command_running = 0; /* If the child got a signal, dos_status has its high 8 bits set, so be careful not to alter them. */ if (proc_return == -1) dos_status |= 0xff; else dos_status |= (proc_return & 0xff); ++dead_children; child->pid = dos_pid++; } #endif /* __MSDOS__ */ #ifdef _AMIGA amiga_status = MyExecute (argv); ++dead_children; child->pid = amiga_pid++; if (amiga_batch_file) { amiga_batch_file = 0; DeleteFile (amiga_bname); /* Ignore errors. */ } #endif /* Amiga */ #ifdef WINDOWS32 { HANDLE hPID; char* arg0; /* make UNC paths safe for CreateProcess -- backslash format */ arg0 = argv[0]; if (arg0 && arg0[0] == '/' && arg0[1] == '/') for ( ; arg0 && *arg0; arg0++) if (*arg0 == '/') *arg0 = '\\'; /* make sure CreateProcess() has Path it needs */ sync_Path_environment (); #ifndef NO_OUTPUT_SYNC /* Divert child output if output_sync in use. */ if (child->output.syncout) { if (child->output.out >= 0) outfd = child->output.out; if (child->output.err >= 0) errfd = child->output.err; } #else outfd = errfd = -1; #endif hPID = process_easy (argv, child->environment, outfd, errfd); if (hPID != INVALID_HANDLE_VALUE) child->pid = (pid_t) hPID; else { int i; unblock_sigs (); fprintf (stderr, _("process_easy() failed to launch process (e=%ld)\n"), process_last_err (hPID)); for (i = 0; argv[i]; i++) fprintf (stderr, "%s ", argv[i]); fprintf (stderr, _("\nCounted %d args in failed launch\n"), i); goto error; } } #endif /* WINDOWS32 */ #endif /* __MSDOS__ or Amiga or WINDOWS32 */ /* Bump the number of jobs started in this second. */ ++job_counter; /* We are the parent side. Set the state to say the commands are running and return. */ set_command_state (child->file, cs_running); /* Free the storage used by the child's argument list. */ #ifndef VMS free (argv[0]); free (argv); #endif OUTPUT_UNSET(); return; error: child->file->update_status = us_failed; notice_finished_file (child->file); OUTPUT_UNSET(); } /* Try to start a child running. Returns nonzero if the child was started (and maybe finished), or zero if the load was too high and the child was put on the 'waiting_jobs' chain. */ static int start_waiting_job (struct child *c, target_stack_node_t *p_call_stack) { struct file *f = c->file; /* If we can start a job remotely, we always want to, and don't care about the local load average. We record that the job should be started remotely in C->remote for start_job_command to test. */ c->remote = start_remote_job_p (1); /* If we are running at least one job already and the load average is too high, make this one wait. */ if (!c->remote && ((job_slots_used > 0 && load_too_high ()) #ifdef WINDOWS32 || (process_used_slots () >= MAXIMUM_WAIT_OBJECTS) #endif )) { /* Put this child on the chain of children waiting for the load average to go down. */ set_command_state (f, cs_running); c->next = waiting_jobs; waiting_jobs = c; return 0; } /* Start the first command; reap_children will run later command lines. */ start_job_command (c, p_call_stack); switch (f->command_state) { case cs_running: c->next = children; DB (DB_JOBS, (_("Putting child %p (%s) PID %s%s on the chain.\n"), c, c->file->name, pid2str (c->pid), c->remote ? _(" (remote)") : "")); children = c; /* One more job slot is in use. */ ++job_slots_used; unblock_sigs (); break; case cs_not_started: /* All the command lines turned out to be empty. */ f->update_status = us_success; /* FALLTHROUGH */ case cs_finished: notice_finished_file (f); free_child (c); break; default: assert (f->command_state == cs_finished); break; } return 1; } /* Create a 'struct child' for FILE and start its commands running. */ void new_job (struct file *file, target_stack_node_t *p_call_stack) { struct commands *cmds = file->cmds; struct child *c; char **lines; unsigned int i; /* Let any previously decided-upon jobs that are waiting for the load to go down start before this new one. */ start_waiting_jobs (p_call_stack); /* Reap any children that might have finished recently. */ reap_children (0, 0, p_call_stack); /* Chop the commands up into lines if they aren't already. */ chop_commands (cmds); /* Start the command sequence, record it in a new 'struct child', and add that to the chain. */ c = xcalloc (sizeof (struct child)); output_init (&c->output); c->file = file; c->sh_batch_file = NULL; /* Cache dontcare flag because file->dontcare can be changed once we return. Check dontcare inheritance mechanism for details. */ c->dontcare = file->dontcare; /* Start saving output in case the expansion uses $(info ...) etc. */ OUTPUT_SET (&c->output); /* Expand the command lines and store the results in LINES. */ lines = xmalloc (cmds->ncommand_lines * sizeof (char *)); for (i = 0; i < cmds->ncommand_lines; ++i) { /* Collapse backslash-newline combinations that are inside variable or function references. These are left alone by the parser so that they will appear in the echoing of commands (where they look nice); and collapsed by construct_command_argv when it tokenizes. But letting them survive inside function invocations loses because we don't want the functions to see them as part of the text. */ char *in, *out, *ref; /* IN points to where in the line we are scanning. OUT points to where in the line we are writing. When we collapse a backslash-newline combination, IN gets ahead of OUT. */ in = out = cmds->command_lines[i]; while ((ref = strchr (in, '$')) != 0) { ++ref; /* Move past the $. */ if (out != in) /* Copy the text between the end of the last chunk we processed (where IN points) and the new chunk we are about to process (where REF points). */ memmove (out, in, ref - in); /* Move both pointers past the boring stuff. */ out += ref - in; in = ref; if (*ref == '(' || *ref == '{') { char openparen = *ref; char closeparen = openparen == '(' ? ')' : '}'; char *outref; int count; char *p; *out++ = *in++; /* Copy OPENPAREN. */ outref = out; /* IN now points past the opening paren or brace. Count parens or braces until it is matched. */ count = 0; while (*in != '\0') { if (*in == closeparen && --count < 0) break; else if (*in == '\\' && in[1] == '\n') { /* We have found a backslash-newline inside a variable or function reference. Eat it and any following whitespace. */ int quoted = 0; for (p = in - 1; p > ref && *p == '\\'; --p) quoted = !quoted; if (quoted) /* There were two or more backslashes, so this is not really a continuation line. We don't collapse the quoting backslashes here as is done in collapse_continuations, because the line will be collapsed again after expansion. */ *out++ = *in++; else { /* Skip the backslash, newline and any following whitespace. */ in = next_token (in + 2); /* Discard any preceding whitespace that has already been written to the output. */ while (out > outref && isblank ((unsigned char)out[-1])) --out; /* Replace it all with a single space. */ *out++ = ' '; } } else { if (*in == openparen) ++count; *out++ = *in++; } } } } /* There are no more references in this line to worry about. Copy the remaining uninteresting text to the output. */ if (out != in) memmove (out, in, strlen (in) + 1); /* Finally, expand the line. */ lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], file); } c->command_lines = lines; /* Fetch the first command line to be run. */ job_next_command (c); /* Wait for a job slot to be freed up. If we allow an infinite number don't bother; also job_slots will == 0 if we're using the jobserver. */ if (job_slots != 0) while (job_slots_used == job_slots) reap_children (1, 0, p_call_stack); #ifdef MAKE_JOBSERVER /* If we are controlling multiple jobs make sure we have a token before starting the child. */ /* This can be inefficient. There's a decent chance that this job won't actually have to run any subprocesses: the command script may be empty or otherwise optimized away. It would be nice if we could defer obtaining a token until just before we need it, in start_job_command. To do that we'd need to keep track of whether we'd already obtained a token (since start_job_command is called for each line of the job, not just once). Also more thought needs to go into the entire algorithm; this is where the old parallel job code waits, so... */ #ifdef WINDOWS32 else if (has_jobserver_semaphore ()) #else else if (job_fds[0] >= 0) #endif while (1) { int got_token; #ifndef WINDOWS32 char token; int saved_errno; #endif DB (DB_JOBS, ("Need a job token; we %shave children\n", children ? "" : "don't ")); /* If we don't already have a job started, use our "free" token. */ if (!jobserver_tokens) break; #ifndef WINDOWS32 /* Read a token. As long as there's no token available we'll block. We enable interruptible system calls before the read(2) so that if we get a SIGCHLD while we're waiting, we'll return with EINTR and we can process the death(s) and return tokens to the free pool. Once we return from the read, we immediately reinstate restartable system calls. This allows us to not worry about checking for EINTR on all the other system calls in the program. There is one other twist: there is a span between the time reap_children() does its last check for dead children and the time the read(2) call is entered, below, where if a child dies we won't notice. This is extremely serious as it could cause us to deadlock, given the right set of events. To avoid this, we do the following: before we reap_children(), we dup(2) the read FD on the jobserver pipe. The read(2) call below uses that new FD. In the signal handler, we close that FD. That way, if a child dies during the section mentioned above, the read(2) will be invoked with an invalid FD and will return immediately with EBADF. */ /* Make sure we have a dup'd FD. */ if (job_rfd < 0) { DB (DB_JOBS, ("Duplicate the job FD\n")); job_rfd = dup (job_fds[0]); } #endif /* Reap anything that's currently waiting. */ reap_children (0, 0, p_call_stack); /* Kick off any jobs we have waiting for an opportunity that can run now (i.e., waiting for load). */ start_waiting_jobs (p_call_stack); /* If our "free" slot has become available, use it; we don't need an actual token. */ if (!jobserver_tokens) break; /* There must be at least one child already, or we have no business waiting for a token. */ if (!children) fatal_err(p_call_stack, "INTERNAL: no children as we go to sleep on read"); #ifdef WINDOWS32 /* On Windows we simply wait for the jobserver semaphore to become * signalled or one of our child processes to terminate. */ got_token = wait_for_semaphore_or_child_process (); if (got_token < 0) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); fatal_err(_("semaphore or child process wait: (Error %ld: %s)"), err, estr); } #else /* Set interruptible system calls, and read() for a job token. */ set_child_handler_action_flags (1, waiting_jobs != NULL); got_token = read (job_rfd, &token, 1); saved_errno = errno; set_child_handler_action_flags (0, waiting_jobs != NULL); #endif /* If we got one, we're done here. */ if (got_token == 1) { DB (DB_JOBS, (_("Obtained token for child %p (%s).\n"), c, c->file->name)); break; } #ifndef WINDOWS32 /* If the error _wasn't_ expected (EINTR or EBADF), punt. Otherwise, go back and reap_children(), and try again. */ errno = saved_errno; if (errno != EINTR && errno != EBADF) pfatal_with_name (_("read jobs pipe")); if (errno == EBADF) DB (DB_JOBS, ("Read returned EBADF.\n")); #endif } #endif ++jobserver_tokens; /* Trace the build. Use message here so that changes to working directories are logged. */ if (db_level & DB_SHELL) { char *newer = allocated_variable_expand_for_file ("$?", c->file); const char *nm; if (! cmds->fileinfo.filenm) nm = _(""); else { char *n = alloca (strlen (cmds->fileinfo.filenm) + 1 + 11 + 1); sprintf (n, "%s:%lu", cmds->fileinfo.filenm, cmds->fileinfo.lineno); nm = n; } if (newer[0] == '\0') OSS (message, 0, _("%s: target '%s' does not exist"), nm, c->file->name); else OSSS (message, 0, _("%s: update target '%s' due to: %s"), nm, c->file->name, newer); free (newer); } /* FIXME: The below is a sign that we need update location somewhere else */ if (cmds->fileinfo.filenm) { if (!file->floc.filenm) { file->floc.filenm = cmds->fileinfo.filenm; file->floc.lineno = cmds->fileinfo.lineno - 1; if (!p_call_stack->p_target->floc.filenm) { p_call_stack->p_target->floc.filenm = file->floc.filenm; p_call_stack->p_target->floc.lineno = file->floc.lineno; } } } /* The job is now primed. Start it running. (This will notice if there is in fact no recipe.) */ (void) start_waiting_job (c, p_call_stack); if (job_slots == 1 || not_parallel) /* Since there is only one job slot, make things run linearly. Wait for the child to die, setting the state to 'cs_finished'. */ while (file->command_state == cs_running) reap_children (1, 0, p_call_stack); OUTPUT_UNSET (); return; } /* Move CHILD's pointers to the next command for it to execute. Returns nonzero if there is another command. */ static int job_next_command (struct child *child) { while (child->command_ptr == 0 || *child->command_ptr == '\0') { /* There are no more lines in the expansion of this line. */ if (child->command_line == child->file->cmds->ncommand_lines) { /* There are no more lines to be expanded. */ child->command_ptr = 0; return 0; } else /* Get the next line to run. */ child->command_ptr = child->command_lines[child->command_line++]; } return 1; } /* Determine if the load average on the system is too high to start a new job. The real system load average is only recomputed once a second. However, a very parallel make can easily start tens or even hundreds of jobs in a second, which brings the system to its knees for a while until that first batch of jobs clears out. To avoid this we use a weighted algorithm to try to account for jobs which have been started since the last second, and guess what the load average would be now if it were computed. This algorithm was provided by Thomas Riedl , who writes: ! calculate something load-oid and add to the observed sys.load, ! so that latter can catch up: ! - every job started increases jobctr; ! - every dying job decreases a positive jobctr; ! - the jobctr value gets zeroed every change of seconds, ! after its value*weight_b is stored into the 'backlog' value last_sec ! - weight_a times the sum of jobctr and last_sec gets ! added to the observed sys.load. ! ! The two weights have been tried out on 24 and 48 proc. Sun Solaris-9 ! machines, using a several-thousand-jobs-mix of cpp, cc, cxx and smallish ! sub-shelled commands (rm, echo, sed...) for tests. ! lowering the 'direct influence' factor weight_a (e.g. to 0.1) ! resulted in significant excession of the load limit, raising it ! (e.g. to 0.5) took bad to small, fast-executing jobs and didn't ! reach the limit in most test cases. ! ! lowering the 'history influence' weight_b (e.g. to 0.1) resulted in ! exceeding the limit for longer-running stuff (compile jobs in ! the .5 to 1.5 sec. range),raising it (e.g. to 0.5) overrepresented ! small jobs' effects. */ #define LOAD_WEIGHT_A 0.25 #define LOAD_WEIGHT_B 0.25 static int load_too_high (void) { #if defined(__MSDOS__) || defined(VMS) || defined(_AMIGA) || defined(__riscos__) return 1; #else static double last_sec; static time_t last_now; double load, guess; time_t now; #ifdef WINDOWS32 /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS children */ if (process_used_slots () >= MAXIMUM_WAIT_OBJECTS) return 1; #endif if (max_load_average < 0) return 0; /* Find the real system load average. */ make_access (); if (getloadavg (&load, 1) != 1) { static int lossage = -1; /* Complain only once for the same error. */ if (lossage == -1 || errno != lossage) { if (errno == 0) /* An errno value of zero means getloadavg is just unsupported. */ O (error, NILF, _("cannot enforce load limits on this operating system")); else perror_with_name (_("cannot enforce load limit: "), "getloadavg"); } lossage = errno; load = 0; } user_access (); /* If we're in a new second zero the counter and correct the backlog value. Only keep the backlog for one extra second; after that it's 0. */ now = time (NULL); if (last_now < now) { if (last_now == now - 1) last_sec = LOAD_WEIGHT_B * job_counter; else last_sec = 0.0; job_counter = 0; last_now = now; } /* Try to guess what the load would be right now. */ guess = load + (LOAD_WEIGHT_A * (job_counter + last_sec)); DB (DB_JOBS, ("Estimated system load = %f (actual = %f) (max requested = %f)\n", guess, load, max_load_average)); return guess >= max_load_average; #endif } /* Start jobs that are waiting for the load to be lower. */ void start_waiting_jobs (target_stack_node_t *p_call_stack) { struct child *job; if (waiting_jobs == 0) return; do { /* Check for recently deceased descendants. */ reap_children (0, 0, NULL); /* Take a job off the waiting list. */ job = waiting_jobs; waiting_jobs = job->next; /* Try to start that job. We break out of the loop as soon as start_waiting_job puts one back on the waiting list. */ } while (start_waiting_job (job, p_call_stack) && waiting_jobs != 0); return; } #ifndef WINDOWS32 /* EMX: Start a child process. This function returns the new pid. */ # if defined __EMX__ int child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd, char **argv, char **envp) { int pid; int save_stdin = -1; int save_stdout = -1; int save_stderr = -1; /* For each FD which needs to be redirected first make a dup of the standard FD to save and mark it close on exec so our child won't see it. Then dup2() the standard FD to the redirect FD, and also mark the redirect FD as close on exec. */ if (stdin_fd != FD_STDIN) { save_stdin = dup (FD_STDIN); if (save_stdin < 0) O (fatal, NILF, _("no more file handles: could not duplicate stdin\n")); CLOSE_ON_EXEC (save_stdin); dup2 (stdin_fd, FD_STDIN); CLOSE_ON_EXEC (stdin_fd); } if (stdout_fd != FD_STDOUT) { save_stdout = dup (FD_STDOUT); if (save_stdout < 0) O (fatal, NILF, _("no more file handles: could not duplicate stdout\n")); CLOSE_ON_EXEC (save_stdout); dup2 (stdout_fd, FD_STDOUT); CLOSE_ON_EXEC (stdout_fd); } if (stderr_fd != FD_STDERR) { if (stderr_fd != stdout_fd) { save_stderr = dup (FD_STDERR); if (save_stderr < 0) O (fatal, NILF, _("no more file handles: could not duplicate stderr\n")); CLOSE_ON_EXEC (save_stderr); } dup2 (stderr_fd, FD_STDERR); CLOSE_ON_EXEC (stderr_fd); } /* Run the command. */ pid = exec_command (argv, envp); /* Restore stdout/stdin/stderr of the parent and close temporary FDs. */ if (save_stdin >= 0) { if (dup2 (save_stdin, FD_STDIN) != FD_STDIN) O (fatal, NILF, _("Could not restore stdin\n")); else close (save_stdin); } if (save_stdout >= 0) { if (dup2 (save_stdout, FD_STDOUT) != FD_STDOUT) O (fatal, NILF, _("Could not restore stdout\n")); else close (save_stdout); } if (save_stderr >= 0) { if (dup2 (save_stderr, FD_STDERR) != FD_STDERR) O (fatal, NILF, _("Could not restore stderr\n")); else close (save_stderr); } return pid; } #elif !defined (_AMIGA) && !defined (__MSDOS__) && !defined (VMS) /* UNIX: Replace the current process with one executing the command in ARGV. STDIN_FD/STDOUT_FD/STDERR_FD are used as the process's stdin/stdout/stderr; ENVP is the environment of the new program. This function does not return. */ void child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd, char **argv, char **envp) { /* For any redirected FD, dup2() it to the standard FD then close it. */ if (stdin_fd != FD_STDIN) { dup2 (stdin_fd, FD_STDIN); close (stdin_fd); } if (stdout_fd != FD_STDOUT) dup2 (stdout_fd, FD_STDOUT); if (stderr_fd != FD_STDERR) dup2 (stderr_fd, FD_STDERR); if (stdout_fd != FD_STDOUT) close (stdout_fd); if (stderr_fd != FD_STDERR && stderr_fd != stdout_fd) close (stderr_fd); /* Run the command. */ exec_command (argv, envp); } #endif /* !AMIGA && !__MSDOS__ && !VMS */ #endif /* !WINDOWS32 */ #ifndef _AMIGA /* Replace the current process with one running the command in ARGV, with environment ENVP. This function does not return. */ /* EMX: This function returns the pid of the child process. */ # ifdef __EMX__ int # else void # endif exec_command (char **argv, char **envp) { #ifdef VMS /* to work around a problem with signals and execve: ignore them */ #ifdef SIGCHLD signal (SIGCHLD,SIG_IGN); #endif /* Run the program. */ execve (argv[0], argv, envp); perror_with_name ("execve: ", argv[0]); _exit (EXIT_FAILURE); #else #ifdef WINDOWS32 HANDLE hPID; HANDLE hWaitPID; int exit_code = EXIT_FAILURE; /* make sure CreateProcess() has Path it needs */ sync_Path_environment (); /* launch command */ hPID = process_easy (argv, envp, -1, -1); /* make sure launch ok */ if (hPID == INVALID_HANDLE_VALUE) { int i; fprintf (stderr, _("process_easy() failed to launch process (e=%ld)\n"), process_last_err (hPID)); for (i = 0; argv[i]; i++) fprintf (stderr, "%s ", argv[i]); fprintf (stderr, _("\nCounted %d args in failed launch\n"), i); exit (EXIT_FAILURE); } /* wait and reap last child */ hWaitPID = process_wait_for_any (1, 0); while (hWaitPID) { /* was an error found on this process? */ int err = process_last_err (hWaitPID); /* get exit data */ exit_code = process_exit_code (hWaitPID); if (err) fprintf (stderr, "make (e=%d, rc=%d): %s", err, exit_code, map_windows32_error_to_string (err)); /* cleanup process */ process_cleanup (hWaitPID); /* expect to find only last pid, warn about other pids reaped */ if (hWaitPID == hPID) break; else { char *pidstr = xstrdup (pid2str ((pid_t)hWaitPID)); fprintf (stderr, _("make reaped child pid %s, still waiting for pid %s\n"), pidstr, pid2str ((pid_t)hPID)); free (pidstr); } } /* return child's exit code as our exit code */ exit (exit_code); #else /* !WINDOWS32 */ # ifdef __EMX__ int pid; # endif /* Be the user, permanently. */ child_access (); # ifdef __EMX__ /* Run the program. */ pid = spawnvpe (P_NOWAIT, argv[0], argv, envp); if (pid >= 0) return pid; /* the file might have a strange shell extension */ if (errno == ENOENT) errno = ENOEXEC; # else /* Run the program. */ environ = envp; execvp (argv[0], argv); # endif /* !__EMX__ */ switch (errno) { case ENOENT: OS (error, NILF, _("%s: Command not found"), argv[0]); break; case ENOEXEC: { /* The file is not executable. Try it as a shell script. */ extern char *getenv (); const char *shell; char **new_argv; int argc; int i=1; # ifdef __EMX__ /* Do not use $SHELL from the environment */ struct variable *p = lookup_variable ("SHELL", 5); if (p) shell = p->value; else shell = 0; # else shell = getenv ("SHELL"); # endif if (shell == 0) shell = default_shell; argc = 1; while (argv[argc] != 0) ++argc; # ifdef __EMX__ if (!unixy_shell) ++argc; # endif new_argv = alloca ((1 + argc + 1) * sizeof (char *)); new_argv[0] = (char *)shell; # ifdef __EMX__ if (!unixy_shell) { new_argv[1] = "/c"; ++i; --argc; } # endif new_argv[i] = argv[0]; while (argc > 0) { new_argv[i + argc] = argv[argc]; --argc; } # ifdef __EMX__ pid = spawnvpe (P_NOWAIT, shell, new_argv, envp); if (pid >= 0) break; # else execvp (shell, new_argv); # endif if (errno == ENOENT) OS (error, NILF, _("%s: Shell program not found"), shell); else perror_with_name ("execvp: ", shell); break; } # ifdef __EMX__ case EINVAL: /* this nasty error was driving me nuts :-( */ O (error, NILF, _("spawnvpe: environment space might be exhausted")); /* FALLTHROUGH */ # endif default: perror_with_name ("execvp: ", argv[0]); break; } # ifdef __EMX__ return pid; # else _exit (127); # endif #endif /* !WINDOWS32 */ #endif /* !VMS */ } #else /* On Amiga */ void exec_command (char **argv) { MyExecute (argv); } void clean_tmp (void) { DeleteFile (amiga_bname); } #endif /* On Amiga */ #ifndef VMS /* Figure out the argument list necessary to run LINE as a command. Try to avoid using a shell. This routine handles only ' quoting, and " quoting when no backslash, $ or ' characters are seen in the quotes. Starting quotes may be escaped with a backslash. If any of the characters in sh_chars is seen, or any of the builtin commands listed in sh_cmds is the first word of a line, the shell is used. If RESTP is not NULL, *RESTP is set to point to the first newline in LINE. If *RESTP is NULL, newlines will be ignored. SHELL is the shell to use, or nil to use the default shell. IFS is the value of $IFS, or nil (meaning the default). FLAGS is the value of lines_flags for this command line. It is used in the WINDOWS32 port to check whether + or $(MAKE) were found in this command line, in which case the effect of just_print_flag is overridden. */ static char ** construct_command_argv_internal (char *line, char **restp, const char *shell, const char *shellflags, const char *ifs, int flags, char **batch_filename UNUSED) { #ifdef MAX_ARG_STRLEN static char eval_line[] = "eval\\ \\\"set\\ x\\;\\ shift\\;\\ "; #define ARG_NUMBER_DIGITS 5 #define EVAL_LEN (sizeof(eval_line)-1 + shell_len + 4 \ + (7 + ARG_NUMBER_DIGITS) * 2 * line_len / (MAX_ARG_STRLEN - 2)) #else #define EVAL_LEN 0 #endif #ifdef __MSDOS__ /* MSDOS supports both the stock DOS shell and ports of Unixy shells. We call 'system' for anything that requires ''slow'' processing, because DOS shells are too dumb. When $SHELL points to a real (unix-style) shell, 'system' just calls it to do everything. When $SHELL points to a DOS shell, 'system' does most of the work internally, calling the shell only for its internal commands. However, it looks on the $PATH first, so you can e.g. have an external command named 'mkdir'. Since we call 'system', certain characters and commands below are actually not specific to COMMAND.COM, but to the DJGPP implementation of 'system'. In particular: The shell wildcard characters are in DOS_CHARS because they will not be expanded if we call the child via 'spawnXX'. The ';' is in DOS_CHARS, because our 'system' knows how to run multiple commands on a single line. DOS_CHARS also include characters special to 4DOS/NDOS, so we won't have to tell one from another and have one more set of commands and special characters. */ static const char *sh_chars_dos = "*?[];|<>%^&()"; static const char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", "copy", "ctty", "date", "del", "dir", "echo", "erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause", "prompt", "rd", "rmdir", "rem", "ren", "rename", "set", "shift", "time", "type", "ver", "verify", "vol", ":", 0 }; static const char *sh_chars_sh = "#;\"*?[]&|<>(){}$`^"; static const char *sh_cmds_sh[] = { "cd", "echo", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "unset", "ulimit", 0 }; const char *sh_chars; const char **sh_cmds; #elif defined (__EMX__) static const char *sh_chars_dos = "*?[];|<>%^&()"; static const char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", "copy", "ctty", "date", "del", "dir", "echo", "erase", "exit", "for", "goto", "if", "md", "mkdir", "path", "pause", "prompt", "rd", "rmdir", "rem", "ren", "rename", "set", "shift", "time", "type", "ver", "verify", "vol", ":", 0 }; static const char *sh_chars_os2 = "*?[];|<>%^()\"'&"; static const char *sh_cmds_os2[] = { "call", "cd", "chcp", "chdir", "cls", "copy", "date", "del", "detach", "dir", "echo", "endlocal", "erase", "exit", "for", "goto", "if", "keys", "md", "mkdir", "move", "path", "pause", "prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "setlocal", "shift", "start", "time", "type", "ver", "verify", "vol", ":", 0 }; static const char *sh_chars_sh = "#;\"*?[]&|<>(){}$`^~'"; static const char *sh_cmds_sh[] = { "echo", "cd", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "unset", 0 }; const char *sh_chars; const char **sh_cmds; #elif defined (_AMIGA) static const char *sh_chars = "#;\"|<>()?*$`"; static const char *sh_cmds[] = { "cd", "eval", "if", "delete", "echo", "copy", "rename", "set", "setenv", "date", "makedir", "skip", "else", "endif", "path", "prompt", "unset", "unsetenv", "version", 0 }; #elif defined (WINDOWS32) /* We used to have a double quote (") in sh_chars_dos[] below, but that caused any command line with quoted file names be run through a temporary batch file, which introduces command-line limit of 4K charcaters imposed by cmd.exe. Since CreateProcess can handle quoted file names just fine, removing the quote lifts the limit from a very frequent use case, because using quoted file names is commonplace on MS-Windows. */ static const char *sh_chars_dos = "|&<>"; static const char *sh_cmds_dos[] = { "assoc", "break", "call", "cd", "chcp", "chdir", "cls", "color", "copy", "ctty", "date", "del", "dir", "echo", "echo.", "endlocal", "erase", "exit", "for", "ftype", "goto", "if", "if", "md", "mkdir", "move", "path", "pause", "prompt", "rd", "rem", "ren", "rename", "rmdir", "set", "setlocal", "shift", "time", "title", "type", "ver", "verify", "vol", ":", 0 }; static const char *sh_chars_sh = "#;\"*?[]&|<>(){}$`^"; static const char *sh_cmds_sh[] = { "cd", "eval", "exec", "exit", "login", "logout", "set", "umask", "wait", "while", "for", "case", "if", ":", ".", "break", "continue", "export", "read", "readonly", "shift", "times", "trap", "switch", "test", #ifdef BATCH_MODE_ONLY_SHELL "echo", #endif 0 }; const char *sh_chars; const char **sh_cmds; #elif defined(__riscos__) static const char *sh_chars = ""; static const char *sh_cmds[] = { 0 }; #else /* must be UNIX-ish */ static const char *sh_chars = "#;\"*?[]&|<>(){}$`^~!"; static const char *sh_cmds[] = { ".", ":", "break", "case", "cd", "continue", "eval", "exec", "exit", "export", "for", "if", "login", "logout", "read", "readonly", "set", "shift", "switch", "test", "times", "trap", "ulimit", "umask", "unset", "wait", "while", 0 }; # ifdef HAVE_DOS_PATHS /* This is required if the MSYS/Cygwin ports (which do not define WINDOWS32) are compiled with HAVE_DOS_PATHS defined, which uses sh_chars_sh directly (see below). The value must be identical to that of sh_chars immediately above. */ static const char *sh_chars_sh = "#;\"*?[]&|<>(){}$`^~!"; # endif /* HAVE_DOS_PATHS */ #endif int i; char *p; #ifndef NDEBUG char *end; #endif char *ap; const char *cap; const char *cp; int instring, word_has_equals, seen_nonequals, last_argument_was_empty; char **new_argv = 0; char *argstr = 0; #ifdef WINDOWS32 int slow_flag = 0; if (!unixy_shell) { sh_cmds = sh_cmds_dos; sh_chars = sh_chars_dos; } else { sh_cmds = sh_cmds_sh; sh_chars = sh_chars_sh; } #endif /* WINDOWS32 */ if (restp != NULL) *restp = NULL; /* Make sure not to bother processing an empty line. */ while (isblank ((unsigned char)*line)) ++line; if (*line == '\0') return 0; if (shellflags == 0) shellflags = posix_pedantic ? "-ec" : "-c"; /* See if it is safe to parse commands internally. */ if (shell == 0) shell = default_shell; #ifdef WINDOWS32 else if (strcmp (shell, default_shell)) { char *s1 = _fullpath (NULL, shell, 0); char *s2 = _fullpath (NULL, default_shell, 0); slow_flag = strcmp ((s1 ? s1 : ""), (s2 ? s2 : "")); free (s1); free (s2); } if (slow_flag) goto slow; #else /* not WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) else if (strcasecmp (shell, default_shell)) { extern int _is_unixy_shell (const char *_path); DB (DB_BASIC, (_("$SHELL changed (was '%s', now '%s')\n"), default_shell, shell)); unixy_shell = _is_unixy_shell (shell); /* we must allocate a copy of shell: construct_command_argv() will free * shell after this function returns. */ default_shell = xstrdup (shell); } if (unixy_shell) { sh_chars = sh_chars_sh; sh_cmds = sh_cmds_sh; } else { sh_chars = sh_chars_dos; sh_cmds = sh_cmds_dos; # ifdef __EMX__ if (_osmode == OS2_MODE) { sh_chars = sh_chars_os2; sh_cmds = sh_cmds_os2; } # endif } #else /* !__MSDOS__ */ else if (strcmp (shell, default_shell)) goto slow; #endif /* !__MSDOS__ && !__EMX__ */ #endif /* not WINDOWS32 */ if (ifs) for (cap = ifs; *cap != '\0'; ++cap) if (*cap != ' ' && *cap != '\t' && *cap != '\n') goto slow; if (shellflags) if (shellflags[0] != '-' || ((shellflags[1] != 'c' || shellflags[2] != '\0') && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0'))) goto slow; i = strlen (line) + 1; /* More than 1 arg per character is impossible. */ new_argv = xmalloc (i * sizeof (char *)); /* All the args can fit in a buffer as big as LINE is. */ ap = new_argv[0] = argstr = xmalloc (i); #ifndef NDEBUG end = ap + i; #endif /* I is how many complete arguments have been found. */ i = 0; instring = word_has_equals = seen_nonequals = last_argument_was_empty = 0; for (p = line; *p != '\0'; ++p) { assert (ap <= end); if (instring) { /* Inside a string, just copy any char except a closing quote or a backslash-newline combination. */ if (*p == instring) { instring = 0; if (ap == new_argv[0] || *(ap-1) == '\0') last_argument_was_empty = 1; } else if (*p == '\\' && p[1] == '\n') { /* Backslash-newline is handled differently depending on what kind of string we're in: inside single-quoted strings you keep them; in double-quoted strings they disappear. For DOS/Windows/OS2, if we don't have a POSIX shell, we keep the pre-POSIX behavior of removing the backslash-newline. */ if (instring == '"' #if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32) || !unixy_shell #endif ) ++p; else { *(ap++) = *(p++); *(ap++) = *p; } } else if (*p == '\n' && restp != NULL) { /* End of the command line. */ *restp = p; goto end_of_line; } /* Backslash, $, and ` are special inside double quotes. If we see any of those, punt. But on MSDOS, if we use COMMAND.COM, double and single quotes have the same effect. */ else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell) goto slow; #ifdef WINDOWS32 else if (instring == '"' && strncmp (p, "\\\"", 2) == 0) *ap++ = *++p; #endif else *ap++ = *p; } else if (strchr (sh_chars, *p) != 0) /* Not inside a string, but it's a special char. */ goto slow; else if (one_shell && *p == '\n') /* In .ONESHELL mode \n is a separator like ; or && */ goto slow; #ifdef __MSDOS__ else if (*p == '.' && p[1] == '.' && p[2] == '.' && p[3] != '.') /* '...' is a wildcard in DJGPP. */ goto slow; #endif else /* Not a special char. */ switch (*p) { case '=': /* Equals is a special character in leading words before the first word with no equals sign in it. This is not the case with sh -k, but we never get here when using nonstandard shell flags. */ if (! seen_nonequals && unixy_shell) goto slow; word_has_equals = 1; *ap++ = '='; break; case '\\': /* Backslash-newline has special case handling, ref POSIX. We're in the fastpath, so emulate what the shell would do. */ if (p[1] == '\n') { /* Throw out the backslash and newline. */ ++p; /* If there's nothing in this argument yet, skip any whitespace before the start of the next word. */ if (ap == new_argv[i]) p = next_token (p + 1) - 1; } #ifdef WINDOWS32 /* Backslash before whitespace is not special if our shell is not Unixy. */ else if (isspace (p[1]) && !unixy_shell) { *ap++ = *p; break; } #endif else if (p[1] != '\0') { #ifdef HAVE_DOS_PATHS /* Only remove backslashes before characters special to Unixy shells. All other backslashes are copied verbatim, since they are probably DOS-style directory separators. This still leaves a small window for problems, but at least it should work for the vast majority of naive users. */ #ifdef __MSDOS__ /* A dot is only special as part of the "..." wildcard. */ if (strneq (p + 1, ".\\.\\.", 5)) { *ap++ = '.'; *ap++ = '.'; p += 4; } else #endif if (p[1] != '\\' && p[1] != '\'' && !isspace ((unsigned char)p[1]) && strchr (sh_chars_sh, p[1]) == 0) /* back up one notch, to copy the backslash */ --p; #endif /* HAVE_DOS_PATHS */ /* Copy and skip the following char. */ *ap++ = *++p; } break; case '\'': case '"': instring = *p; break; case '\n': if (restp != NULL) { /* End of the command line. */ *restp = p; goto end_of_line; } else /* Newlines are not special. */ *ap++ = '\n'; break; case ' ': case '\t': /* We have the end of an argument. Terminate the text of the argument. */ *ap++ = '\0'; new_argv[++i] = ap; last_argument_was_empty = 0; /* Update SEEN_NONEQUALS, which tells us if every word heretofore has contained an '='. */ seen_nonequals |= ! word_has_equals; if (word_has_equals && ! seen_nonequals) /* An '=' in a word before the first word without one is magical. */ goto slow; word_has_equals = 0; /* Prepare for the next word. */ /* If this argument is the command name, see if it is a built-in shell command. If so, have the shell handle it. */ if (i == 1) { register int j; for (j = 0; sh_cmds[j] != 0; ++j) { if (streq (sh_cmds[j], new_argv[0])) goto slow; #if defined(__EMX__) || defined(WINDOWS32) /* Non-Unix shells are case insensitive. */ if (!unixy_shell && strcasecmp (sh_cmds[j], new_argv[0]) == 0) goto slow; #endif } } /* Ignore multiple whitespace chars. */ p = next_token (p) - 1; break; default: *ap++ = *p; break; } } end_of_line: if (instring) /* Let the shell deal with an unterminated quote. */ goto slow; /* Terminate the last argument and the argument list. */ *ap = '\0'; if (new_argv[i][0] != '\0' || last_argument_was_empty) ++i; new_argv[i] = 0; if (i == 1) { register int j; for (j = 0; sh_cmds[j] != 0; ++j) if (streq (sh_cmds[j], new_argv[0])) goto slow; } if (new_argv[0] == 0) { /* Line was empty. */ free (argstr); free (new_argv); return 0; } return new_argv; slow:; /* We must use the shell. */ if (new_argv != 0) { /* Free the old argument list we were working on. */ free (argstr); free (new_argv); } #ifdef __MSDOS__ execute_by_shell = 1; /* actually, call 'system' if shell isn't unixy */ #endif #ifdef _AMIGA { char *ptr; char *buffer; char *dptr; buffer = xmalloc (strlen (line)+1); ptr = line; for (dptr=buffer; *ptr; ) { if (*ptr == '\\' && ptr[1] == '\n') ptr += 2; else if (*ptr == '@') /* Kludge: multiline commands */ { ptr += 2; *dptr++ = '\n'; } else *dptr++ = *ptr++; } *dptr = 0; new_argv = xmalloc (2 * sizeof (char *)); new_argv[0] = buffer; new_argv[1] = 0; } #else /* Not Amiga */ #ifdef WINDOWS32 /* * Not eating this whitespace caused things like * * sh -c "\n" * * which gave the shell fits. I think we have to eat * whitespace here, but this code should be considered * suspicious if things start failing.... */ /* Make sure not to bother processing an empty line. */ while (isspace ((unsigned char)*line)) ++line; if (*line == '\0') return 0; #endif /* WINDOWS32 */ { /* SHELL may be a multi-word command. Construct a command line "$(SHELL) $(.SHELLFLAGS) LINE", with all special chars in LINE escaped. Then recurse, expanding this command line to get the final argument list. */ char *new_line; unsigned int shell_len = strlen (shell); unsigned int line_len = strlen (line); unsigned int sflags_len = shellflags ? strlen (shellflags) : 0; #ifdef WINDOWS32 char *command_ptr = NULL; /* used for batch_mode_shell mode */ #endif char *args_ptr; # ifdef __EMX__ /* is this necessary? */ if (!unixy_shell && shellflags) shellflags[0] = '/'; /* "/c" */ # endif /* In .ONESHELL mode we are allowed to throw the entire current recipe string at a single shell and trust that the user has configured the shell and shell flags, and formatted the string, appropriately. */ if (one_shell) { /* If the shell is Bourne compatible, we must remove and ignore interior special chars [@+-] because they're meaningless to the shell itself. If, however, we're in .ONESHELL mode and have changed SHELL to something non-standard, we should leave those alone because they could be part of the script. In this case we must also leave in place any leading [@+-] for the same reason. */ /* Remove and ignore interior prefix chars [@+-] because they're meaningless given a single shell. */ #if defined __MSDOS__ || defined (__EMX__) if (unixy_shell) /* the test is complicated and we already did it */ #else if (is_bourne_compatible_shell (shell) #ifdef WINDOWS32 /* If we didn't find any sh.exe, don't behave is if we did! */ && !no_default_sh_exe #endif ) #endif { const char *f = line; char *t = line; /* Copy the recipe, removing and ignoring interior prefix chars [@+-]: they're meaningless in .ONESHELL mode. */ while (f[0] != '\0') { int esc = 0; /* This is the start of a new recipe line. Skip whitespace and prefix characters. */ while (isblank (*f) || *f == '-' || *f == '@' || *f == '+') ++f; /* Copy until we get to the next logical recipe line. */ while (*f != '\0') { *(t++) = *(f++); if (f[-1] == '\\') esc = !esc; else { /* On unescaped newline, we're done with this line. */ if (f[-1] == '\n' && ! esc) break; /* Something else: reset the escape sequence. */ esc = 0; } } } *t = '\0'; } #ifdef WINDOWS32 else /* non-Posix shell (cmd.exe etc.) */ { const char *f = line; char *t = line; char *tstart = t; int temp_fd; FILE* batch = NULL; int id = GetCurrentProcessId (); PATH_VAR(fbuf); /* Generate a file name for the temporary batch file. */ sprintf (fbuf, "make%d", id); *batch_filename = create_batch_file (fbuf, 0, &temp_fd); DB (DB_JOBS, (_("Creating temporary batch file %s\n"), *batch_filename)); /* Create a FILE object for the batch file, and write to it the commands to be executed. Put the batch file in TEXT mode. */ _setmode (temp_fd, _O_TEXT); batch = _fdopen (temp_fd, "wt"); fputs ("@echo off\n", batch); DB (DB_JOBS, (_("Batch file contents:\n\t@echo off\n"))); /* Copy the recipe, removing and ignoring interior prefix chars [@+-]: they're meaningless in .ONESHELL mode. */ while (*f != '\0') { /* This is the start of a new recipe line. Skip whitespace and prefix characters. */ while (isblank (*f) || *f == '-' || *f == '@' || *f == '+') ++f; /* Copy until we get to the next logical recipe line. */ while (*f != '\0') { /* Remove the escaped newlines in the command, and the whitespace that follows them. Windows shells cannot handle escaped newlines. */ if (*f == '\\' && f[1] == '\n') { f += 2; while (isblank (*f)) ++f; } *(t++) = *(f++); /* On an unescaped newline, we're done with this line. */ if (f[-1] == '\n') break; } /* Write another line into the batch file. */ if (t > tstart) { int c = *t; *t = '\0'; fputs (tstart, batch); DB (DB_JOBS, ("\t%s", tstart)); tstart = t; *t = c; } } DB (DB_JOBS, ("\n")); fclose (batch); /* Create an argv list for the shell command line that will run the batch file. */ new_argv = xmalloc (2 * sizeof (char *)); new_argv[0] = xstrdup (*batch_filename); new_argv[1] = NULL; return new_argv; } #endif /* WINDOWS32 */ /* Create an argv list for the shell command line. */ { int n = 0; new_argv = xmalloc ((4 + sflags_len/2) * sizeof (char *)); new_argv[n++] = xstrdup (shell); /* Chop up the shellflags (if any) and assign them. */ if (! shellflags) new_argv[n++] = xstrdup (""); else { const char *s = shellflags; char *t; unsigned int len; while ((t = find_next_token (&s, &len)) != 0) new_argv[n++] = xstrndup (t, len); } /* Set the command to invoke. */ new_argv[n++] = line; new_argv[n++] = NULL; } return new_argv; } new_line = xmalloc ((shell_len*2) + 1 + sflags_len + 1 + (line_len*2) + 1 + EVAL_LEN); ap = new_line; /* Copy SHELL, escaping any characters special to the shell. If we don't escape them, construct_command_argv_internal will recursively call itself ad nauseam, or until stack overflow, whichever happens first. */ for (cp = shell; *cp != '\0'; ++cp) { if (strchr (sh_chars, *cp) != 0) *(ap++) = '\\'; *(ap++) = *cp; } *(ap++) = ' '; if (shellflags) memcpy (ap, shellflags, sflags_len); ap += sflags_len; *(ap++) = ' '; #ifdef WINDOWS32 command_ptr = ap; #endif #if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) if (unixy_shell && line_len > MAX_ARG_STRLEN) { unsigned j; memcpy (ap, eval_line, sizeof (eval_line) - 1); ap += sizeof (eval_line) - 1; for (j = 1; j <= 2 * line_len / (MAX_ARG_STRLEN - 2); j++) ap += sprintf (ap, "\\$\\{%u\\}", j); *ap++ = '\\'; *ap++ = '"'; *ap++ = ' '; /* Copy only the first word of SHELL to $0. */ for (p = shell; *p != '\0'; ++p) { if (isspace ((unsigned char)*p)) break; *ap++ = *p; } *ap++ = ' '; } #endif args_ptr = ap; for (p = line; *p != '\0'; ++p) { if (restp != NULL && *p == '\n') { *restp = p; break; } else if (*p == '\\' && p[1] == '\n') { /* POSIX says we keep the backslash-newline. If we don't have a POSIX shell on DOS/Windows/OS2, mimic the pre-POSIX behavior and remove the backslash/newline. */ #if defined (__MSDOS__) || defined (__EMX__) || defined (WINDOWS32) # define PRESERVE_BSNL unixy_shell #else # define PRESERVE_BSNL 1 #endif if (PRESERVE_BSNL) { *(ap++) = '\\'; /* Only non-batch execution needs another backslash, because it will be passed through a recursive invocation of this function. */ if (!batch_mode_shell) *(ap++) = '\\'; *(ap++) = '\n'; } ++p; continue; } /* DOS shells don't know about backslash-escaping. */ if (unixy_shell && !batch_mode_shell && (*p == '\\' || *p == '\'' || *p == '"' || isspace ((unsigned char)*p) || strchr (sh_chars, *p) != 0)) *ap++ = '\\'; #ifdef __MSDOS__ else if (unixy_shell && strneq (p, "...", 3)) { /* The case of '...' wildcard again. */ strcpy (ap, "\\.\\.\\"); ap += 5; p += 2; } #endif *ap++ = *p; #if !defined (WINDOWS32) && defined (MAX_ARG_STRLEN) if (unixy_shell && line_len > MAX_ARG_STRLEN && (ap - args_ptr > (long) MAX_ARG_STRLEN - 2)) { *ap++ = ' '; args_ptr = ap; } #endif } if (ap == new_line + shell_len + sflags_len + 2) { /* Line was empty. */ free (new_line); return 0; } *ap = '\0'; #ifdef WINDOWS32 /* Some shells do not work well when invoked as 'sh -c xxx' to run a command line (e.g. Cygnus GNUWIN32 sh.exe on WIN32 systems). In these cases, run commands via a script file. */ if (just_print_flag && !(flags & COMMANDS_RECURSE)) { /* Need to allocate new_argv, although it's unused, because start_job_command will want to free it and its 0'th element. */ new_argv = xmalloc (2 * sizeof (char *)); new_argv[0] = xstrdup (""); new_argv[1] = NULL; } else if ((no_default_sh_exe || batch_mode_shell) && batch_filename) { int temp_fd; FILE* batch = NULL; int id = GetCurrentProcessId (); PATH_VAR (fbuf); /* create a file name */ sprintf (fbuf, "make%d", id); *batch_filename = create_batch_file (fbuf, unixy_shell, &temp_fd); DB (DB_JOBS, (_("Creating temporary batch file %s\n"), *batch_filename)); /* Create a FILE object for the batch file, and write to it the commands to be executed. Put the batch file in TEXT mode. */ _setmode (temp_fd, _O_TEXT); batch = _fdopen (temp_fd, "wt"); if (!unixy_shell) fputs ("@echo off\n", batch); fputs (command_ptr, batch); fputc ('\n', batch); fclose (batch); DB (DB_JOBS, (_("Batch file contents:%s\n\t%s\n"), !unixy_shell ? "\n\t@echo off" : "", command_ptr)); /* create argv */ new_argv = xmalloc (3 * sizeof (char *)); if (unixy_shell) { new_argv[0] = xstrdup (shell); new_argv[1] = *batch_filename; /* only argv[0] gets freed later */ } else { new_argv[0] = xstrdup (*batch_filename); new_argv[1] = NULL; } new_argv[2] = NULL; } else #endif /* WINDOWS32 */ if (unixy_shell) new_argv = construct_command_argv_internal (new_line, 0, 0, 0, 0, flags, 0); #ifdef __EMX__ else if (!unixy_shell) { /* new_line is local, must not be freed therefore We use line here instead of new_line because we run the shell manually. */ size_t line_len = strlen (line); char *p = new_line; char *q = new_line; memcpy (new_line, line, line_len + 1); /* Replace all backslash-newline combination and also following tabs. Important: stop at the first '\n' because that's what the loop above did. The next line starting at restp[0] will be executed during the next call of this function. */ while (*q != '\0' && *q != '\n') { if (q[0] == '\\' && q[1] == '\n') q += 2; /* remove '\\' and '\n' */ else *p++ = *q++; } *p = '\0'; # ifndef NO_CMD_DEFAULT if (strnicmp (new_line, "echo", 4) == 0 && (new_line[4] == ' ' || new_line[4] == '\t')) { /* the builtin echo command: handle it separately */ size_t echo_len = line_len - 5; char *echo_line = new_line + 5; /* special case: echo 'x="y"' cmd works this way: a string is printed as is, i.e., no quotes are removed. But autoconf uses a command like echo 'x="y"' to determine whether make works. autoconf expects the output x="y" so we will do exactly that. Note: if we do not allow cmd to be the default shell we do not need this kind of voodoo */ if (echo_line[0] == '\'' && echo_line[echo_len - 1] == '\'' && strncmp (echo_line + 1, "ac_maketemp=", strlen ("ac_maketemp=")) == 0) { /* remove the enclosing quotes */ memmove (echo_line, echo_line + 1, echo_len - 2); echo_line[echo_len - 2] = '\0'; } } # endif { /* Let the shell decide what to do. Put the command line into the 2nd command line argument and hope for the best ;-) */ size_t sh_len = strlen (shell); /* exactly 3 arguments + NULL */ new_argv = xmalloc (4 * sizeof (char *)); /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times the trailing '\0' */ new_argv[0] = xmalloc (sh_len + line_len + 5); memcpy (new_argv[0], shell, sh_len + 1); new_argv[1] = new_argv[0] + sh_len + 1; memcpy (new_argv[1], "/c", 3); new_argv[2] = new_argv[1] + 3; memcpy (new_argv[2], new_line, line_len + 1); new_argv[3] = NULL; } } #elif defined(__MSDOS__) else { /* With MSDOS shells, we must construct the command line here instead of recursively calling ourselves, because we cannot backslash-escape the special characters (see above). */ new_argv = xmalloc (sizeof (char *)); line_len = strlen (new_line) - shell_len - sflags_len - 2; new_argv[0] = xmalloc (line_len + 1); strncpy (new_argv[0], new_line + shell_len + sflags_len + 2, line_len); new_argv[0][line_len] = '\0'; } #else else fatal (NILF, CSTRLEN (__FILE__) + INTSTR_LENGTH, _("%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\n"), __FILE__, __LINE__); #endif free (new_line); } #endif /* ! AMIGA */ return new_argv; } #endif /* !VMS */ /* Figure out the argument list necessary to run LINE as a command. Try to avoid using a shell. This routine handles only ' quoting, and " quoting when no backslash, $ or ' characters are seen in the quotes. Starting quotes may be escaped with a backslash. If any of the characters in sh_chars is seen, or any of the builtin commands listed in sh_cmds is the first word of a line, the shell is used. If RESTP is not NULL, *RESTP is set to point to the first newline in LINE. If *RESTP is NULL, newlines will be ignored. FILE is the target whose commands these are. It is used for variable expansion for $(SHELL) and $(IFS). */ char ** construct_command_argv (char *line, char **restp, struct file *file, int cmd_flags, char **batch_filename) { char *shell, *ifs, *shellflags; char **argv; #ifdef VMS char *cptr; int argc; argc = 0; cptr = line; for (;;) { while ((*cptr != 0) && (isspace ((unsigned char)*cptr))) cptr++; if (*cptr == 0) break; while ((*cptr != 0) && (!isspace ((unsigned char)*cptr))) cptr++; argc++; } argv = xmalloc (argc * sizeof (char *)); if (argv == 0) abort (); cptr = line; argc = 0; for (;;) { while ((*cptr != 0) && (isspace ((unsigned char)*cptr))) cptr++; if (*cptr == 0) break; DB (DB_JOBS, ("argv[%d] = [%s]\n", argc, cptr)); argv[argc++] = cptr; while ((*cptr != 0) && (!isspace ((unsigned char)*cptr))) cptr++; if (*cptr != 0) *cptr++ = 0; } #else { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; shell = allocated_variable_expand_for_file ("$(SHELL)", file); #ifdef WINDOWS32 /* * Convert to forward slashes so that construct_command_argv_internal() * is not confused. */ if (shell) { char *p = w32ify (shell, 0); strcpy (shell, p); } #endif #ifdef __EMX__ { static const char *unixroot = NULL; static const char *last_shell = ""; static int init = 0; if (init == 0) { unixroot = getenv ("UNIXROOT"); /* unixroot must be NULL or not empty */ if (unixroot && unixroot[0] == '\0') unixroot = NULL; init = 1; } /* if we have an unixroot drive and if shell is not default_shell (which means it's either cmd.exe or the test has already been performed) and if shell is an absolute path without drive letter, try whether it exists e.g.: if "/bin/sh" does not exist use "$UNIXROOT/bin/sh" instead. */ if (unixroot && shell && strcmp (shell, last_shell) != 0 && (shell[0] == '/' || shell[0] == '\\')) { /* trying a new shell, check whether it exists */ size_t size = strlen (shell); char *buf = xmalloc (size + 7); memcpy (buf, shell, size); memcpy (buf + size, ".exe", 5); /* including the trailing '\0' */ if (access (shell, F_OK) != 0 && access (buf, F_OK) != 0) { /* try the same for the unixroot drive */ memmove (buf + 2, buf, size + 5); buf[0] = unixroot[0]; buf[1] = unixroot[1]; if (access (buf, F_OK) == 0) /* we have found a shell! */ /* free(shell); */ shell = buf; else free (buf); } else free (buf); } } #endif /* __EMX__ */ shellflags = allocated_variable_expand_for_file ("$(.SHELLFLAGS)", file); ifs = allocated_variable_expand_for_file ("$(IFS)", file); warn_undefined_variables_flag = save; } argv = construct_command_argv_internal (line, restp, shell, shellflags, ifs, cmd_flags, batch_filename); free (shell); free (shellflags); free (ifs); #endif /* !VMS */ return argv; } #if !defined(HAVE_DUP2) && !defined(_AMIGA) int dup2 (int old, int new) { int fd; (void) close (new); fd = dup (old); if (fd != new) { (void) close (fd); errno = EMFILE; return -1; } return fd; } #endif /* !HAVE_DUP2 && !_AMIGA */ /* On VMS systems, include special VMS functions. */ #ifdef VMS #include "vmsjobs.c" #endif remake-4.1+dbg1.3~dfsg.1/job.h000066400000000000000000000122251317072305000157200ustar00rootroot00000000000000/* Definitions for managing subprocesses in GNU Make. Copyright (C) 1992-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _REMAKE_JOB_H_ #define _REMAKE_JOB_H_ #include "output.h" #include "trace.h" #ifdef HAVE_FCNTL_H # include #else # include #endif /* How to set close-on-exec for a file descriptor. */ #if !defined F_SETFD # ifdef WINDOWS32 # define CLOSE_ON_EXEC(_d) process_noinherit(_d) # else # define CLOSE_ON_EXEC(_d) # endif #else # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif # define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC) #endif #ifdef NO_OUTPUT_SYNC # define RECORD_SYNC_MUTEX(m) \ O (error, NILF, \ _("-O[TYPE] (--output-sync[=TYPE]) is not configured for this build.")); #else # ifdef WINDOWS32 /* For emulations in w32/compat/posixfcn.c. */ # define F_GETFD 1 # define F_SETLKW 2 /* Implementation note: None of the values of l_type below can be zero -- they are compared with a static instance of the struct, so zero means unknown/invalid, see w32/compat/posixfcn.c. */ # define F_WRLCK 1 # define F_UNLCK 2 struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; }; /* This type is actually a HANDLE, but we want to avoid including windows.h as much as possible. */ typedef intptr_t sync_handle_t; /* Public functions emulated/provided in posixfcn.c. */ int fcntl (intptr_t fd, int cmd, ...); intptr_t create_mutex (void); int same_stream (FILE *f1, FILE *f2); # define RECORD_SYNC_MUTEX(m) record_sync_mutex(m) void record_sync_mutex (const char *str); void prepare_mutex_handle_string (intptr_t hdl); # else /* !WINDOWS32 */ typedef int sync_handle_t; /* file descriptor */ # define RECORD_SYNC_MUTEX(m) (void)(m) # endif #endif /* !NO_OUTPUT_SYNC */ /* Structure describing a running or dead child process. */ struct child { struct child *next; /* Link in the chain. */ struct file *file; /* File being remade. */ char **environment; /* Environment for commands. */ char *sh_batch_file; /* Script file for shell commands */ char **command_lines; /* Array of variable-expanded cmd lines. */ char *command_ptr; /* Ptr into command_lines[command_line]. */ #ifdef VMS char *comname; /* Temporary command file name */ int efn; /* Completion event flag number */ int cstatus; /* Completion status */ #endif unsigned int command_line; /* Index into command_lines. */ struct output output; /* Output for this child. */ pid_t pid; /* Child process's ID number. */ unsigned int remote:1; /* Nonzero if executing remotely. */ unsigned int noerror:1; /* Nonzero if commands contained a '-'. */ unsigned int good_stdin:1; /* Nonzero if this child has a good stdin. */ unsigned int deleted:1; /* Nonzero if targets have been deleted. */ unsigned int dontcare:1; /* Saved dontcare flag. */ }; extern struct child *children; int is_bourne_compatible_shell(const char *path); extern void new_job (file_t *file, target_stack_node_t *p_call_stack); extern void reap_children (int block, int err, target_stack_node_t *p_call_stack); extern void start_waiting_jobs (target_stack_node_t *p_call_stack); char **construct_command_argv (char *line, char **restp, struct file *file, int cmd_flags, char** batch_file); #ifdef VMS int child_execute_job (char *argv, struct child *child); #else # define FD_STDIN (fileno (stdin)) # define FD_STDOUT (fileno (stdout)) # define FD_STDERR (fileno (stderr)) # if defined(__EMX__) int child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd, char **argv, char **envp); # else void child_execute_job (int stdin_fd, int stdout_fd, int stderr_fd, char **argv, char **envp) __attribute__ ((noreturn)); # endif #endif #ifdef _AMIGA void exec_command (char **argv) __attribute__ ((noreturn)); #elif defined(__EMX__) int exec_command (char **argv, char **envp); #else void exec_command (char **argv, char **envp) __attribute__ ((noreturn)); #endif extern unsigned int job_slots_used; void block_sigs (void); #ifdef POSIX void unblock_sigs (void); #else #ifdef HAVE_SIGSETMASK extern int fatal_signal_mask; #define unblock_sigs() sigsetmask (0) #else #define unblock_sigs() #endif #endif extern unsigned int jobserver_tokens; #endif /* _REMAKE_JOB_H_ */ remake-4.1+dbg1.3~dfsg.1/load.c000066400000000000000000000147511317072305000160660ustar00rootroot00000000000000/* Loading dynamic objects for GNU Make. Copyright (C) 2012-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #if MAKE_LOAD #include #include #include #include #include #define SYMBOL_EXTENSION "_gmk_setup" #include "debug.h" #include "filedef.h" #include "variable.h" /* Tru64 V4.0 does not have this flag */ #ifndef RTLD_GLOBAL # define RTLD_GLOBAL 0 #endif struct load_list { struct load_list *next; const char *name; void *dlp; }; static struct load_list *loaded_syms = NULL; static load_func_t load_object (const gmk_floc *flocp, int noerror, const char *ldname, const char *symname) { static void *global_dl = NULL; load_func_t symp; if (! global_dl) { global_dl = dlopen (NULL, RTLD_NOW|RTLD_GLOBAL); if (! global_dl) { const char *err = dlerror (); OS (fatal, flocp, _("Failed to open global symbol table: %s"), err); } } symp = (load_func_t) dlsym (global_dl, symname); if (! symp) { struct load_list *new; void *dlp = NULL; /* If the path has no "/", try the current directory first. */ if (! strchr (ldname, '/') #ifdef HAVE_DOS_PATHS && ! strchr (ldname, '\\') #endif ) dlp = dlopen (concat (2, "./", ldname), RTLD_LAZY|RTLD_GLOBAL); /* If we haven't opened it yet, try the default search path. */ if (! dlp) dlp = dlopen (ldname, RTLD_LAZY|RTLD_GLOBAL); /* Still no? Then fail. */ if (! dlp) { const char *err = dlerror (); if (noerror) DB (DB_BASIC, ("%s", err)); else OS (error, flocp, "%s", err); return NULL; } /* Assert that the GPL license symbol is defined. */ symp = (load_func_t) dlsym (dlp, "plugin_is_GPL_compatible"); if (! symp) OS (fatal, flocp, _("Loaded object %s is not declared to be GPL compatible"), ldname); symp = (load_func_t) dlsym (dlp, symname); if (! symp) { const char *err = dlerror (); OSSS (fatal, flocp, _("Failed to load symbol %s from %s: %s"), symname, ldname, err); } /* Add this symbol to a trivial lookup table. This is not efficient but it's highly unlikely we'll be loading lots of objects, and we only need it to look them up on unload, if we rebuild them. */ new = xmalloc (sizeof (struct load_list)); new->name = xstrdup (ldname); new->dlp = dlp; new->next = loaded_syms; loaded_syms = new; } return symp; } int load_file (const gmk_floc *flocp, const char **ldname, int noerror) { int nmlen = strlen (*ldname); char *new = alloca (nmlen + CSTRLEN (SYMBOL_EXTENSION) + 1); char *symname = NULL; char *loaded; const char *fp; int r; load_func_t symp; /* Break the input into an object file name and a symbol name. If no symbol name was provided, compute one from the object file name. */ fp = strchr (*ldname, '('); if (fp) { const char *ep; /* There's an open paren, so see if there's a close paren: if so use that as the symbol name. We can't have whitespace: it would have been chopped up before this function is called. */ ep = strchr (fp+1, ')'); if (ep && ep[1] == '\0') { int l = fp - *ldname;; ++fp; if (fp == ep) OS (fatal, flocp, _("Empty symbol name for load: %s"), *ldname); /* Make a copy of the ldname part. */ memcpy (new, *ldname, l); new[l] = '\0'; *ldname = new; nmlen = l; /* Make a copy of the symbol name part. */ symname = new + l + 1; memcpy (symname, fp, ep - fp); symname[ep - fp] = '\0'; } } /* Add this name to the string cache so it can be reused later. */ *ldname = strcache_add (*ldname); /* If this object has been loaded, we're done. */ loaded = allocated_variable_expand ("$(.LOADED)"); fp = strstr (loaded, *ldname); r = fp && (fp==loaded || fp[-1]==' ') && (fp[nmlen]=='\0' || fp[nmlen]==' '); free (loaded); if (r) return 1; /* If we didn't find a symbol name yet, construct it from the ldname. */ if (! symname) { char *p = new; fp = strrchr (*ldname, '/'); #ifdef HAVE_DOS_PATHS if (fp) { const char *fp2 = strchr (fp, '\\'); if (fp2 > fp) fp = fp2; } else fp = strrchr (*ldname, '\\'); /* The (improbable) case of d:foo. */ if (fp && *fp && fp[1] == ':') fp++; #endif if (!fp) fp = *ldname; else ++fp; while (isalnum (*fp) || *fp == '_') *(p++) = *(fp++); strcpy (p, SYMBOL_EXTENSION); symname = new; } DB (DB_VERBOSE, (_("Loading symbol %s from %s\n"), symname, *ldname)); /* Load it! */ symp = load_object (flocp, noerror, *ldname, symname); if (! symp) return 0; /* Invoke the symbol. */ r = (*symp) (flocp); /* If it succeeded, add the load file to the loaded variable. */ if (r > 0) do_variable_definition (flocp, ".LOADED", *ldname, o_default, f_append, 0); return r; } void unload_file (const char *name) { struct load_list *d; for (d = loaded_syms; d != NULL; d = d->next) if (streq (d->name, name) && d->dlp) { if (dlclose (d->dlp)) perror_with_name ("dlclose", d->name); d->dlp = NULL; break; } } #else int load_file (const gmk_floc *flocp, const char **ldname, int noerror) { if (! noerror) O (fatal, flocp, _("The 'load' operation is not supported on this platform.")); return 0; } void unload_file (const char *name) { O (fatal, NILF, "INTERNAL: Cannot unload when load is not supported!"); } #endif /* MAKE_LOAD */ remake-4.1+dbg1.3~dfsg.1/loadapi.c000066400000000000000000000035361317072305000165570ustar00rootroot00000000000000/* API for GNU Make dynamic objects. Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "variable.h" #include "dep.h" /* Allocate a buffer in our context, so we can free it. */ char * gmk_alloc (unsigned int len) { return xmalloc (len); } /* Free a buffer returned by gmk_expand(). */ void gmk_free (char *s) { free (s); } /* Evaluate a buffer as make syntax. Ideally eval_buffer() will take const char *, but not yet. */ void gmk_eval (const char *buffer, const gmk_floc *floc) { /* Preserve existing variable buffer context. */ char *pbuf; unsigned int plen; char *s; install_variable_buffer (&pbuf, &plen); s = xstrdup (buffer); eval_buffer (s, floc); free (s); restore_variable_buffer (pbuf, plen); } /* Expand a string and return an allocated buffer. Caller must call gmk_free() with this buffer. */ char * gmk_expand (const char *ref) { return allocated_variable_expand (ref); } /* Register a function to be called from makefiles. */ void gmk_add_function (const char *name, gmk_func_ptr func, unsigned int min, unsigned int max, unsigned int flags) { define_new_function (reading_file, name, min, max, flags, func); } remake-4.1+dbg1.3~dfsg.1/main.c000066400000000000000000003310071317072305000160670ustar00rootroot00000000000000/* Argument parsing and main program of GNU Make. Copyright (C) 2015 Rocky Bernstein Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "globals.h" #include "profile.h" #include "filedef.h" #include "dep.h" #include "variable.h" #include "job.h" #include "commands.h" #include "rule.h" #include "debug.h" #include "getopt.h" #include #ifdef _AMIGA # include # include #endif #ifdef WINDOWS32 # include # include # include "pathstuff.h" # include "sub_proc.h" # include "w32err.h" #endif #ifdef __EMX__ # include # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef _AMIGA int __stack = 20000; /* Make sure we have 20K of stack space */ #endif extern void initialize_stopchar_map (); void init_dir (void); void remote_setup (void); void remote_cleanup (void); RETSIGTYPE fatal_error_signal (int sig); void print_variable_data_base (void); void print_dir_data_base (void); void print_rule_data_base (bool b_verbose); void print_vpath_data_base (void); void verify_file_data_base (void); #if defined HAVE_WAITPID || defined HAVE_WAIT3 # define HAVE_WAIT_NOHANG #endif #ifndef HAVE_UNISTD_H int chdir (); #endif #ifndef STDC_HEADERS # ifndef sun /* Sun has an incorrect decl in a header. */ void exit (int) __attribute__ ((noreturn)); # endif double atof (); #endif static void clean_jobserver (int status); static void print_data_base (void); static void print_version (void); static void decode_switches (int argc, const char **argv, int env); static void decode_env_switches (const char *envar, unsigned int len); static struct variable *define_makeflags (int all, int makefile); static char *quote_for_env (char *out, const char *in); static void initialize_global_hash_tables (void); /* The structure that describes an accepted command switch. */ struct command_switch { int c; /* The switch character. */ enum /* Type of the value. */ { flag, /* Turn int flag on. */ flag_off, /* Turn int flag off. */ string, /* One string per invocation. */ strlist, /* One string per switch. */ filename, /* A string containing a file name. */ positive_int, /* A positive integer. */ floating, /* A floating-point number (double). */ ignore /* Ignored. */ } type; void *value_ptr; /* Pointer to the value-holding variable. */ unsigned int env:1; /* Can come from MAKEFLAGS. */ unsigned int toenv:1; /* Should be put in MAKEFLAGS. */ unsigned int no_makefile:1; /* Don't propagate when remaking makefiles. */ const void *noarg_value; /* Pointer to value used if no arg given. */ const void *default_value; /* Pointer to default value. */ const char *long_name; /* Long option name. */ }; /* True if C is a switch value that corresponds to a short option. */ #define short_option(c) ((c) <= CHAR_MAX) /* The structure used to hold the list of strings given in command switches of a type that takes strlist arguments. */ /* The recognized command switches. */ /* Synchronize output (--output-sync). */ char *output_sync_option = 0; /*! If non-null, contains the type of tracing we are to do. This is coordinated with tracing_flag. */ stringlist_t *tracing_opts = NULL; /*! If true, show version information on entry. */ bool b_show_version = false; /*! If true, go into debugger on error. Sets --debugger --debugger-stop=error. */ bool b_post_mortem_flag = false; /*! Nonzero means use GNU readline in the debugger. */ int use_readline_flag = #ifdef HAVE_READLINE_READLINE_H 1 #else 0 #endif ; /*! If nonzero, the basename of filenames is in giving locations. Normally, giving a file directory location helps a debugger frontend when we change directories. For regression tests it is helpful to list just the basename part as that doesn't change from installation to installation. Users may have their preferences too. */ int basename_filenames = 0; /* Output level (--verbosity). */ static struct stringlist *verbosity_opts; #ifdef WINDOWS32 /* Suspend make in main for a short time to allow debugger to attach */ int suspend_flag = 0; #endif /* Environment variables override makefile definitions. */ /* Nonzero means keep going even if remaking some file fails (-k). */ int keep_going_flag; int default_keep_going_flag = 0; /*! Nonzero gives a list of explicit target names that have commands AND comments associated with them and exits. Set by option --task-comments */ int show_task_comments_flag = 0; /* Nonzero means ignore print_directory_flag and never print the directory. This is necessary because print_directory_flag is set implicitly. */ int inhibit_print_directory_flag = 0; /* List of makefiles given with -f switches. */ static struct stringlist *makefiles = 0; /* Size of the stack when we started. */ #ifdef SET_STACK_SIZE struct rlimit stack_limit; #endif /* Number of job slots (commands that can be run at once). */ unsigned int job_slots = 1; unsigned int default_job_slots = 1; static unsigned int master_job_slots = 0; /* Value of job_slots that means no limit. */ static unsigned int inf_jobs = 0; /* File descriptors for the jobs pipe. */ char *jobserver_fds = 0; int job_fds[2] = { -1, -1 }; int job_rfd = -1; /* Handle for the mutex used on Windows to synchronize output of our children under -O. */ char *sync_mutex = 0; /* Maximum load average at which multiple jobs will be run. Negative values mean unlimited, while zero means limit to zero load (which could be useful to start infinite jobs remotely but one at a time locally). */ #ifndef NO_FLOAT double max_load_average = -1.0; double default_load_average = -1.0; #else int max_load_average = -1; int default_load_average = -1; #endif /* List of directories given with -C switches. */ static struct stringlist *directories = 0; /* List of include directories given with -I switches. */ static struct stringlist *include_directories = 0; /* List of files given with -o switches. */ static struct stringlist *old_files = 0; /* List of files given with -W switches. */ static struct stringlist *new_files = 0; /* List of strings to be eval'd. */ static struct stringlist *eval_strings = 0; /* If nonzero, we should just print usage and exit. */ static int print_usage_flag = 0; /*! Do we want to go into a debugger or not? Values are "error" - enter on errors or fatal errors "fatal" - enter on fatal errors "goal" - set to enter debugger before updating goal "preread" - set to enter debugger before reading makefile(s) "preaction" - set to enter debugger before performing any actions(s) "full" - "enter" + "error" + "fatal" */ static stringlist_t* debugger_opts = NULL; /* If nonzero, always build all targets, regardless of whether they appear out of date or not. */ static int always_make_set = 0; int always_make_flag = 0; /* If nonzero, we're in the "try to rebuild makefiles" phase. */ int rebuilding_makefiles = 0; /* The usage output. We write it this way to make life easier for the translators, especially those trying to translate to right-to-left languages like Hebrew. */ static const char *const usage[] = { N_("Options:\n"), N_("\ -b, -m Ignored for compatibility.\n"), N_("\ -B, --always-make Unconditionally make all targets.\n"), N_("\ -C DIRECTORY, --directory=DIRECTORY\n\ Change to DIRECTORY before doing anything.\n"), N_("\ -d Print lots of debugging information.\n"), N_("\ --debug[=FLAGS] Print various types of debugging information.\n"), N_("\ -e, --environment-overrides\n\ Environment variables override makefiles.\n"), N_("\ --eval=STRING Evaluate STRING as a makefile statement.\n"), N_("\ -f FILE, --file=FILE, --makefile=FILE\n\ Read FILE as a makefile.\n"), N_("\ -h, --help Print this message and exit.\n"), N_("\ -i, --ignore-errors Ignore errors from recipes.\n"), N_("\ -I DIRECTORY, --include-dir=DIRECTORY\n\ Search DIRECTORY for included makefiles.\n"), N_("\ -j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.\n"), N_("\ -k, --keep-going Keep going when some targets can't be made.\n"), N_("\ -l [N], --load-average[=N], --max-load[=N]\n\ Don't start multiple jobs unless load is below N.\n"), N_("\ -L, --check-symlink-times Use the latest mtime between symlinks and target.\n"), N_("\ --no-extended-errors Do not give additional error reporting.\n"), N_("\ -n, --just-print, --dry-run, --recon\n\ Don't actually run any recipe; just print them.\n"), N_("\ -o FILE, --old-file=FILE, --assume-old=FILE\n\ Consider FILE to be very old and don't remake it.\n"), N_("\ -O[TYPE], --output-sync[=TYPE]\n\ Synchronize output of parallel jobs by TYPE.\n"), N_("\ -p, --print-data-base Print make's internal database.\n"), N_("\ -P, --profile Print profiling information for each target.\n"), N_("\ -q, --question Run no recipe; exit status says if up to date.\n"), N_("\ -r, --no-builtin-rules Disable the built-in implicit rules.\n"), N_("\ -R, --no-builtin-variables Disable the built-in variable settings.\n"), N_("\ -s, --silent, --quiet Don't echo recipes.\n"), N_("\ -S, --no-keep-going, --stop\n\ Turns off -k.\n"), N_("\ --targets Give list of explicitly-named targets.\n"), N_("\ --tasks Give list of explicitly-named targets which\n\ have commands associated with them.\n"), N_("\ -t, --touch Touch targets instead of remaking them.\n"), N_("\ --trace Print tracing information.\n"), N_("\ -v, --version Print the version number of make and exit.\n"), N_("\ --verbosity[=LEVEL] Set verbosity level. LEVEL may be \"terse\" \"no-header\" or\n\ \"full\". The default is \"full\".\n"), N_("\ -w, --print-directory Print the current directory.\n"), N_("\ --no-print-directory Turn off -w, even if it was turned on implicitly.\n"), N_("\ -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE\n\ Consider FILE to be infinitely new.\n"), N_("\ --warn-undefined-variables Warn when an undefined variable is referenced.\n"), N_("\ -x, --trace[=TYPE] Trace command execution TYPE may be\n\ \"command\", \"read\", \"normal\".\"\n\ \"noshell\", or \"full\". Default is \"normal\"\n"), N_("\ --debugger-stop[=TYPE] Which point to enter debugger. TYPE may be\n\ \"goal\", \"preread\", \"preaction\",\n\ \"full\", \"error\", or \"fatal\".\n\ Only makes sense with -X set.\n"), N_("\ --post-mortem Go into debugger on error.\n\ Same as --debugger --debugger-stop=error\n"), N_("\ -v, --version Print the version number of make and exit.\n"), N_("\ -X, N(|--debugger Enter debugger.\n"), N_("\ --no-readline Do not use GNU ReadLine in debugger.\n"), NULL }; /* The table of command switches. Order matters here: this is the order MAKEFLAGS will be constructed. So be sure all simple flags (single char, no argument) come first. */ static const struct command_switch switches[] = { { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" }, { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 }, #ifdef WINDOWS32 { 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" }, #endif { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", }, { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" }, { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" }, { 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "keep-going" }, { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" }, { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 }, { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" }, { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" }, { 'P', flag, &profile_flag, 1, 1, 0, 0, 0, "profile" }, { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" }, { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" }, { 'R', flag, &no_builtin_variables_flag, 1, 1, 0, 0, 0, "no-builtin-variables" }, { 's', flag, &silent_flag, 1, 1, 0, 0, 0, "silent" }, { 'S', flag_off, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag, "no-keep-going" }, { 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" }, { 'v', flag, &print_version_flag, 1, 1, 0, 0, 0, "version" }, { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" }, { 'x', strlist, &tracing_opts, 1, 1, 0, "normal", 0, "trace" }, { 'X', flag, &debugger_flag, 1, 1, 0, 0, 0, "debugger" }, /* These options take arguments. */ { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" }, { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" }, { 'I', filename, &include_directories, 1, 1, 0, 0, 0, "include-dir" }, { 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots, "jobs" }, #ifndef NO_FLOAT { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #else { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average, &default_load_average, "load-average" }, #endif { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" }, { 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync" }, { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" }, /* These are long-style options. */ { CHAR_MAX+1, strlist, &db_flags, 1, 1, 0, "basic", 0, "debug" }, { CHAR_MAX+2, string, &jobserver_fds, 1, 1, 0, 0, 0, "jobserver-fds" }, { CHAR_MAX+3, flag, &show_tasks_flag, 0, 0, 0, 0, 0, "tasks" }, { CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0, "no-print-directory" }, { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0, "warn-undefined-variables" }, { CHAR_MAX+6, strlist, &eval_strings, 1, 0, 0, 0, 0, "eval" }, { CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, "sync-mutex" }, { CHAR_MAX+8, strlist, &verbosity_opts, 1, 1, 0, 0, 0, "verbosity" }, { CHAR_MAX+9, flag, (char *) &no_extended_errors, 1, 1, 0, 0, 0, "no-extended-errors", }, { CHAR_MAX+10, flag_off, (char *) &use_readline_flag, 1, 0, 0, 0, 0, "no-readline", }, { CHAR_MAX+11, flag, &show_targets_flag, 0, 0, 0, 0, 0, "targets" }, { CHAR_MAX+12, strlist, &debugger_opts, 1, 1, 0, "preaction", 0, "debugger-stop" }, { CHAR_MAX+13, flag, &b_post_mortem_flag, 0, 0, 0, 0, 0, "post-mortem" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* Secondary long names for options. */ static struct option long_option_aliases[] = { { "quiet", no_argument, 0, 's' }, { "stop", no_argument, 0, 'S' }, { "new-file", required_argument, 0, 'W' }, { "assume-new", required_argument, 0, 'W' }, { "assume-old", required_argument, 0, 'o' }, { "max-load", optional_argument, 0, 'l' }, { "dry-run", no_argument, 0, 'n' }, { "recon", no_argument, 0, 'n' }, { "makefile", required_argument, 0, 'f' }, }; /* List of goal targets. */ static struct dep *goals, *lastgoal; /* List of variables which were defined on the command line (or, equivalently, in MAKEFLAGS). */ struct command_variable { struct command_variable *next; struct variable *variable; }; static struct command_variable *command_variables; /*! Value of argv[0] which seems to get modified. Can we merge this with program below? */ char *argv0 = NULL; /*! The name we were invoked with. */ /*! Our initial arguments -- used for debugger restart execvp. */ const char * const*global_argv; /*! Our current directory before processing any -C options. */ char *directory_before_chdir = NULL; /*! Pointer to the value of the .DEFAULT_GOAL special variable. The value will be the name of the goal to remake if the command line does not override it. It can be set by the makefile, or else it's the first target defined in the makefile whose name does not start with '.'. */ struct variable * default_goal_var; /*! Pointer to structure for the file .DEFAULT whose commands are used for any file that has none of its own. This is zero if the makefiles do not define .DEFAULT. */ struct file *default_file; /* Nonzero if we have seen the '.SECONDEXPANSION' target. This turns on secondary expansion of prerequisites. */ int second_expansion; /* Nonzero if we have seen the '.ONESHELL' target. This causes the entire recipe to be handed to SHELL as a single string, potentially containing newlines. */ int one_shell; /* Nonzero if we have seen the '.NOTPARALLEL' target. This turns off parallel builds for this invocation of make. */ int not_parallel; /* Nonzero if some rule detected clock skew; we keep track so (a) we only print one warning about it during the run, and (b) we can print a final warning at the end of the run. */ int clock_skew_detected; /* If output-sync is enabled we'll collect all the output generated due to options, while reading makefiles, etc. */ struct output make_sync; /* Mask of signals that are being caught with fatal_error_signal. */ #ifdef POSIX sigset_t fatal_signal_set; #else # ifdef HAVE_SIGSETMASK int fatal_signal_mask; # endif #endif #if !HAVE_DECL_BSD_SIGNAL && !defined bsd_signal # if !defined HAVE_SIGACTION # define bsd_signal signal # else typedef RETSIGTYPE (*bsd_signal_ret_t) (int); static bsd_signal_ret_t bsd_signal (int sig, bsd_signal_ret_t func) { struct sigaction act, oact; act.sa_handler = func; act.sa_flags = SA_RESTART; sigemptyset (&act.sa_mask); sigaddset (&act.sa_mask, sig); if (sigaction (sig, &act, &oact) != 0) return SIG_ERR; return oact.sa_handler; } # endif #endif void decode_trace_flags (stringlist_t *ppsz_tracing_opts) { if (ppsz_tracing_opts) { const char **p; db_level |= (DB_TRACE | DB_SHELL); if (!ppsz_tracing_opts->list) db_level |= (DB_BASIC); else for (p = ppsz_tracing_opts->list; *p != 0; ++p) { if (0 == strcmp(*p, "command")) ; else if (0 == strcmp(*p, "full")) db_level |= (DB_VERBOSE|DB_READ_MAKEFILES); else if (0 == strcmp(*p, "normal")) db_level |= DB_BASIC; else if (0 == strcmp(*p, "noshell")) db_level = DB_BASIC | DB_TRACE; else if (0 == strcmp(*p, "read")) db_level |= DB_READ_MAKEFILES; } } } void decode_verbosity_flags (stringlist_t *ppsz_verbosity_opts) { if (ppsz_verbosity_opts) { const char **p; if (ppsz_verbosity_opts->list) for (p = ppsz_verbosity_opts->list; *p != 0; ++p) { if (0 == strcmp(*p, "no-header")) b_show_version = false; else if (0 == strcmp(*p, "full")) { db_level |= (DB_VERBOSE); b_show_version = true; } else if (0 == strcmp(*p, "terse")) { db_level &= (~DB_VERBOSE); b_show_version = false; } } } } static void initialize_global_hash_tables (void) { init_hash_global_variable_set (); strcache_init (); init_hash_files (); hash_init_directories (); hash_init_function_table (); } static const char * expand_command_line_file (const char *name) { const char *cp; char *expanded = 0; if (name[0] == '\0') O (fatal, NILF, _("empty string invalid as file name")); if (name[0] == '~') { expanded = remake_tilde_expand (name); if (expanded && expanded[0] != '\0') name = expanded; } /* This is also done in parse_file_seq, so this is redundant for names read from makefiles. It is here for names passed on the command line. */ while (name[0] == '.' && name[1] == '/') { name += 2; while (name[0] == '/') /* Skip following slashes: ".//foo" is "foo", not "/foo". */ ++name; } if (name[0] == '\0') { /* Nothing else but one or more "./", maybe plus slashes! */ name = "./"; } cp = strcache_add (name); free (expanded); return cp; } /* Toggle -d on receipt of SIGUSR1. */ #ifdef SIGUSR1 static RETSIGTYPE debug_signal_handler (int sig UNUSED) { db_level = db_level ? DB_NONE : DB_BASIC; } #endif static void decode_debug_flags (void) { const char **pp; if (debug_flag) db_level = DB_ALL; if (db_flags) for (pp=db_flags->list; *pp; ++pp) { const char *p = *pp; while (1) { switch (tolower (p[0])) { case 'a': db_level |= DB_ALL; break; case 'b': db_level |= DB_BASIC; break; case 'i': db_level |= DB_BASIC | DB_IMPLICIT; break; case 'j': db_level |= DB_JOBS; break; case 'm': db_level |= DB_BASIC | DB_MAKEFILES; break; case 'n': db_level = 0; break; case 'v': db_level |= DB_BASIC | DB_VERBOSE; break; default: OS (fatal, NILF, _("unknown debug level specification '%s'"), p); } while (*(++p) != '\0') if (*p == ',' || *p == ' ') { ++p; break; } if (*p == '\0') break; } } if (db_level) verify_flag = 1; if (! db_level) debug_flag = 0; } static void decode_output_sync_flags (void) { if (output_sync_option) { if (streq (output_sync_option, "none")) output_sync = OUTPUT_SYNC_NONE; else if (streq (output_sync_option, "line")) output_sync = OUTPUT_SYNC_LINE; else if (streq (output_sync_option, "target")) output_sync = OUTPUT_SYNC_TARGET; else if (streq (output_sync_option, "recurse")) output_sync = OUTPUT_SYNC_RECURSE; else OS (fatal, NILF, _("unknown output-sync type '%s'"), output_sync_option); } if (sync_mutex) RECORD_SYNC_MUTEX (sync_mutex); } #ifdef WINDOWS32 #ifndef NO_OUTPUT_SYNC /* This is called from start_job_command when it detects that output_sync option is in effect. The handle to the synchronization mutex is passed, as a string, to sub-makes via the --sync-mutex command-line argument. */ void prepare_mutex_handle_string (sync_handle_t handle) { if (!sync_mutex) { /* Prepare the mutex handle string for our children. */ /* 2 hex digits per byte + 2 characters for "0x" + null. */ sync_mutex = xmalloc ((2 * sizeof (sync_handle_t)) + 2 + 1); sprintf (sync_mutex, "0x%Ix", handle); define_makeflags (1, 0); } } #endif /* NO_OUTPUT_SYNC */ /* * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture * exception and print it to stderr instead. * * If ! DB_VERBOSE, just print a simple message and exit. * If DB_VERBOSE, print a more verbose message. * If compiled for DEBUG, let exception pass through to GUI so that * debuggers can attach. */ LONG WINAPI handle_runtime_exceptions (struct _EXCEPTION_POINTERS *exinfo) { PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord; LPSTR cmdline = GetCommandLine (); LPSTR prg = strtok (cmdline, " "); CHAR errmsg[1024]; #ifdef USE_EVENT_LOG HANDLE hEventSource; LPTSTR lpszStrings[1]; #endif if (! ISDB (DB_VERBOSE)) { sprintf (errmsg, _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"), prg, exrec->ExceptionCode, exrec->ExceptionAddress); fprintf (stderr, errmsg); exit (255); } sprintf (errmsg, _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"), prg, exrec->ExceptionCode, exrec->ExceptionFlags, exrec->ExceptionAddress); if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && exrec->NumberParameters >= 2) sprintf (&errmsg[strlen(errmsg)], (exrec->ExceptionInformation[0] ? _("Access violation: write operation at address 0x%p\n") : _("Access violation: read operation at address 0x%p\n")), (PVOID)exrec->ExceptionInformation[1]); /* turn this on if we want to put stuff in the event log too */ #ifdef USE_EVENT_LOG hEventSource = RegisterEventSource (NULL, "GNU Make"); lpszStrings[0] = errmsg; if (hEventSource != NULL) { ReportEvent (hEventSource, /* handle of event source */ EVENTLOG_ERROR_TYPE, /* event type */ 0, /* event category */ 0, /* event ID */ NULL, /* current user's SID */ 1, /* strings in lpszStrings */ 0, /* no bytes of raw data */ lpszStrings, /* array of error strings */ NULL); /* no raw data */ (VOID) DeregisterEventSource (hEventSource); } #endif /* Write the error to stderr too */ fprintf (stderr, errmsg); #ifdef DEBUG return EXCEPTION_CONTINUE_SEARCH; #else exit (255); return (255); /* not reached */ #endif } /* * On WIN32 systems we don't have the luxury of a /bin directory that * is mapped globally to every drive mounted to the system. Since make could * be invoked from any drive, and we don't want to propagate /bin/sh * to every single drive. Allow ourselves a chance to search for * a value for default shell here (if the default path does not exist). */ int find_and_set_default_shell (const char *token) { int sh_found = 0; char *atoken = 0; const char *search_token; const char *tokend; PATH_VAR(sh_path); extern const char *default_shell; if (!token) search_token = default_shell; else search_token = atoken = xstrdup (token); /* If the user explicitly requests the DOS cmd shell, obey that request. However, make sure that's what they really want by requiring the value of SHELL either equal, or have a final path element of, "cmd" or "cmd.exe" case-insensitive. */ tokend = search_token + strlen (search_token) - 3; if (((tokend == search_token || (tokend > search_token && (tokend[-1] == '/' || tokend[-1] == '\\'))) && !strcasecmp (tokend, "cmd")) || ((tokend - 4 == search_token || (tokend - 4 > search_token && (tokend[-5] == '/' || tokend[-5] == '\\'))) && !strcasecmp (tokend - 4, "cmd.exe"))) { batch_mode_shell = 1; unixy_shell = 0; sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else if (!no_default_sh_exe && (token == NULL || !strcmp (search_token, default_shell))) { /* no new information, path already set or known */ sh_found = 1; } else if (_access (search_token, 0) == 0) { /* search token path was found */ sprintf (sh_path, "%s", search_token); default_shell = xstrdup (w32ify (sh_path, 0)); DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"), default_shell)); sh_found = 1; } else { char *p; struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH")); /* Search Path for shell */ if (v && v->value) { char *ep; p = v->value; ep = strchr (p, PATH_SEPARATOR_CHAR); while (ep && *ep) { *ep = '\0'; sprintf (sh_path, "%s/%s", p, search_token); if (_access (sh_path, 0) == 0) { default_shell = xstrdup (w32ify (sh_path, 0)); sh_found = 1; *ep = PATH_SEPARATOR_CHAR; /* terminate loop */ p += strlen (p); } else { *ep = PATH_SEPARATOR_CHAR; p = ++ep; } ep = strchr (p, PATH_SEPARATOR_CHAR); } /* be sure to check last element of Path */ if (p && *p) { sprintf (sh_path, "%s/%s", p, search_token); if (_access (sh_path, 0) == 0) { default_shell = xstrdup (w32ify (sh_path, 0)); sh_found = 1; } } if (sh_found) DB (DB_VERBOSE, (_("find_and_set_shell() path search set default_shell = %s\n"), default_shell)); } } /* naive test */ if (!unixy_shell && sh_found && (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) { unixy_shell = 1; batch_mode_shell = 0; } #ifdef BATCH_MODE_ONLY_SHELL batch_mode_shell = 1; #endif free (atoken); return (sh_found); } #endif /* WINDOWS32 */ #ifdef __MSDOS__ static void msdos_return_to_initial_directory (void) { if (directory_before_chdir) chdir (directory_before_chdir); } #endif /* __MSDOS__ */ int main (int argc, const char **argv, char **envp) { static char *stdin_nm = 0; int makefile_status = MAKE_SUCCESS; PATH_VAR (current_directory); unsigned int restarts = 0; unsigned int syncing = 0; #ifdef WINDOWS32 const char *unix_path = NULL; const char *windows32_path = NULL; SetUnhandledExceptionFilter (handle_runtime_exceptions); /* start off assuming we have no shell */ unixy_shell = 0; no_default_sh_exe = 1; #endif argv0 = strdup(argv[0]); output_init (&make_sync); initialize_stopchar_map(); #ifdef SET_STACK_SIZE /* Get rid of any avoidable limit on stack size. */ { struct rlimit rlim; /* Set the stack limit huge so that alloca does not fail. */ if (getrlimit (RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur > 0 && rlim.rlim_cur < rlim.rlim_max) { stack_limit = rlim; rlim.rlim_cur = rlim.rlim_max; setrlimit (RLIMIT_STACK, &rlim); } else stack_limit.rlim_cur = 0; } #endif global_argv = argv; /* Needed for OS/2 */ initialize_main (&argc, &argv); #ifdef MAKE_MAINTAINER_MODE /* In maintainer mode we always enable verification. */ verify_flag = 1; #endif #if defined (__MSDOS__) && !defined (_POSIX_SOURCE) /* Request the most powerful version of 'system', to make up for the dumb default shell. */ __system_flags = (__system_redirect | __system_use_shell | __system_allow_multiple_cmds | __system_allow_long_cmds | __system_handle_null_commands | __system_emulate_chdir); #endif /* Set up gettext/internationalization support. */ setlocale (LC_ALL, ""); /* The cast to void shuts up compiler warnings on systems that disable NLS. */ (void)bindtextdomain (PACKAGE, LOCALEDIR); (void)textdomain (PACKAGE); #ifdef POSIX sigemptyset (&fatal_signal_set); #define ADD_SIG(sig) sigaddset (&fatal_signal_set, sig) #else #ifdef HAVE_SIGSETMASK fatal_signal_mask = 0; #define ADD_SIG(sig) fatal_signal_mask |= sigmask (sig) #else #define ADD_SIG(sig) (void)sig #endif #endif #define FATAL_SIG(sig) \ if (bsd_signal (sig, fatal_error_signal) == SIG_IGN) \ bsd_signal (sig, SIG_IGN); \ else \ ADD_SIG (sig); #ifdef SIGHUP FATAL_SIG (SIGHUP); #endif #ifdef SIGQUIT FATAL_SIG (SIGQUIT); #endif FATAL_SIG (SIGINT); FATAL_SIG (SIGTERM); #ifdef __MSDOS__ /* Windows 9X delivers FP exceptions in child programs to their parent! We don't want Make to die when a child divides by zero, so we work around that lossage by catching SIGFPE. */ FATAL_SIG (SIGFPE); #endif #ifdef SIGDANGER FATAL_SIG (SIGDANGER); #endif #ifdef SIGXCPU FATAL_SIG (SIGXCPU); #endif #ifdef SIGXFSZ FATAL_SIG (SIGXFSZ); #endif #undef FATAL_SIG /* Do not ignore the child-death signal. This must be done before any children could possibly be created; otherwise, the wait functions won't work on systems with the SVR4 ECHILD brain damage, if our invoker is ignoring this signal. */ #ifdef HAVE_WAIT_NOHANG # if defined SIGCHLD (void) bsd_signal (SIGCHLD, SIG_DFL); # endif # if defined SIGCLD && SIGCLD != SIGCHLD (void) bsd_signal (SIGCLD, SIG_DFL); # endif #endif output_init (NULL); /* Figure out where this program lives. */ if (argv[0] == 0) argv[0] = (char *)""; if (argv[0][0] == '\0') program = "make"; else { program = strrchr (argv[0], '/'); #if defined(__MSDOS__) || defined(__EMX__) if (program == 0) program = strrchr (argv[0], '\\'); else { /* Some weird environments might pass us argv[0] with both kinds of slashes; we must find the rightmost. */ char *p = strrchr (argv[0], '\\'); if (p && p > program) program = p; } if (program == 0 && argv[0][1] == ':') program = argv[0] + 1; #endif #ifdef WINDOWS32 if (program == 0) { /* Extract program from full path */ program = strrchr (argv[0], '\\'); if (program) { int argv0_len = strlen (program); if (argv0_len > 4 && streq (&program[argv0_len - 4], ".exe")) /* Remove .exe extension */ program[argv0_len - 4] = '\0'; } } #endif if (program == 0) #ifdef VMS program = vms_progname(argv[0]); #else program = argv[0]; #endif else ++program; } /* Set up to access user data (files). */ user_access (); initialize_global_hash_tables (); /* Figure out where we are. */ #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else OS (error, NILF, "getwd: %s", current_directory); #endif current_directory[0] = '\0'; directory_before_chdir = 0; } else directory_before_chdir = xstrdup (current_directory); #ifdef __MSDOS__ /* Make sure we will return to the initial directory, come what may. */ atexit (msdos_return_to_initial_directory); #endif /* Initialize the special variables. */ define_variable_cname (".VARIABLES", "", o_default, 0)->special = 1; /* define_variable_cname (".TARGETS", "", o_default, 0)->special = 1; */ define_variable_cname (".RECIPEPREFIX", "", o_default, 0)->special = 1; define_variable_cname (".SHELLFLAGS", "-c", o_default, 0); /* Set up .FEATURES Use a separate variable because define_variable_cname() is a macro and some compilers (MSVC) don't like conditionals in macros. */ { const char *features = "target-specific order-only second-expansion" " else-if shortest-stem undefine oneshell" #ifndef NO_ARCHIVES " archives" #endif #ifdef MAKE_JOBSERVER " jobserver" #endif #ifndef NO_OUTPUT_SYNC " output-sync" #endif #ifdef MAKE_SYMLINKS " check-symlink" #endif #ifdef HAVE_GUILE " guile" #endif #ifdef MAKE_LOAD " load" #endif ; define_variable_cname (".FEATURES", features, o_default, 0); } /* Configure GNU Guile support */ guile_gmake_setup (NILF); /* Read in variables from the environment. It is important that this be done before $(MAKE) is figured out so its definitions will not be from the environment. */ #ifndef _AMIGA { unsigned int i; for (i = 0; envp[i] != 0; ++i) { struct variable *v; const char *ep = envp[i]; /* By default, export all variables culled from the environment. */ enum variable_export export = v_export; unsigned int len; while (! STOP_SET (*ep, MAP_EQUALS)) ++ep; /* If there's no equals sign it's a malformed environment. Ignore. */ if (*ep == '\0') continue; #ifdef WINDOWS32 if (!unix_path && strneq (envp[i], "PATH=", 5)) unix_path = ep+1; else if (!strnicmp (envp[i], "Path=", 5)) { if (!windows32_path) windows32_path = ep+1; /* PATH gets defined after the loop exits. */ continue; } #endif /* Length of the variable name, and skip the '='. */ len = ep++ - envp[i]; /* If this is MAKE_RESTARTS, check to see if the "already printed the enter statement" flag is set. */ if (len == 13 && strneq (envp[i], "MAKE_RESTARTS", 13)) { if (*ep == '-') { OUTPUT_TRACED (); ++ep; } restarts = (unsigned int) atoi (ep); export = v_noexport; } v = define_variable (envp[i], len, ep, o_env, 1); /* POSIX says the value of SHELL set in the makefile won't change the value of SHELL given to subprocesses. */ if (streq (v->name, "SHELL")) { #ifndef __MSDOS__ export = v_noexport; #endif shell_var.name = xstrdup ("SHELL"); shell_var.length = 5; shell_var.value = xstrdup (ep); } v->export = export; } } #ifdef WINDOWS32 /* If we didn't find a correctly spelled PATH we define PATH as * either the first misspelled value or an empty string */ if (!unix_path) define_variable_cname ("PATH", windows32_path ? windows32_path : "", o_env, 1)->export = v_export; #endif #else /* For Amiga, read the ENV: device, ignoring all dirs */ { BPTR env, file, old; char buffer[1024]; int len; __aligned struct FileInfoBlock fib; env = Lock ("ENV:", ACCESS_READ); if (env) { old = CurrentDir (DupLock (env)); Examine (env, &fib); while (ExNext (env, &fib)) { if (fib.fib_DirEntryType < 0) /* File */ { /* Define an empty variable. It will be filled in variable_lookup(). Makes startup quite a bit faster. */ define_variable (fib.fib_FileName, strlen (fib.fib_FileName), "", o_env, 1)->export = v_export; } } UnLock (env); UnLock (CurrentDir (old)); } } #endif /* Decode the switches. */ decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS")); /* Clear GNUMAKEFLAGS to avoid duplication. */ define_variable_cname ("GNUMAKEFLAGS", "", o_env, 0); decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); /* In output sync mode we need to sync any output generated by reading the makefiles, such as in $(info ...) or stderr from $(shell ...) etc. */ syncing = make_sync.syncout = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); OUTPUT_SET (&make_sync); #if 0 /* People write things like: MFLAGS="CC=gcc -pipe" "CFLAGS=-g" and we set the -p, -i and -e switches. Doesn't seem quite right. */ decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif decode_switches (argc, (const char **)argv, 0); /* Set a variable specifying whether stdout/stdin is hooked to a TTY. */ #ifdef HAVE_ISATTY if (isatty (fileno (stdout))) if (! lookup_variable (STRING_SIZE_TUPLE ("MAKE_TERMOUT"))) { const char *tty = TTYNAME (fileno (stdout)); define_variable_cname ("MAKE_TERMOUT", tty ? tty : DEFAULT_TTYNAME, o_default, 0)->export = v_export; } if (isatty (fileno (stderr))) if (! lookup_variable (STRING_SIZE_TUPLE ("MAKE_TERMERR"))) { const char *tty = TTYNAME (fileno (stderr)); define_variable_cname ("MAKE_TERMERR", tty ? tty : DEFAULT_TTYNAME, o_default, 0)->export = v_export; } #endif /* Reset in case the switches changed our minds. */ syncing = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); if (make_sync.syncout && ! syncing) output_close (&make_sync); make_sync.syncout = syncing; OUTPUT_SET (&make_sync); /* Figure out the level of recursion. */ { struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME)); if (v && v->value[0] != '\0' && v->value[0] != '-') makelevel = (unsigned int) atoi (v->value); else makelevel = 0; } #ifdef WINDOWS32 if (suspend_flag) { fprintf (stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId ()); fprintf (stderr, _("%s is suspending for 30 seconds..."), argv[0]); Sleep (30 * 1000); fprintf (stderr, _("done sleep(30). Continuing.\n")); } #endif decode_trace_flags (tracing_opts); decode_verbosity_flags (verbosity_opts); /* FIXME: put into a subroutine like decode_trace_flags */ if (b_post_mortem_flag) { debugger_on_error |= (DEBUGGER_ON_ERROR|DEBUGGER_ON_FATAL); debugger_enabled = 1; } else if (debugger_flag) { b_debugger_preread = false; job_slots = 1; i_debugger_stepping = 1; i_debugger_nexting = 0; debugger_enabled = 1; /* For now we'll do basic debugging. Later, "stepping' will stop here while next won't - either way no printing. */ db_level |= DB_BASIC | DB_CALL | DB_SHELL | DB_UPDATE_GOAL | DB_MAKEFILES; } else { /* debugging sets some things */ if (debugger_opts) { const char **p; b_show_version = true; for (p = debugger_opts->list; *p != 0; ++p) { if (0 == strcmp(*p, "preread")) { b_debugger_preread = true; db_level |= DB_READ_MAKEFILES; } if (0 == strcmp(*p, "goal")) { b_debugger_goal = true; db_level |= DB_UPDATE_GOAL; } if ( 0 == strcmp(*p, "full") || b_debugger_preread || 0 == strcmp(*p, "preaction") ) { job_slots = 1; i_debugger_stepping = 1; i_debugger_nexting = 0; debugger_enabled = 1; /* For now we'll do basic debugging. Later, "stepping' will stop here while next won't - either way no printing. */ db_level |= DB_BASIC | DB_CALL | DB_SHELL | DB_UPDATE_GOAL | DB_MAKEFILES; } if ( 0 == strcmp(*p, "full") || 0 == strcmp(*p, "error") ) { debugger_on_error |= (DEBUGGER_ON_ERROR|DEBUGGER_ON_FATAL); } else if ( 0 == strcmp(*p, "fatal") ) { debugger_on_error |= DEBUGGER_ON_FATAL; } } #ifndef HAVE_LIBREADLINE error (NILF, "warning: you specified a debugger option, but you don't have readline support"); error (NILF, "debugger support compiled in. Debugger options will be ignored."); #endif } } /* Set always_make_flag if -B was given and we've not restarted already. */ always_make_flag = always_make_set && (restarts == 0); /* Print version information, and exit. */ if (print_version_flag) { print_version (); die (MAKE_SUCCESS); } if (ISDB (DB_BASIC) && makelevel == 0 && b_show_version) print_version (); #ifndef VMS /* Set the "MAKE_COMMAND" variable to the name we were invoked with. (If it is a relative pathname with a slash, prepend our directory name so the result will run the same program regardless of the current dir. If it is a name with no slash, we can only hope that PATH did not find it in the current directory.) */ #ifdef WINDOWS32 /* * Convert from backslashes to forward slashes for * programs like sh which don't like them. Shouldn't * matter if the path is one way or the other for * CreateProcess(). */ if (strpbrk (argv[0], "/:\\") || strstr (argv[0], "..") || strneq (argv[0], "//", 2)) argv[0] = xstrdup (w32ify (argv[0], 1)); #else /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) if (strchr (argv[0], '\\')) { char *p; argv[0] = xstrdup (argv[0]); for (p = argv[0]; *p; p++) if (*p == '\\') *p = '/'; } /* If argv[0] is not in absolute form, prepend the current directory. This can happen when Make is invoked by another DJGPP program that uses a non-absolute name. */ if (current_directory[0] != '\0' && argv[0] != 0 && (argv[0][0] != '/' && (argv[0][0] == '\0' || argv[0][1] != ':')) # ifdef __EMX__ /* do not prepend cwd if argv[0] contains no '/', e.g. "make" */ && (strchr (argv[0], '/') != 0 || strchr (argv[0], '\\') != 0) # endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #else /* !__MSDOS__ */ if (current_directory[0] != '\0' && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0 #ifdef HAVE_DOS_PATHS && (argv[0][0] != '\\' && (!argv[0][0] || argv[0][1] != ':')) && strchr (argv[0], '\\') != 0 #endif ) argv[0] = xstrdup (concat (3, current_directory, "/", argv[0])); #endif /* !__MSDOS__ */ #endif /* WINDOWS32 */ #endif /* We may move, but until we do, here we are. */ starting_directory = current_directory; if (profile_flag) init_callgrind(PACKAGE_TARNAME " " PACKAGE_VERSION, argv); #ifdef MAKE_JOBSERVER /* If the jobserver-fds option is seen, make sure that -j is reasonable. This can't be usefully set in the makefile, and we want to verify the FDs are valid before any other aspect of make has a chance to start using them for something else. */ if (jobserver_fds) { /* Make sure the jobserver option has the proper format. */ const char *cp = jobserver_fds; #ifdef WINDOWS32 if (! open_jobserver_semaphore (cp)) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); fatal (NILF, strlen (cp) + INTSTR_LENGTH + strlen (estr), _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"), cp, err, estr); } DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp)); #else if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2) OS (fatal, NILF, _("internal error: invalid --jobserver-fds string '%s'"), cp); DB (DB_JOBS, (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1])); #endif /* The combination of a pipe + !job_slots means we're using the jobserver. If !job_slots and we don't have a pipe, we can start infinite jobs. If we see both a pipe and job_slots >0 that means the user set -j explicitly. This is broken; in this case obey the user (ignore the jobserver pipe for this make) but print a message. If we've restarted, we already printed this the first time. */ if (job_slots > 0) { if (! restarts) O (error, NILF, _("warning: -jN forced in submake: disabling jobserver mode.")); } #ifndef WINDOWS32 #ifdef HAVE_FCNTL # define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF)) #else # define FD_OK(_f) 1 #endif /* Create a duplicate pipe, that will be closed in the SIGCHLD handler. If this fails with EBADF, the parent has closed the pipe on us because it didn't think we were a submake. If so, print a warning then default to -j1. */ else if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1]) || (job_rfd = dup (job_fds[0])) < 0) { if (errno != EBADF) pfatal_with_name (_("dup jobserver")); O (error, NILF, _("warning: jobserver unavailable: using -j1. Add '+' to parent make rule.")); job_slots = 1; job_fds[0] = job_fds[1] = -1; } #endif if (job_slots > 0) { #ifdef WINDOWS32 free_jobserver_semaphore (); #else if (job_fds[0] >= 0) close (job_fds[0]); if (job_fds[1] >= 0) close (job_fds[1]); #endif job_fds[0] = job_fds[1] = -1; free (jobserver_fds); jobserver_fds = 0; } } #endif /* The extra indirection through $(MAKE_COMMAND) is done for hysterical raisins. */ #ifdef VMS define_variable_cname("MAKE_COMMAND", vms_command(argv[0]), o_default, 0); #else define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0); #endif define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1); if (command_variables != 0) { struct command_variable *cv; struct variable *v; unsigned int len = 0; char *value, *p; /* Figure out how much space will be taken up by the command-line variable definitions. */ for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; len += 2 * strlen (v->name); if (! v->recursive) ++len; ++len; len += 2 * strlen (v->value); ++len; } /* Now allocate a buffer big enough and fill it. */ p = value = alloca (len); for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; p = quote_for_env (p, v->name); if (! v->recursive) *p++ = ':'; *p++ = '='; p = quote_for_env (p, v->value); *p++ = ' '; } p[-1] = '\0'; /* Kill the final space and terminate. */ /* Define an unchangeable variable with a name that no POSIX.2 makefile could validly use for its own variable. */ define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0); /* Define the variable; this will not override any user definition. Normally a reference to this variable is written into the value of MAKEFLAGS, allowing the user to override this value to affect the exported value of MAKEFLAGS. In POSIX-pedantic mode, we cannot allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so a reference to this hidden variable is written instead. */ define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}", o_env, 1); } /* If there were -C flags, move ourselves about. */ if (directories != 0) { unsigned int i; for (i = 0; directories->list[i] != 0; ++i) { const char *dir = directories->list[i]; #ifdef WINDOWS32 /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/' But allow -C/ just in case someone wants that. */ { char *p = (char *)dir + strlen (dir) - 1; while (p > dir && (p[0] == '/' || p[0] == '\\')) --p; p[1] = '\0'; } #endif if (chdir (dir) < 0) pfatal_with_name (dir); } } #ifdef WINDOWS32 /* * THIS BLOCK OF CODE MUST COME AFTER chdir() CALL ABOVE IN ORDER * TO NOT CONFUSE THE DEPENDENCY CHECKING CODE IN implicit.c. * * The functions in dir.c can incorrectly cache information for "." * before we have changed directory and this can cause file * lookups to fail because the current directory (.) was pointing * at the wrong place when it was first evaluated. */ no_default_sh_exe = !find_and_set_default_shell (NULL); #endif /* WINDOWS32 */ /* Except under -s, always do -w in sub-makes and under -C. */ if (!silent_flag && (directories != 0 || makelevel > 0)) print_directory_flag = 1; /* Let the user disable that with --no-print-directory. */ if (inhibit_print_directory_flag) print_directory_flag = 0; /* If -R was given, set -r too (doesn't make sense otherwise!) */ if (no_builtin_variables_flag) no_builtin_rules_flag = 1; /* Construct the list of include directories to search. */ construct_include_path (include_directories == 0 ? 0 : include_directories->list); /* If we chdir'ed, figure out where we are now. */ if (directories) { #ifdef WINDOWS32 if (getcwd_fs (current_directory, GET_PATH_MAX) == 0) #else if (getcwd (current_directory, GET_PATH_MAX) == 0) #endif { #ifdef HAVE_GETCWD perror_with_name ("getcwd", ""); #else OS (error, NILF, "getwd: %s", current_directory); #endif starting_directory = 0; } else starting_directory = current_directory; } define_variable_cname ("CURDIR", current_directory, o_file, 0); /* Read any stdin makefiles into temporary files. */ if (makefiles != 0) { unsigned int i; for (i = 0; i < makefiles->idx; ++i) if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0') { /* This makefile is standard input. Since we may re-exec and thus re-read the makefiles, we read standard input into a temporary file and read from that. */ FILE *outfile; char *template; const char *tmpdir; if (stdin_nm) O (fatal, NILF, _("Makefile from standard input specified twice.")); #ifdef VMS # define DEFAULT_TMPDIR "sys$scratch:" #else # ifdef P_tmpdir # define DEFAULT_TMPDIR P_tmpdir # else # define DEFAULT_TMPDIR "/tmp" # endif #endif #define DEFAULT_TMPFILE "GmXXXXXX" if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0') #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__) /* These are also used commonly on these platforms. */ && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0') && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0') #endif ) tmpdir = DEFAULT_TMPDIR; template = alloca (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2); strcpy (template, tmpdir); #ifdef HAVE_DOS_PATHS if (strchr ("/\\", template[strlen (template) - 1]) == NULL) strcat (template, "/"); #else # ifndef VMS if (template[strlen (template) - 1] != '/') strcat (template, "/"); # endif /* !VMS */ #endif /* !HAVE_DOS_PATHS */ strcat (template, DEFAULT_TMPFILE); outfile = output_tmpfile (&stdin_nm, template); if (outfile == 0) pfatal_with_name (_("fopen (temporary file)")); while (!feof (stdin) && ! ferror (stdin)) { char buf[2048]; unsigned int n = fread (buf, 1, sizeof (buf), stdin); if (n > 0 && fwrite (buf, 1, n, outfile) != n) pfatal_with_name (_("fwrite (temporary file)")); } fclose (outfile); /* Replace the name that read_all_makefiles will see with the name of the temporary file. */ makefiles->list[i] = strcache_add (stdin_nm); /* Make sure the temporary file will not be remade. */ { struct file *f = enter_file (strcache_add (stdin_nm)); f->updated = 1; f->update_status = us_success; f->command_state = cs_finished; /* Can't be intermediate, or it'll be removed too early for make re-exec. */ f->intermediate = 0; f->dontcare = 0; } } } #ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */ #if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG) /* Set up to handle children dying. This must be done before reading in the makefiles so that 'shell' function calls will work. If we don't have a hanging wait we have to fall back to old, broken functionality here and rely on the signal handler and counting children. If we're using the jobs pipe we need a signal handler so that SIGCHLD is not ignored; we need it to interrupt the read(2) of the jobserver pipe in job.c if we're waiting for a token. If none of these are true, we don't need a signal handler at all. */ { RETSIGTYPE child_handler (int sig); # if defined SIGCHLD bsd_signal (SIGCHLD, child_handler); # endif # if defined SIGCLD && SIGCLD != SIGCHLD bsd_signal (SIGCLD, child_handler); # endif } #endif #endif /* Let the user send us SIGUSR1 to toggle the -d flag during the run. */ #ifdef SIGUSR1 bsd_signal (SIGUSR1, debug_signal_handler); #endif /* Define the initial list of suffixes for old-style rules. */ set_default_suffixes (); /* Define the file rules for the built-in suffix rules. These will later be converted into pattern rules. We used to do this in install_default_implicit_rules, but since that happens after reading makefiles, it results in the built-in pattern rules taking precedence over makefile-specified suffix rules, which is wrong. */ install_default_suffix_rules (); /* Define some internal and special variables. */ define_automatic_variables (); /* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see. Initialize it to be exported but allow the makefile to reset it. */ define_makeflags (0, 0)->export = v_export; /* Define the default variables. */ define_default_variables (); default_file = enter_file (strcache_add (".DEFAULT")); default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0); /* Evaluate all strings provided with --eval. Also set up the $(-*-eval-flags-*-) variable. */ if (eval_strings) { char *p, *value; unsigned int i; unsigned int len = (CSTRLEN ("--eval=") + 1) * eval_strings->idx; for (i = 0; i < eval_strings->idx; ++i) { p = xstrdup (eval_strings->list[i]); len += 2 * strlen (p); eval_buffer (p, NULL); free (p); } p = value = alloca (len); for (i = 0; i < eval_strings->idx; ++i) { strcpy (p, "--eval="); p += CSTRLEN ("--eval="); p = quote_for_env (p, eval_strings->list[i]); *(p++) = ' '; } p[-1] = '\0'; define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0); } /* Read all the makefiles. */ read_makefiles = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list); #ifdef WINDOWS32 /* look one last time after reading all Makefiles */ if (no_default_sh_exe) no_default_sh_exe = !find_and_set_default_shell (NULL); #endif /* WINDOWS32 */ #if defined (__MSDOS__) || defined (__EMX__) /* We need to know what kind of shell we will be using. */ { extern int _is_unixy_shell (const char *_path); struct variable *shv = lookup_variable (STRING_SIZE_TUPLE ("SHELL")); extern int unixy_shell; extern const char *default_shell; if (shv && *shv->value) { char *shell_path = recursively_expand (shv); if (shell_path && _is_unixy_shell (shell_path)) unixy_shell = 1; else unixy_shell = 0; if (shell_path) default_shell = shell_path; } } #endif /* __MSDOS__ || __EMX__ */ { int old_builtin_rules_flag = no_builtin_rules_flag; int old_builtin_variables_flag = no_builtin_variables_flag; /* Decode switches again, for variables set by the makefile. */ decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS")); /* Clear GNUMAKEFLAGS to avoid duplication. */ define_variable_cname ("GNUMAKEFLAGS", "", o_override, 0); decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); #if 0 decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); #endif /* Reset in case the switches changed our mind. */ syncing = (output_sync == OUTPUT_SYNC_LINE || output_sync == OUTPUT_SYNC_TARGET); if (make_sync.syncout && ! syncing) output_close (&make_sync); make_sync.syncout = syncing; OUTPUT_SET (&make_sync); /* If we've disabled builtin rules, get rid of them. */ if (no_builtin_rules_flag && ! old_builtin_rules_flag) { if (suffix_file->builtin) { free_dep_chain (suffix_file->deps); suffix_file->deps = 0; } define_variable_cname ("SUFFIXES", "", o_default, 0); } /* If we've disabled builtin variables, get rid of them. */ if (no_builtin_variables_flag && ! old_builtin_variables_flag) undefine_default_variables (); } #if defined (__MSDOS__) || defined (__EMX__) || defined (VMS) if (job_slots != 1 # ifdef __EMX__ && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */ # endif ) { O (error, NILF, _("Parallel jobs (-j) are not supported on this platform.")); O (error, NILF, _("Resetting to single job (-j1) mode.")); job_slots = 1; } #endif #ifdef MAKE_JOBSERVER /* If we have >1 slot but no jobserver-fds, then we're a top-level make. Set up the pipe and install the fds option for our children. */ if (job_slots > 1) { #ifdef WINDOWS32 /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects * and one of them is the job-server semaphore object. Limit the * number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */ if (job_slots >= MAXIMUM_WAIT_OBJECTS) { job_slots = MAXIMUM_WAIT_OBJECTS - 1; DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), job_slots)); } if (! create_jobserver_semaphore (job_slots - 1)) { DWORD err = GetLastError (); const char *estr = map_windows32_error_to_string (err); ONS (fatal, NILF, _("creating jobserver semaphore: (Error %ld: %s)"), err, estr); } #else char c = '+'; if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0) pfatal_with_name (_("creating jobs pipe")); #endif /* Every make assumes that it always has one job it can run. For the submakes it's the token they were given by their parent. For the top make, we just subtract one from the number the user wants. We want job_slots to be 0 to indicate we're using the jobserver. */ master_job_slots = job_slots; #ifdef WINDOWS32 /* We're using the jobserver so set job_slots to 0. */ job_slots = 0; #else while (--job_slots) { int r; EINTRLOOP (r, write (job_fds[1], &c, 1)); if (r != 1) pfatal_with_name (_("init jobserver pipe")); } #endif /* Fill in the jobserver_fds for our children. */ #ifdef WINDOWS32 jobserver_fds = xmalloc (MAX_PATH + 1); strcpy (jobserver_fds, get_jobserver_semaphore_name ()); #else jobserver_fds = xmalloc ((INTSTR_LENGTH * 2) + 2); sprintf (jobserver_fds, "%d,%d", job_fds[0], job_fds[1]); #endif } #endif #ifndef MAKE_SYMLINKS if (check_symlink_flag) { O (error, NILF, _("Symbolic links not supported: disabling -L.")); check_symlink_flag = 0; } #endif /* Set up MAKEFLAGS and MFLAGS again, so they will be right. */ define_makeflags (1, 0); /* Make each 'struct dep' point at the 'struct file' for the file depended on. Also do magic for special targets. */ snap_deps (); /* Convert old-style suffix rules to pattern rules. It is important to do this before installing the built-in pattern rules below, so that makefile-specified suffix rules take precedence over built-in pattern rules. */ convert_to_pattern (); /* Install the default implicit pattern rules. This used to be done before reading the makefiles. But in that case, built-in pattern rules were in the chain before user-defined ones, so they matched first. */ install_default_implicit_rules (); /* Compute implicit rule limits. */ count_implicit_rule_limits (); /* Construct the listings of directories in VPATH lists. */ build_vpath_lists (); /* Mark files given with -o flags as very old and as having been updated already, and files given with -W flags as brand new (time-stamp as far as possible into the future). If restarts is set we'll do -W later. */ if (old_files != 0) { const char **p; for (p = old_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = OLD_MTIME; f->updated = 1; f->update_status = us_success; f->command_state = cs_finished; } } if (!restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* Initialize the remote job module. */ remote_setup (); /* Dump any output we've collected. */ OUTPUT_UNSET (); output_close (&make_sync); if (read_makefiles != 0) { /* Update any makefiles if necessary. */ FILE_TIMESTAMP *makefile_mtimes = 0; unsigned int mm_idx = 0; char **aargv = NULL; const char **nargv; int nargc; int orig_db_level = db_level; enum update_status status; if (! ISDB (DB_MAKEFILES)) db_level = DB_NONE; DB (DB_BASIC, (_("Updating makefiles....\n"))); /* Remove any makefiles we don't want to try to update. Also record the current modtimes so we can compare them later. */ { register struct dep *d, *last; last = 0; d = read_makefiles; while (d != 0) { struct file *f = d->file; if (f->double_colon) for (f = f->double_colon; f != NULL; f = f->prev) { if (f->deps == 0 && f->cmds != 0) { /* This makefile is a :: target with commands, but no dependencies. So, it will always be remade. This might well cause an infinite loop, so don't try to remake it. (This will only happen if your makefiles are written exceptionally stupidly; but if you work for Athena, that's how you write your makefiles.) */ DB (DB_VERBOSE, (_("Makefile '%s' might loop; not remaking it.\n"), f->name)); if (last == 0) read_makefiles = d->next; else last->next = d->next; /* Free the storage. */ free_dep (d); d = last == 0 ? read_makefiles : last->next; break; } } if (f == NULL || !f->double_colon) { makefile_mtimes = xrealloc (makefile_mtimes, (mm_idx+1) * sizeof (FILE_TIMESTAMP)); makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file); last = d; d = d->next; } } } /* Set up 'MAKEFLAGS' specially while remaking makefiles. */ define_makeflags (1, 1); rebuilding_makefiles = 1; status = update_goal_chain (read_makefiles); rebuilding_makefiles = 0; switch (status) { case us_question: /* The only way this can happen is if the user specified -q and asked * for one of the makefiles to be remade as a target on the command * line. Since we're not actually updating anything with -q we can * treat this as "did nothing". */ case us_none: /* Did nothing. */ break; case us_failed: /* Failed to update. Figure out if we care. */ { /* Nonzero if any makefile was successfully remade. */ int any_remade = 0; /* Nonzero if any makefile we care about failed in updating or could not be found at all. */ int any_failed = 0; unsigned int i; struct dep *d; for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next) { /* Reset the considered flag; we may need to look at the file again to print an error. */ d->file->considered = 0; if (d->file->updated) { /* This makefile was updated. */ if (d->file->update_status == us_success) { /* It was successfully updated. */ any_remade |= (file_mtime_no_search (d->file) != makefile_mtimes[i]); } else if (! (d->changed & RM_DONTCARE)) { FILE_TIMESTAMP mtime; /* The update failed and this makefile was not from the MAKEFILES variable, so we care. */ OS (error, NILF, _("Failed to remake makefile '%s'."), d->file->name); mtime = file_mtime_no_search (d->file); any_remade |= (mtime != NONEXISTENT_MTIME && mtime != makefile_mtimes[i]); makefile_status = MAKE_FAILURE; } } else /* This makefile was not found at all. */ if (! (d->changed & RM_DONTCARE)) { const char *dnm = dep_name (d); size_t l = strlen (dnm); /* This is a makefile we care about. See how much. */ if (d->changed & RM_INCLUDED) /* An included makefile. We don't need to die, but we do want to complain. */ error (NILF, l, _("Included makefile '%s' was not found."), dnm); else { /* A normal makefile. We must die later. */ error (NILF, l, _("Makefile '%s' was not found"), dnm); any_failed = 1; } } } /* Reset this to empty so we get the right error message below. */ read_makefiles = 0; if (any_remade) goto re_exec; if (any_failed) die (MAKE_FAILURE); break; } case us_success: re_exec: /* Updated successfully. Re-exec ourselves. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); clean_jobserver (0); if (makefiles != 0) { /* These names might have changed. */ int i, j = 0; for (i = 1; i < argc; ++i) if (strneq (argv[i], "-f", 2)) /* XXX */ { if (argv[i][2] == '\0') /* This cast is OK since we never modify argv. */ argv[++i] = (char *) makefiles->list[j]; else argv[i] = xstrdup (concat (2, "-f", makefiles->list[j])); ++j; } } /* Add -o option for the stdin temporary file, if necessary. */ nargc = argc; if (stdin_nm) { void *m = xmalloc ((nargc + 2) * sizeof (char *)); aargv = m; memcpy (aargv, argv, argc * sizeof (char *)); aargv[nargc++] = xstrdup (concat (2, "-o", stdin_nm)); aargv[nargc] = 0; nargv = m; } else nargv = (const char**)argv; if (directories != 0 && directories->idx > 0) { int bad = 1; if (directory_before_chdir != 0) { if (chdir (directory_before_chdir) < 0) perror_with_name ("chdir", ""); else bad = 0; } if (bad) O (fatal, NILF, _("Couldn't change back to original directory.")); } ++restarts; /* If we're re-exec'ing the first make, put back the number of job slots so define_makefiles() will get it right. */ if (master_job_slots) job_slots = master_job_slots; if (ISDB (DB_BASIC)) { const char **p; printf (_("Re-executing[%u]:"), restarts); for (p = nargv; *p != 0; ++p) printf (" %s", *p); putchar ('\n'); } #ifndef _AMIGA { char **p; for (p = environ; *p != 0; ++p) { if (strneq (*p, MAKELEVEL_NAME "=", MAKELEVEL_LENGTH+1)) { *p = alloca (40); sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel); } else if (strneq (*p, "MAKE_RESTARTS=", CSTRLEN ("MAKE_RESTARTS="))) { *p = alloca (40); sprintf (*p, "MAKE_RESTARTS=%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); restarts = 0; } } } #else /* AMIGA */ { char buffer[256]; sprintf (buffer, "%u", makelevel); SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY); sprintf (buffer, "%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY); restarts = 0; } #endif /* If we didn't set the restarts variable yet, add it. */ if (restarts) { char *b = alloca (40); sprintf (b, "MAKE_RESTARTS=%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts); putenv (b); } fflush (stdout); fflush (stderr); /* Close the dup'd jobserver pipe if we opened one. */ if (job_rfd >= 0) close (job_rfd); #ifdef _AMIGA exec_command (nargv); exit (0); #elif defined (__EMX__) { /* It is not possible to use execve() here because this would cause the parent process to be terminated with exit code 0 before the child process has been terminated. Therefore it may be the best solution simply to spawn the child process including all file handles and to wait for its termination. */ int pid; int r; pid = child_execute_job (FD_STDIN, FD_STDOUT, FD_STDERR, nargv, environ); /* is this loop really necessary? */ do { pid = wait (&r); } while (pid <= 0); /* use the exit code of the child process */ exit (WIFEXITED(r) ? WEXITSTATUS(r) : EXIT_FAILURE); } #else exec_command ((char **)nargv, environ); #endif free (aargv); break; } db_level = orig_db_level; /* Free the makefile mtimes. */ free (makefile_mtimes); } /* Set up 'MAKEFLAGS' again for the normal targets. */ define_makeflags (1, 0); /* Set always_make_flag if -B was given. */ always_make_flag = always_make_set; /* If restarts is set we haven't set up -W files yet, so do that now. */ if (restarts && new_files != 0) { const char **p; for (p = new_files->list; *p != 0; ++p) { struct file *f = enter_file (*p); f->last_mtime = f->mtime_before_update = NEW_MTIME; } } /* If there is a temp file from reading a makefile from stdin, get rid of it now. */ if (stdin_nm && unlink (stdin_nm) < 0 && errno != ENOENT) perror_with_name (_("unlink (temporary file): "), stdin_nm); /* If there were no command-line goals, use the default. */ if (goals == 0) { char *p; if (default_goal_var->recursive) p = variable_expand (default_goal_var->value); else { p = variable_buffer_output (variable_buffer, default_goal_var->value, strlen (default_goal_var->value)); *p = '\0'; p = variable_buffer; } if (*p != '\0') { struct file *f = lookup_file (p); /* If .DEFAULT_GOAL is a non-existent target, enter it into the table and let the standard logic sort it out. */ if (f == 0) { struct nameseq *ns; ns = PARSE_SIMPLE_SEQ (&p, struct nameseq); if (ns) { /* .DEFAULT_GOAL should contain one target. */ if (ns->next != 0) O (fatal, NILF, _(".DEFAULT_GOAL contains more than one target")); f = enter_file (strcache_add (ns->name)); ns->name = 0; /* It was reused by enter_file(). */ free_ns_chain (ns); } } if (f) { goals = alloc_dep (); goals->file = f; } } } else lastgoal->next = 0; if (!goals) { if (read_makefiles == 0) O (fatal, NILF, _("No targets specified and no makefile found")); O (fatal, NILF, _("No targets")); } if (show_tasks_flag || show_task_comments_flag) { dbg_cmd_info_targets(show_task_comments_flag ? INFO_TARGET_TASKS_WITH_COMMENTS : INFO_TARGET_TASKS); die(0); } else if (show_targets_flag) { dbg_cmd_info_targets(INFO_TARGET_NAME); die(0); } /* Update the goals. */ DB (DB_BASIC, (_("Updating goal targets....\n"))); { switch (update_goal_chain (goals)) { case us_none: /* Nothing happened. */ /* FALLTHROUGH */ case us_success: /* Keep the previous result. */ break; case us_question: /* We are under -q and would run some commands. */ makefile_status = MAKE_TROUBLE; break; case us_failed: /* Updating failed. POSIX.2 specifies exit status >1 for this; but in VMS, there is only success and failure. */ makefile_status = MAKE_FAILURE; break; } /* If we detected some clock skew, generate one last warning */ if (clock_skew_detected) O (error, NILF, _("warning: Clock skew detected. Your build may be incomplete.")); /* Exit. */ die (makefile_status); } /* NOTREACHED */ exit (MAKE_SUCCESS); } /* Parsing of arguments, decoding of switches. */ static char options[1 + sizeof (switches) / sizeof (switches[0]) * 3]; static struct option long_options[(sizeof (switches) / sizeof (switches[0])) + (sizeof (long_option_aliases) / sizeof (long_option_aliases[0]))]; /* Fill in the string and vector for getopt. */ static void init_switches (void) { char *p; unsigned int c; unsigned int i; if (options[0] != '\0') /* Already done. */ return; p = options; /* Return switch and non-switch args in order, regardless of POSIXLY_CORRECT. Non-switch args are returned as option 1. */ *p++ = '-'; for (i = 0; switches[i].c != '\0'; ++i) { long_options[i].name = (switches[i].long_name == 0 ? "" : switches[i].long_name); long_options[i].flag = 0; long_options[i].val = switches[i].c; if (short_option (switches[i].c)) *p++ = switches[i].c; switch (switches[i].type) { case flag: case flag_off: case ignore: long_options[i].has_arg = no_argument; break; case string: case strlist: case filename: case positive_int: case floating: if (short_option (switches[i].c)) *p++ = ':'; if (switches[i].noarg_value != 0) { if (short_option (switches[i].c)) *p++ = ':'; long_options[i].has_arg = optional_argument; } else long_options[i].has_arg = required_argument; break; } } *p = '\0'; for (c = 0; c < (sizeof (long_option_aliases) / sizeof (long_option_aliases[0])); ++c) long_options[i++] = long_option_aliases[c]; long_options[i].name = 0; } /* Non-option argument. It might be a variable definition. */ static void handle_non_switch_argument (const char *arg, int env) { struct variable *v; if (arg[0] == '-' && arg[1] == '\0') /* Ignore plain '-' for compatibility. */ return; v = try_variable_definition (0, arg, o_command, 0); if (v != 0) { /* It is indeed a variable definition. If we don't already have this one, record a pointer to the variable for later use in define_makeflags. */ struct command_variable *cv; for (cv = command_variables; cv != 0; cv = cv->next) if (cv->variable == v) break; if (! cv) { cv = xmalloc (sizeof (*cv)); cv->variable = v; cv->next = command_variables; command_variables = cv; } } else if (! env) { /* Not an option or variable definition; it must be a goal target! Enter it as a file and add it to the dep chain of goals. */ struct file *f = enter_file (strcache_add (expand_command_line_file (arg))); f->cmd_target = 1; if (goals == 0) { goals = alloc_dep (); lastgoal = goals; } else { lastgoal->next = alloc_dep (); lastgoal = lastgoal->next; } lastgoal->file = f; { /* Add this target name to the MAKECMDGOALS variable. */ struct variable *gv; const char *value; gv = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS")); if (gv == 0) value = f->name; else { /* Paste the old and new values together */ unsigned int oldlen, newlen; char *vp; oldlen = strlen (gv->value); newlen = strlen (f->name); vp = alloca (oldlen + 1 + newlen + 1); memcpy (vp, gv->value, oldlen); vp[oldlen] = ' '; memcpy (&vp[oldlen + 1], f->name, newlen + 1); value = vp; } define_variable_cname ("MAKECMDGOALS", value, o_default, 0); } } } /* Print a nice usage method. */ static void print_usage (int bad) { const char *const *cpp; FILE *usageto; if (print_version_flag) print_version (); usageto = bad ? stderr : stdout; fprintf (usageto, _("Usage: %s [options] [target] ...\n"), program); for (cpp = usage; *cpp; ++cpp) fputs (_(*cpp), usageto); if (!remote_description || *remote_description == '\0') fprintf (usageto, _("\nThis program built for %s\n"), make_host); else fprintf (usageto, _("\nThis program built for %s (%s)\n"), make_host, remote_description); fprintf (usageto, _("Report bugs to https://github.com/rocky/remake/issues\n")); } /* Decode switches from ARGC and ARGV. They came from the environment if ENV is nonzero. */ static void decode_switches (int argc, const char **argv, int env) { int bad = 0; register const struct command_switch *cs; register struct stringlist *sl; register int c; /* getopt does most of the parsing for us. First, get its vectors set up. */ init_switches (); /* Let getopt produce error messages for the command line, but not for options from the environment. */ opterr = !env; /* Reset getopt's state. */ optind = 0; while (optind < argc) { const char *coptarg; /* Parse the next argument. */ c = getopt_long (argc, (char*const*)argv, options, long_options, NULL); coptarg = optarg; if (c == EOF) /* End of arguments, or "--" marker seen. */ break; else if (c == 1) /* An argument not starting with a dash. */ handle_non_switch_argument (coptarg, env); else if (c == '?') /* Bad option. We will print a usage message and die later. But continue to parse the other options so the user can see all he did wrong. */ bad = 1; else for (cs = switches; cs->c != '\0'; ++cs) if (cs->c == c) { /* Whether or not we will actually do anything with this switch. We test this individually inside the switch below rather than just once outside it, so that options which are to be ignored still consume args. */ int doit = !env || cs->env; switch (cs->type) { default: abort (); case ignore: break; case flag: case flag_off: if (doit) *(int *) cs->value_ptr = cs->type == flag; break; case string: case strlist: case filename: if (!doit) break; if (! coptarg) coptarg = xstrdup (cs->noarg_value); else if (*coptarg == '\0') { char opt[2] = "c"; const char *op = opt; if (short_option (cs->c)) opt[0] = cs->c; else op = cs->long_name; error (NILF, strlen (op), _("the '%s%s' option requires a non-empty string argument"), short_option (cs->c) ? "-" : "--", op); bad = 1; break; } if (cs->type == string) { char **val = (char **)cs->value_ptr; free (*val); *val = xstrdup (coptarg); break; } sl = *(struct stringlist **) cs->value_ptr; if (sl == 0) { sl = xmalloc (sizeof (struct stringlist)); sl->max = 5; sl->idx = 0; sl->list = xmalloc (5 * sizeof (char *)); *(struct stringlist **) cs->value_ptr = sl; } else if (sl->idx == sl->max - 1) { sl->max += 5; /* MSVC erroneously warns without a cast here. */ sl->list = xrealloc ((void *)sl->list, sl->max * sizeof (char *)); } if (cs->type == filename) sl->list[sl->idx++] = expand_command_line_file (coptarg); else sl->list[sl->idx++] = xstrdup (coptarg); sl->list[sl->idx] = 0; break; case positive_int: /* See if we have an option argument; if we do require that it's all digits, not something like "10foo". */ if (coptarg == 0 && argc > optind) { const char *cp; for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp) ; if (cp[0] == '\0') coptarg = argv[optind++]; } if (!doit) break; if (coptarg) { int i = atoi (coptarg); const char *cp; /* Yes, I realize we're repeating this in some cases. */ for (cp = coptarg; ISDIGIT (cp[0]); ++cp) ; if (i < 1 || cp[0] != '\0') { error (NILF, 0, _("the '-%c' option requires a positive integer argument"), cs->c); bad = 1; } else *(unsigned int *) cs->value_ptr = i; } else *(unsigned int *) cs->value_ptr = *(unsigned int *) cs->noarg_value; break; #ifndef NO_FLOAT case floating: if (coptarg == 0 && optind < argc && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.')) coptarg = argv[optind++]; if (doit) *(double *) cs->value_ptr = (coptarg != 0 ? atof (coptarg) : *(double *) cs->noarg_value); break; #endif } /* We've found the switch. Stop looking. */ break; } } /* There are no more options according to getting getopt, but there may be some arguments left. Since we have asked for non-option arguments to be returned in order, this only happens when there is a "--" argument to prevent later arguments from being options. */ while (optind < argc) handle_non_switch_argument (argv[optind++], env); if (!env && (bad || print_usage_flag)) { print_usage (bad); die (bad ? MAKE_FAILURE : MAKE_SUCCESS); } /* If there are any options that need to be decoded do it now. */ decode_debug_flags (); decode_output_sync_flags (); } /* Decode switches from environment variable ENVAR (which is LEN chars long). We do this by chopping the value into a vector of words, prepending a dash to the first word if it lacks one, and passing the vector to decode_switches. */ static void decode_env_switches (const char *envar, unsigned int len) { char *varref = alloca (2 + len + 2); char *value, *p, *buf; int argc; const char **argv; /* Get the variable's value. */ varref[0] = '$'; varref[1] = '('; memcpy (&varref[2], envar, len); varref[2 + len] = ')'; varref[2 + len + 1] = '\0'; value = variable_expand (varref); /* Skip whitespace, and check for an empty value. */ value = next_token (value); len = strlen (value); if (len == 0) return; /* Allocate a vector that is definitely big enough. */ argv = alloca ((1 + len + 1) * sizeof (char *)); /* getopt will look at the arguments starting at ARGV[1]. Prepend a spacer word. */ argv[0] = 0; argc = 1; /* We need a buffer to copy the value into while we split it into words and unquote it. Set up in case we need to prepend a dash later. */ buf = alloca (1 + len + 1); buf[0] = '-'; p = buf+1; argv[argc] = p; while (*value != '\0') { if (*value == '\\' && value[1] != '\0') ++value; /* Skip the backslash. */ else if (isblank ((unsigned char)*value)) { /* End of the word. */ *p++ = '\0'; argv[++argc] = p; do ++value; while (isblank ((unsigned char)*value)); continue; } *p++ = *value++; } *p = '\0'; argv[++argc] = 0; assert (p < buf + len + 2); if (argv[1][0] != '-' && strchr (argv[1], '=') == 0) /* The first word doesn't start with a dash and isn't a variable definition, so add a dash. */ argv[1] = buf; /* Parse those words. */ decode_switches (argc, argv, 1); } /* Quote the string IN so that it will be interpreted as a single word with no magic by decode_env_switches; also double dollar signs to avoid variable expansion in make itself. Write the result into OUT, returning the address of the next character to be written. Allocating space for OUT twice the length of IN is always sufficient. */ static char * quote_for_env (char *out, const char *in) { while (*in != '\0') { if (*in == '$') *out++ = '$'; else if (isblank ((unsigned char)*in) || *in == '\\') *out++ = '\\'; *out++ = *in++; } return out; } /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the command switches. Include options with args if ALL is nonzero. Don't include options with the 'no_makefile' flag set if MAKEFILE. */ static struct variable * define_makeflags (int all, int makefile) { const char ref[] = "$(MAKEOVERRIDES)"; const char posixref[] = "$(-*-command-variables-*-)"; const char evalref[] = "$(-*-eval-flags-*-)"; const struct command_switch *cs; char *flagstring; char *p; /* We will construct a linked list of 'struct flag's describing all the flags which need to go in MAKEFLAGS. Then, once we know how many there are and their lengths, we can put them all together in a string. */ struct flag { struct flag *next; const struct command_switch *cs; const char *arg; }; struct flag *flags = 0; struct flag *last = 0; unsigned int flagslen = 0; #define ADD_FLAG(ARG, LEN) \ do { \ struct flag *new = alloca (sizeof (struct flag)); \ new->cs = cs; \ new->arg = (ARG); \ new->next = 0; \ if (! flags) \ flags = new; \ else \ last->next = new; \ last = new; \ if (new->arg == 0) \ /* Just a single flag letter: " -x" */ \ flagslen += 3; \ else \ /* " -xfoo", plus space to escape "foo". */ \ flagslen += 1 + 1 + 1 + (3 * (LEN)); \ if (!short_option (cs->c)) \ /* This switch has no single-letter version, so we use the long. */ \ flagslen += 2 + strlen (cs->long_name); \ } while (0) for (cs = switches; cs->c != '\0'; ++cs) if (cs->toenv && (!makefile || !cs->no_makefile)) switch (cs->type) { case ignore: break; case flag: case flag_off: if ((!*(int *) cs->value_ptr) == (cs->type == flag_off) && (cs->default_value == 0 || *(int *) cs->value_ptr != *(int *) cs->default_value)) if (cs->c != 'X') ADD_FLAG (0, 0); break; case positive_int: if (all) { if ((cs->default_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->default_value))) break; else if (cs->noarg_value != 0 && (*(unsigned int *) cs->value_ptr == *(unsigned int *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { char *buf = alloca (30); sprintf (buf, "%u", *(unsigned int *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #ifndef NO_FLOAT case floating: if (all) { if (cs->default_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->default_value)) break; else if (cs->noarg_value != 0 && (*(double *) cs->value_ptr == *(double *) cs->noarg_value)) ADD_FLAG ("", 0); /* Optional value omitted; see below. */ else { char *buf = alloca (100); sprintf (buf, "%g", *(double *) cs->value_ptr); ADD_FLAG (buf, strlen (buf)); } } break; #endif case string: if (all) { p = *((char **)cs->value_ptr); if (p) ADD_FLAG (p, strlen (p)); } break; case filename: case strlist: if (all) { struct stringlist *sl = *(struct stringlist **) cs->value_ptr; if (sl != 0) { unsigned int i; for (i = 0; i < sl->idx; ++i) ADD_FLAG (sl->list[i], strlen (sl->list[i])); } } break; default: abort (); } #undef ADD_FLAG /* Four more for the possible " -- ", plus variable references. */ flagslen += 4 + CSTRLEN (posixref) + 1 + CSTRLEN (evalref) + 1; /* Construct the value in FLAGSTRING. We allocate enough space for a preceding dash and trailing null. */ flagstring = alloca (1 + flagslen + 1); memset (flagstring, '\0', 1 + flagslen + 1); p = flagstring; /* Start with a dash, for MFLAGS. */ *p++ = '-'; /* Add simple options as a group. */ while (flags != 0 && !flags->arg && short_option (flags->cs->c)) { if (flags->cs->c != 'X') { *p++ = flags->cs->c; flags = flags->next; } } /* Now add more complex flags: ones with options and/or long names. */ while (flags) { *p++ = ' '; *p++ = '-'; /* Add the flag letter or name to the string. */ if (short_option (flags->cs->c)) { if (flags->cs->c != 'X') *p++ = flags->cs->c; } else { /* Long options require a double-dash. */ *p++ = '-'; strcpy (p, flags->cs->long_name); p += strlen (p); } /* An omitted optional argument has an ARG of "". */ if (flags->arg && flags->arg[0] != '\0') { if (!short_option (flags->cs->c)) /* Long options require '='. */ *p++ = '='; p = quote_for_env (p, flags->arg); } flags = flags->next; } /* If no flags at all, get rid of the initial dash. */ if (p == &flagstring[1]) { flagstring[0] = '\0'; p = flagstring; } /* Define MFLAGS before appending variable definitions. Omit an initial empty dash. Since MFLAGS is not parsed for flags, there is no reason to override any makefile redefinition. */ define_variable_cname ("MFLAGS", flagstring + (flagstring[0] == '-' && flagstring[1] == ' ' ? 2 : 0), o_env, 1); /* Write a reference to -*-eval-flags-*-, which contains all the --eval flag options. */ if (eval_strings) { *p++ = ' '; memcpy (p, evalref, CSTRLEN (evalref)); p += CSTRLEN (evalref); } if (all && command_variables) { /* Write a reference to $(MAKEOVERRIDES), which contains all the command-line variable definitions. Separate the variables from the switches with a "--" arg. */ strcpy (p, " -- "); p += 4; /* Copy in the string. */ if (posix_pedantic) { memcpy (p, posixref, CSTRLEN (posixref)); p += CSTRLEN (posixref); } else { memcpy (p, ref, CSTRLEN (ref)); p += CSTRLEN (ref); } } /* If there is a leading dash, omit it. */ if (flagstring[0] == '-') ++flagstring; /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS. Makefiles set MAKEFLAGS to add switches, but we still want to redefine its value with the full set of switches. Then we used o_file, but that lost when users added -e, causing a previous MAKEFLAGS env. var. to take precedence over the new one. Of course, an override or command definition will still take precedence. */ return define_variable_cname ("MAKEFLAGS", flagstring, env_overrides ? o_env_override : o_file, 1); } /* Print version information. */ static void print_version (void) { static int printed_version = 0; const char *precede = print_data_base_flag ? "# " : ""; if (printed_version) /* Do it only once. */ return; printf ("%sGNU Make %s\n", precede, version_string); if (!remote_description || *remote_description == '\0') printf (_("%sBuilt for %s\n"), precede, make_host); else printf (_("%sBuilt for %s (%s)\n"), precede, make_host, remote_description); /* Print this untranslated. The coding standards recommend translating the (C) to the copyright symbol, but this string is going to change every year, and none of the rest of it should be translated (including the word "Copyright"), so it hardly seems worth it. */ printf ("%sCopyright (C) 1988-2014 Free Software Foundation, Inc.\n" "Copyright (C) 2015 Rocky Bernstein.\n", precede); printf (_("%sLicense GPLv3+: GNU GPL version 3 or later \n\ %sThis is free software: you are free to change and redistribute it.\n\ %sThere is NO WARRANTY, to the extent permitted by law.\n"), precede, precede, precede); printed_version = 1; /* Flush stdout so the user doesn't have to wait to see the version information while make thinks about things. */ fflush (stdout); } /* Print a bunch of information about this and that. */ static void print_data_base () { time_t when = time ((time_t *) 0); print_version (); printf (_("\n# Make data base, printed on %s"), ctime (&when)); print_variable_data_base (); print_dir_data_base (); print_rule_data_base (true); print_file_data_base (); print_vpath_data_base (); strcache_print_stats ("#"); when = time ((time_t *) 0); printf (_("\n# Finished Make data base on %s\n"), ctime (&when)); } static void clean_jobserver (int status) { /* Sanity: have we written all our jobserver tokens back? If our exit status is 2 that means some kind of syntax error; we might not have written all our tokens so do that now. If tokens are left after any other error code, that's bad. */ #ifdef WINDOWS32 if (has_jobserver_semaphore () && jobserver_tokens) #else char token = '+'; if (job_fds[0] != -1 && jobserver_tokens) #endif { if (status != 2) ON (error, NILF, "INTERNAL: Exiting with %u jobserver tokens (should be 0)!", jobserver_tokens); else /* Don't write back the "free" token */ while (--jobserver_tokens) { #ifdef WINDOWS32 if (! release_jobserver_semaphore ()) perror_with_name ("release_jobserver_semaphore", ""); #else int r; EINTRLOOP (r, write (job_fds[1], &token, 1)); if (r != 1) perror_with_name ("write", ""); #endif } } /* Sanity: If we're the master, were all the tokens written back? */ if (master_job_slots) { /* We didn't write one for ourself, so start at 1. */ unsigned int tcnt = 1; #ifdef WINDOWS32 while (acquire_jobserver_semaphore ()) ++tcnt; #else /* Close the write side, so the read() won't hang. */ close (job_fds[1]); while (read (job_fds[0], &token, 1) == 1) ++tcnt; #endif if (tcnt != master_job_slots) ONN (error, NILF, "INTERNAL: Exiting with %u jobserver tokens available; should be %u!", tcnt, master_job_slots); #ifdef WINDOWS32 free_jobserver_semaphore (); #else close (job_fds[0]); #endif /* Clean out jobserver_fds so we don't pass this information to any sub-makes. Also reset job_slots since it will be put on the command line, not in MAKEFLAGS. */ job_slots = default_job_slots; free (jobserver_fds); jobserver_fds = 0; } } /* Exit with STATUS, cleaning up as necessary. */ void die (int status) { static char dying = 0; if (!dying) { int err; dying = 1; if (print_version_flag) print_version (); /* Wait for children to die. */ err = (status != 0); while (job_slots_used > 0) reap_children (1, err, NULL); /* Let the remote job module clean up its state. */ remote_cleanup (); /* Remove the intermediate files. */ remove_intermediates (0); if (print_data_base_flag) print_data_base (); if (verify_flag) verify_file_data_base (); clean_jobserver (status); if (output_context) { /* die() might be called in a recipe output context due to an $(error ...) function. */ output_close (output_context); if (output_context != &make_sync) output_close (&make_sync); OUTPUT_UNSET (); } output_close (NULL); /* Try to move back to the original directory. This is essential on MS-DOS (where there is really only one process), and on Unix it puts core files in the original directory instead of the -C directory. Must wait until after remove_intermediates(), or unlinks of relative pathnames fail. */ if (directory_before_chdir != 0) { /* If it fails we don't care: shut up GCC. */ int _x UNUSED; _x = chdir (directory_before_chdir); } } if (profile_flag) { const char *status_str; switch (status) { case MAKE_SUCCESS: status_str = "Normal program termination"; break; case MAKE_TROUBLE: status_str = "Platform failure termination"; break; case MAKE_FAILURE: status_str = "Failure program termination"; break; case DEBUGGER_QUIT_RC: status_str = "Debugger termination"; break; default: status_str = ""; } close_callgrind(status_str); } exit (status); } remake-4.1+dbg1.3~dfsg.1/main.h000077500000000000000000000030271317072305000160750ustar00rootroot00000000000000/* Copyright (C) 2011 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*! If nonzero, the basename of filenames is in giving locations. Normally, giving a file directory location helps a debugger frontend when we change directories. For regression tests it is helpful to list just the basename part as that doesn't change from installation to installation. Users may have their preferences too. */ extern int basename_filenames; /*! Nonzero means --trace=noshell. */ extern int no_shell_trace; /*! Nonzero means use GNU readline in the debugger. */ extern int use_readline_flag; /* is default_shell unixy? */ extern int unixy_shell; /**! The default value of SHELL and the shell that is used when issuing commands on targets. */ extern char *default_shell; /*! Print version information. */ extern void print_version (void); remake-4.1+dbg1.3~dfsg.1/maintMakefile000066400000000000000000000221701317072305000174660ustar00rootroot00000000000000# Maintainer-only makefile segment. This contains things that are relevant # only if you have the full copy of the GNU make sources from the CVS # tree, not a dist copy. # We like mondo-warnings! AM_CFLAGS += -Wall -Wextra -Wdeclaration-after-statement -Wshadow -Wpointer-arith -Wbad-function-cast MAKE_MAINTAINER_MODE := -DMAKE_MAINTAINER_MODE AM_CPPFLAGS += $(MAKE_MAINTAINER_MODE) # I want this one but I have to wait for the const cleanup! # -Wwrite-strings # Find the glob source files... this might be dangerous, but we're maintainers! globsrc := $(wildcard glob/*.c) globhdr := $(wildcard glob/*.h) TEMPLATES = README README.DOS README.W32 README.OS2 \ config.ami configh.dos config.h.W32 config.h-vms MTEMPLATES = Makefile.DOS SMakefile # These are built as a side-effect of the dist rule #all-am: $(TEMPLATES) $(MTEMPLATES) build.sh.in # General rule for turning a .template into a regular file. # $(TEMPLATES) : % : %.template Makefile rm -f $@ sed -e 's@%VERSION%@$(VERSION)@g' \ -e 's@%PACKAGE%@$(PACKAGE)@g' \ $< > $@ chmod a-w $@ # Construct Makefiles by adding on dependencies, etc. # $(MTEMPLATES) : % : %.template .dep_segment Makefile rm -f $@ sed -e 's@%VERSION%@$(VERSION)@g' \ -e 's@%PROGRAMS%@$(bin_PROGRAMS)@g' \ -e 's@%SOURCES%@$(filter-out remote-%,$(make_SOURCES)) remote-$$(REMOTE).c@g' \ -e 's@%OBJECTS%@$(filter-out remote-%,$(make_OBJECTS)) remote-$$(REMOTE).o@g' \ -e 's@%GLOB_SOURCES%@$(globsrc) $(globhdr)@g' \ -e 's@%GLOB_OBJECTS%@$(globsrc:glob/%.c=%.o)@g' \ $< > $@ echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \ cat $(word 2,$^) >>$@ chmod a-w $@ NMakefile: NMakefile.template .dep_segment Makefile rm -f $@ cp $< $@ echo >>$@; echo '# --------------- DEPENDENCIES' >>$@; echo '#' >>$@; \ sed 's/^\([^ ]*\)\.o:/$$(OUTDIR)\/\1.obj:/' $(word 2,$^) >>$@ chmod a-w $@ # Construct build.sh.in # build.sh.in: build.template Makefile rm -f $@ sed -e 's@%objs%@$(patsubst %.o,%.$${OBJEXT},$(filter-out remote-%,$(make_OBJECTS)))@g' \ -e 's@%globobjs%@$(patsubst %.c,%.$${OBJEXT},$(globsrc))@g' \ $< > $@ chmod a-w+x $@ # Use automake to build a dependency list file, for "foreign" makefiles like # Makefile.DOS. # # Automake used to have a --generate-deps flag, but it's gone now, so we have # to do it ourselves. # DEP_FILES := $(wildcard $(DEPDIR)/*.Po) .dep_segment: Makefile.am maintMakefile $(DEP_FILES) rm -f $@ (for f in $(DEPDIR)/*.Po; do \ echo ""; \ echo "# $$f"; \ sed -e '/^[^:]*\.[ch] *:/d' \ -e 's, /usr/[^ ]*,,g' \ -e 's, $(srcdir)/, ,g' \ -e '/^ *\\$$/d' \ -e '/^ *$$/d' \ < $$f; \ done) > $@ # Get rid of everything "else". # maintFILES = configure aclocal.m4 config.h.in Makefile.in stamp-h.in CVS-CLEAN-FILES += $(maintFILES) $(TEMPLATES) $(MTEMPLATES) NMakefile \ build.sh.in .deps .dep_segment ABOUT-NLS \ ansi2knr.* # This rule tries to clean the tree right down to how it looks when you do a # virgin CVS checkout. # This target is potentially dangerous since it removes _ANY FILE_ that # is not in CVS. Including files you might mean to add to CVS but # haven't yet... I only use this in subdirectories where it's unlikely # we have any new files. Still... be careful!! cvsclean = $(PERL) -e '$$k{CVS} = 1; open(E,"< CVS/Entries") || die "CVS/Entries: $$!\n"; while (defined ($$_ = )) { m%^/([^/]*)% or next; $$k{$$1} = 1; } close(E) || die "CVS/Entries: $$!\n"; opendir(D, ".") || die ".: $$!\n"; while (defined ($$_ = readdir(D))) { -f $$_ && ! exists $$k{$$_} && unlink($$_); } closedir(D) || die ".: $$!\n";' .PHONY: cvs-clean cvs-clean: maintainer-clean -rm -rf *~ $(CVS-CLEAN-FILES) -cd config && $(cvsclean) -cd po && $(cvsclean) -cd doc && $(cvsclean) -cd glob && $(cvsclean) # ---------------------------------------------------------------------- # # The sections below were stolen from the Makefile.maint used by fileutils, # sh-utils, textutils, CPPI, Bison, and Autoconf. ## ---------------- ## ## Updating files. ## ## ---------------- ## WGET = wget --passive-ftp -nv ftp-gnu = ftp://ftp.gnu.org/gnu move_if_change = if test -r $(target) && cmp -s $(target).t $(target); then \ echo $(target) is unchanged; rm -f $(target).t; \ else \ mv $(target).t $(target); \ fi # ------------------- # # Updating PO files. # # ------------------- # # PO archive mirrors --- Be careful; some might not be fully populated! # ftp://ftp.unex.es/pub/gnu-i18n/po/maint/ # http://translation.sf.net/maint/ # ftp://tiger.informatik.hu-berlin.de/pub/po/maint/ po_wget_flags = --recursive --level=1 --no-directories --no-parent \ --no-check-certificate po_repo = http://translationproject.org/latest/make .PHONY: do-po-update po-update do-po-update: tmppo="/tmp/po-$(PACKAGE)-$(VERSION).$$$$" \ && rm -rf "$$tmppo" \ && mkdir "$$tmppo" \ && (cd "$$tmppo" \ && $(WGET) $(po_wget_flags) -A '*.po' $(po_repo)) \ && cp "$$tmppo"/*.po $(top_srcdir)/po && rm -rf "$$tmppo" cd po && $(MAKE) update-po $(MAKE) po-check po-update: [ -d "po" ] && $(MAKE) do-po-update # -------------------------- # # Updating GNU build files. # # -------------------------- # # The following pseudo table associates a local directory and a URL # with each of the files that belongs to some other package and is # regularly updated from the specified URL. cvs-url = http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~ git-url = http://git.savannah.gnu.org/cgit target = $(patsubst get-%,%,$@) config-url = $(git-url)/config.git/plain/$(patsubst get-config/%,%,$@) get-config/config.guess get-config/config.sub: @echo $(WGET) $(config-url) -O $(target) \ && $(WGET) $(config-url) -O $(target).t \ && $(move_if_change) gnulib-url = $(git-url)/gnulib.git/plain/build-aux/$(patsubst get-config/%,%,$@) get-config/texinfo.tex: @echo $(WGET) $(gnulib-url) -O $(target) \ && $(WGET) $(gnulib-url) -O $(target).t \ && $(move_if_change) gnustandards-url = $(cvs-url)/gnustandards/gnustandards/$(patsubst get-doc/%,%,$@) get-doc/make-stds.texi get-doc/fdl.texi: @echo $(WGET) $(gnustandards-url) -O $(target) \ && $(WGET) $(gnustandards-url) -O $(target).t \ && $(move_if_change) .PHONY: scm-update scm-update: get-config/texinfo.tex get-config/config.guess get-config/config.sub get-doc/make-stds.texi get-doc/fdl.texi # --------------------- # # Updating everything. # # --------------------- # .PHONY: update update: po-update scm-update ## --------------- ## ## Sanity checks. ## ## --------------- ## # Checks that don't require cvs. Run `changelog-check' last as # previous test may reveal problems requiring new ChangeLog entries. local-check: po-check changelog-check # copyright-check writable-files changelog-check: if head $(top_srcdir)/ChangeLog | grep 'Version $(VERSION)' >/dev/null; then \ :; \ else \ echo "$(VERSION) not in ChangeLog" 1>&2; \ exit 1; \ fi # Verify that all source files using _() are listed in po/POTFILES.in. # Ignore make.h; it defines _(). po-check: if test -f po/POTFILES.in; then \ grep '^[^#]' po/POTFILES.in | sort > $@-1; \ $(PERL) -wn -e 'if (/\b_\(/) { $$ARGV eq "make.h" || print "$$ARGV\n" and close ARGV }' *.c *.h | sort > $@-2; \ diff -u $@-1 $@-2 || exit 1; \ rm -f $@-1 $@-2; \ fi ## ------------------------- ## ## GNU FTP upload artifacts. ## ## ------------------------- ## # This target creates the upload artifacts. # Sign it with my key. If you don't have my key/passphrase then sorry, # you're SOL! :) GPG = gpg GPGFLAGS = -u 6338B6D4 DIST_ARCHIVES_SIG = $(addsuffix .sig,$(DIST_ARCHIVES)) DIST_ARCHIVES_DIRECTIVE = $(addsuffix .directive.asc,$(DIST_ARCHIVES)) # A simple rule to test signing, etc. .PHONY: distsign distsign: $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE) %.sig : % @echo "Signing file '$<':" $(GPG) $(GPGFLAGS) -o "$@" -b "$<" %.directive.asc: % @echo "Creating directive file '$@':" @( \ echo 'version: 1.1'; \ echo 'directory: make'; \ echo 'filename: $*'; \ echo 'comment: Official upload of GNU make version $(VERSION)'; \ ) > "$*.directive" $(GPG) $(GPGFLAGS) -o "$@" --clearsign "$*.directive" @rm -f "$*.directive" # Upload the artifacts FTPPUT = ncftpput gnu-upload-host = ftp-upload.gnu.org gnu-upload-dir = /incoming UPLOADS = upload-alpha upload-ftp .PHONY: $(UPLOADS) $(UPLOADS): $(DIST_ARCHIVES) $(DIST_ARCHIVES_SIG) $(DIST_ARCHIVES_DIRECTIVE) $(FTPPUT) "$(gnu-upload-host)" "$(gnu-upload-dir)/$(@:upload-%=%)" $^ # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/make.1000066400000000000000000000302221317072305000157710ustar00rootroot00000000000000.TH REMAKE 1 "03 March 2016" "GNU" "User Commands" .SH NAME remake \- GNU make utility with enhanced debugger .SH SYNOPSIS .B make [\fIOPTION\fR]... [\fITARGET\fR]... .SH DESCRIPTION .LP The .I make utility will determine automatically which pieces of a large program need to be recompiled, and issue the commands to recompile them. The manual describes the GNU implementation of .BR make , which was written by Richard Stallman and Roland McGrath, and is currently maintained by Paul Smith. Extended error reporting, debugger, and profiling extensions were written by Rocky Bernstein. Our examples show C programs, since they are very common, but you can use .B make with any programming language whose compiler can be run with a shell command. In fact, .B make is not limited to programs. You can use it to describe any task where some files must be updated automatically from others whenever the others change. .LP To prepare to use .BR make , you must write a file called the .I makefile that describes the relationships among files in your program, and the states the commands for updating each file. In a program, typically the executable file is updated from object files, which are in turn made by compiling source files. .LP Once a suitable makefile exists, each time you change some source files, this simple shell command: .sp 1 .RS .B make .RE .sp 1 suffices to perform all necessary recompilations. The .B make program uses the makefile description and the last-modification times of the files to decide which of the files need to be updated. For each of those files, it issues the commands recorded in the makefile. .LP .B make executes commands in the .I makefile to update one or more target .IR names , where .I name is typically a program. If no .B \-f option is present, .B make will look for the makefiles .IR GNUmakefile , .IR makefile , and .IR Makefile , in that order. .LP Normally you should call your makefile either .I makefile or .IR Makefile . (We recommend .I Makefile because it appears prominently near the beginning of a directory listing, right near other important files such as .IR README .) The first name checked, .IR GNUmakefile , is not recommended for most makefiles. You should use this name if you have a makefile that is specific to GNU .BR make , and will not be understood by other versions of .BR make . If .I makefile is '\-', the standard input is read. .LP .B make updates a target if it depends on prerequisite files that have been modified since the target was last modified, or if the target does not exist. .SH OPTIONS .sp 1 .TP 0.5i \fB\-b\fR, \fB\-m\fR These options are ignored for compatibility with other versions of .BR make . .TP 0.5i \fB\-B\fR, \fB\-\-always\-make\fR Unconditionally make all targets. .TP 0.5i \fB\-C\fR \fIdir\fR, \fB\-\-directory\fR=\fIdir\fR Change to directory .I dir before reading the makefiles or doing anything else. If multiple .B \-C options are specified, each is interpreted relative to the previous one: .BR "\-C " / .BR "\-C " etc is equivalent to .BR "\-C " /etc. This is typically used with recursive invocations of .BR make . .TP 0.5i .B \-d Print debugging information in addition to normal processing. The debugging information says which files are being considered for remaking, which file-times are being compared and with what results, which files actually need to be remade, which implicit rules are considered and which are applied---everything interesting about how .B make decides what to do. .TP 0.5i .BR "\-\-profile" Creates callgrind profile output. Callgrind output can be used with kcachegrind, callgrind_annotate, or gprof2dot to analyze data. You can get not only timings, but a graph of the target dependencies checked .TP 0.5i .BR "\-\-targets" Print a list of explicitly named targets found in read-in makefiles. .TP 0.5i .BR \-\-tasks Print a list of explicitly named targets found in read-in makefiles which have commands associated with them and are either phony or are not implicit. .TP 0.5i .BI \-\-debug "[=FLAGS]" Print debugging information in addition to normal processing. If the .I FLAGS are omitted, then the behavior is the same as if .B \-d was specified. .I FLAGS may be .I a for all debugging output (same as using .BR \-d ), .I b for basic debugging, .I v for more verbose basic debugging, .I i for showing implicit rules, .I j for details on invocation of commands, and .I m for debugging while remaking makefiles. Use .I n to disable all previous debugging flags. .TP 0.5i .B \-x, " \-\-trace" Print trace information. Commands in rules which are normally silent are shown, same as if \fB\-\-just\-print\fR were given. .TP 0.5i .BI \-\-trace "[=FLAGS]" Set trace flags If the .I FLAGS are omitted, then the behavior is the same as if .B \-d was specified. .I FLAGS may be .I read for all tracing Makefiles, .I noshell which is like \fInormal\fR but shell tracing is disabled, or .I full for maximum tracing. .TP 0.5i .B \-X, " \-\-debugger" Enter debugger .TP 0.5i .BI \-\-debugger "[=TYPE]" Enter debugger with If the .I TYPE are omitted, then the behavior is the same as if .B \-X was specified. .I TYPE may be .I goal for all tracing Makefiles read .BR \-d ), .I preread which is the same as given no option .I preaction which is like \fInormal\fR but shell tracing is disabled .I full for maximum tracing. .I fatal for entering the debugger on a fatal error, .I error for entering the debugger on an error .TP 0.5i \fB\-e\fR, \fB\-\-environment\-overrides\fR Give variables taken from the environment precedence over variables from makefiles. .TP 0.5i \fB\-f\fR \fIfile\fR, \fB\-\-file\fR=\fIfile\fR, \fB\-\-makefile\fR=\fIFILE\fR Use .I file as a makefile. .TP 0.5i \fB\-i\fR, \fB\-\-ignore\-errors\fR Ignore all errors in commands executed to remake files. .TP 0.5i \fB\-I\fR \fIdir\fR, \fB\-\-include\-dir\fR=\fIdir\fR Specifies a directory .I dir to search for included makefiles. If several .B \-I options are used to specify several directories, the directories are searched in the order specified. Unlike the arguments to other flags of .BR make , directories given with .B \-I flags may come directly after the flag: .BI \-I dir is allowed, as well as .B \-I .IR dir . This syntax is allowed for compatibility with the C preprocessor's .B \-I flag. .TP 0.5i \fB\-j\fR [\fIjobs\fR], \fB\-\-jobs\fR[=\fIjobs\fR] Specifies the number of .I jobs (commands) to run simultaneously. If there is more than one .B \-j option, the last one is effective. If the .B \-j option is given without an argument, .BR make will not limit the number of jobs that can run simultaneously. .TP 0.5i \fB\-k\fR, \fB\-\-keep\-going\fR Continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same. .TP 0.5i \fB\-l\fR [\fIload\fR], \fB\-\-load\-average\fR[=\fIload\fR] Specifies that no new jobs (commands) should be started if there are others jobs running and the load average is at least .I load (a floating-point number). With no argument, removes a previous load limit. .TP 0.5i \fB\-L\fR, \fB\-\-check\-symlink\-times\fR Use the latest mtime between symlinks and target. .TP 0.5i \fB\-n\fR, \fB\-\-just\-print\fR, \fB\-\-dry\-run\fR, \fB\-\-recon\fR Print the commands that would be executed, but do not execute them (except in certain circumstances). .TP 0.5i \fB\-o\fR \fIfile\fR, \fB\-\-old\-file\fR=\fIfile\fR, \fB\-\-assume\-old\fR=\fIfile\fR Do not remake the file .I file even if it is older than its dependencies, and do not remake anything on account of changes in .IR file . Essentially the file is treated as very old and its rules are ignored. .TP 0.5i \fB\-O\fR[\fItype\fR], \fB\-\-output\-sync\fR[=\fItype\fR] When running multiple jobs in parallel with \fB-j\fR, ensure the output of each job is collected together rather than interspersed with output from other jobs. If .I type is not specified or is .B target the output from the entire recipe for each target is grouped together. If .I type is .B line the output from each command line within a recipe is grouped together. If .I type is .B recurse output from an entire recursive make is grouped together. If .I type is .B none output synchronization is disabled. .TP 0.5i \fB\-p\fR, \fB\-\-print\-data\-base\fR Print the data base (rules and variable values) that results from reading the makefiles; then execute as usual or as otherwise specified. This also prints the version information given by the .B \-v switch (see below). To print the data base without trying to remake any files, use .IR "make \-p \-f/dev/null" . .TP 0.5i \fB\-q\fR, \fB\-\-question\fR ``Question mode''. Do not run any commands, or print anything; just return an exit status that is zero if the specified targets are already up to date, nonzero otherwise. .TP 0.5i \fB\-r\fR, \fB\-\-no\-builtin\-rules\fR Eliminate use of the built\-in implicit rules. Also clear out the default list of suffixes for suffix rules. .TP 0.5i \fB\-R\fR, \fB\-\-no\-builtin\-variables\fR Don't define any built\-in variables. .TP 0.5i \fB\-s\fR, \fB\-\-silent\fR, \fB\-\-quiet\fR Silent operation; do not print the commands as they are executed. .TP 0.5i \fB\-S\fR, \fB\-\-no\-keep\-going\fR, \fB\-\-stop\fR Cancel the effect of the .B \-k option. This is never necessary except in a recursive .B make where .B \-k might be inherited from the top-level .B make via MAKEFLAGS or if you set .B \-k in MAKEFLAGS in your environment. .TP 0.5i \fB\-t\fR, \fB\-\-touch\fR Touch files (mark them up to date without really changing them) instead of running their commands. This is used to pretend that the commands were done, in order to fool future invocations of .BR make . .TP 0.5i \fB\-v\fR, \fB\-\-version\fR Print the version of the .B make program plus a copyright, a list of authors and a notice that there is no warranty. .TP 0.5i \fB\-w\fR, \fB\-\-print\-directory\fR Print a message containing the working directory before and after other processing. This may be useful for tracking down errors from complicated nests of recursive .B make commands. .TP 0.5i .B \-\-no\-print\-directory Turn off .BR \-w , even if it was turned on implicitly. .TP 0.5i \fB\-W\fR \fIfile\fR, \fB\-\-what\-if\fR=\fIfile\fR, \fB\-\-new\-file\fR=\fIfile\fR, \fB\-\-assume\-new\fR=\fIfile\fR Pretend that the target .I file has just been modified. When used with the .B \-n flag, this shows you what would happen if you were to modify that file. Without .BR \-n , it is almost the same as running a .I touch command on the given file before running .BR make , except that the modification time is changed only in the imagination of .BR make . .TP 0.5i .B \-\-warn\-undefined\-variables Warn when an undefined variable is referenced. .SH "EXIT STATUS" GNU .B make exits with a status of zero if all makefiles were successfully parsed and no targets that were built failed. A status of one will be returned if the .B \-q flag was used and .B make determines that a target needs to be rebuilt. A status of two will be returned if any errors were encountered. .SH "SEE ALSO" The full documentation for .B make is maintained as a Texinfo manual. If the .B info and .B make programs are properly installed at your site, the command .IP .B info make .PP should give you access to the complete manual. .SH BUGS See the chapter ``Problems and Bugs'' in .IR "The GNU Make Manual" . .SH AUTHORS This manual page contributed by Dennis Morse of Stanford University. Further updates contributed by Mike Frysinger. It has been reworked by Roland McGrath. Maintained by Paul Smith. Remake-specific changes by Rocky Bernstein .SH "COPYRIGHT" Copyright \(co 1992-1993, 1996-2014 Free Software Foundation, Inc. This file is part of .IR "GNU make" . .LP GNU Make is free software; you can 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. .LP GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. .LP You should have received a copy of the GNU General Public License along with this program. If not, see .IR http://www.gnu.org/licenses/ . remake-4.1+dbg1.3~dfsg.1/make.h000066400000000000000000000356541317072305000160760ustar00rootroot00000000000000/* Miscellaneous global declarations and portability cruft for GNU Make. Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because make.h was found in $srcdir). */ #ifndef MAKE_H #define MAKE_H #include #undef HAVE_CONFIG_H #define HAVE_CONFIG_H 1 /* Specify we want GNU source code. This must be defined before any system headers are included. */ #define _GNU_SOURCE 1 /* AIX requires this to be the first thing in the file. */ #if HAVE_ALLOCA_H # include #else # ifdef _AIX #pragma alloca # else # if !defined(__GNUC__) && !defined(WINDOWS32) # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif #ifdef CRAY /* This must happen before #include so that the declaration therein is changed. */ # define signal bsdsignal #endif /* If we're compiling for the dmalloc debugger, turn off string inlining. */ #if defined(HAVE_DMALLOC_H) && defined(__GNUC__) # define __NO_STRING_INLINES #endif #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H /* SCO 3.2 "devsys 4.2" has a prototype for `ftime' in that bombs unless has been included first. Does every system have a ? If any does not, configure should check for it. */ # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #ifndef errno extern int errno; #endif #ifndef isblank # define isblank(c) ((c) == ' ' || (c) == '\t') #endif #ifdef HAVE_UNISTD_H # include /* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get POSIX.1 behavior with `cc -YPOSIX', which predefines POSIX itself! */ # if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS) # define POSIX 1 # endif #endif /* Some systems define _POSIX_VERSION but are not really POSIX.1. */ #if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386))) # undef POSIX #endif #if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE) # define POSIX 1 #endif #ifndef RETSIGTYPE # define RETSIGTYPE void #endif #ifndef sigmask # define sigmask(sig) (1 << ((sig) - 1)) #endif #ifndef HAVE_SA_RESTART # define SA_RESTART 0 #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifndef PATH_MAX # ifndef POSIX # define PATH_MAX MAXPATHLEN # endif #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif #ifdef PATH_MAX # define GET_PATH_MAX PATH_MAX # define PATH_VAR(var) char var[PATH_MAX] #else # define NEED_GET_PATH_MAX 1 # define GET_PATH_MAX (get_path_max ()) # define PATH_VAR(var) char *var = alloca (GET_PATH_MAX) unsigned int get_path_max (void); #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif /* The minimum and maximum values for the integer type T. Use ~ (t) 0, not -1, for portability to 1's complement hosts. */ #define INTEGER_TYPE_MINIMUM(t) \ (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)) #define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t)) #ifndef CHAR_MAX # define CHAR_MAX INTEGER_TYPE_MAXIMUM (char) #endif #ifdef STAT_MACROS_BROKEN # ifdef S_ISREG # undef S_ISREG # endif # ifdef S_ISDIR # undef S_ISDIR # endif #endif /* STAT_MACROS_BROKEN. */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifdef VMS # include # include # include # include /* Needed to use alloca on VMS. */ # include #endif #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of `format' and `printf' attributes are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #define UNUSED __attribute__ ((unused)) #if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) # include # include # define ANSI_STRING 1 #else /* No standard headers. */ # ifdef HAVE_STRING_H # include # define ANSI_STRING 1 # else # include # endif # ifdef HAVE_MEMORY_H # include # endif # ifdef HAVE_STDLIB_H # include # else void *malloc (int); void *realloc (void *, int); void free (void *); void abort (void) __attribute__ ((noreturn)); void exit (int) __attribute__ ((noreturn)); # endif /* HAVE_STDLIB_H. */ #endif /* Standard headers. */ /* These should be in stdlib.h. Make sure we have them. */ #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef ANSI_STRING /* SCO Xenix has a buggy macro definition in . */ #undef strerror #if !defined(__DECC) char *strerror (int errnum); #endif #endif /* !ANSI_STRING. */ #undef ANSI_STRING #if HAVE_INTTYPES_H # include #endif #define FILE_TIMESTAMP uintmax_t #if !defined(HAVE_STRSIGNAL) char *strsignal (int signum); #endif /* Test if two strings are equal. Is this worthwhile? Should be profiled. */ #define streq(a, b) \ ((a) == (b) || \ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) /* Test if two strings are equal, but match case-insensitively on systems which have case-insensitive filesystems. Should only be used for filenames! */ #ifdef HAVE_CASE_INSENSITIVE_FS # define patheq(a, b) \ ((a) == (b) \ || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1)))) #else # define patheq(a, b) streq(a, b) #endif #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) #if defined(__GNUC__) || defined(ENUM_BITFIELDS) # define ENUM_BITFIELD(bits) :bits #else # define ENUM_BITFIELD(bits) #endif /* Handle gettext and locales. */ #if HAVE_LOCALE_H # include #else # define setlocale(category, locale) #endif #include #define _(msgid) gettext (msgid) #define N_(msgid) gettext_noop (msgid) #define S_(msg1,msg2,num) ngettext (msg1,msg2,num) /* Handle other OSs. */ #ifndef PATH_SEPARATOR_CHAR # if defined(HAVE_DOS_PATHS) # define PATH_SEPARATOR_CHAR ';' # elif defined(VMS) # define PATH_SEPARATOR_CHAR ',' # else # define PATH_SEPARATOR_CHAR ':' # endif #endif /* This is needed for getcwd() and chdir(), on some W32 systems. */ #if defined(HAVE_DIRECT_H) # include #endif #ifdef WINDOWS32 # include # include # define pipe(_p) _pipe((_p), 512, O_BINARY) # define kill(_pid,_sig) w32_kill((_pid),(_sig)) void sync_Path_environment (void); int w32_kill (pid_t pid, int sig); char *end_of_token_w32 (const char *s, char stopchar); int find_and_set_default_shell (const char *token); /* indicates whether or not we have Bourne shell */ extern int no_default_sh_exe; /* is default_shell unixy? */ extern int unixy_shell; #endif /* WINDOWS32 */ #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include struct rlimit stack_limit; #endif /* We have to have stdarg.h or varargs.h AND v*printf or doprnt to use variadic versions of these functions. */ #if HAVE_STDARG_H || HAVE_VARARGS_H # if HAVE_VPRINTF || HAVE_DOPRNT # define USE_VARIADIC 1 # endif #endif void die (int); void pfatal_with_name (const char *); void perror_with_name (const char *, const char *); void *xmalloc (unsigned int); void *xcalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); char *xstrndup (const char *, unsigned int); char *find_next_token (const char **, unsigned int *); char *next_token (const char *); char *end_of_token (const char *); void collapse_continuations (char *); char *lindex (const char *, const char *, int); int alpha_compare (const void *, const void *); void print_spaces (unsigned int); char *find_percent (char *); const char *find_percent_cached (const char **); FILE *open_tmpfile (char **, const char *); #ifndef NO_ARCHIVES int ar_name (const char *); void ar_parse_name (const char *, char **, char **); int ar_touch (const char *); int ar_member_date (const char *, time_t *); #endif int dir_file_exists_p (const char *, const char *); int file_exists_p (const char *); int file_impossible_p (const char *); void file_impossible (const char *); const char *dir_name (const char *); void hash_init_directories (void); void define_default_variables (void); void set_default_suffixes (void); void install_default_suffix_rules (void); void install_default_implicit_rules (void); void build_vpath_lists (void); void construct_vpath_list (char *pattern, char *dirpath); const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index); int gpath_search (const char *file, unsigned int len); /*! Construct the list of include directories from the arguments and the default list. */ extern void construct_include_path (const char **arg_dirs); void user_access (void); void make_access (void); void child_access (void); char *strip_whitespace (const char **begpp, const char **endpp); /* String caching */ void strcache_init (void); void strcache_print_stats (const char *prefix); int strcache_iscached (const char *str); const char *strcache_add (const char *str); #ifdef HAVE_VFORK_H # include #endif /* We omit these declarations on non-POSIX systems which define _POSIX_VERSION, because such systems often declare them in header files anyway. */ #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32) long int atol (); # ifndef VMS long int lseek (); # endif #endif /* Not GNU C library or POSIX. */ #ifdef HAVE_GETCWD # if !defined(VMS) && !defined(__DECC) char *getcwd (); # endif #else char *getwd (); # define getcwd(buf, len) getwd (buf) #endif #if !HAVE_STRCASECMP # if HAVE_STRICMP # define strcasecmp stricmp # elif HAVE_STRCMPI # define strcasecmp strcmpi # else /* Create our own, in misc.c */ int strcasecmp (const char *s1, const char *s2); # endif #endif #if !HAVE_STRNCASECMP # if HAVE_STRNICMP # define strncasecmp strnicmp # elif HAVE_STRNCMPI # define strncasecmp strncmpi # else /* Create our own, in misc.c */ int strncasecmp (const char *s1, const char *s2, int n); # endif #endif extern char **environ; extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, posix_pedantic, not_parallel; extern int second_expansion, clock_skew_detected, rebuilding_makefiles; extern int one_shell; /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; /* Resetting the command script introduction prefix character. */ #define RECIPEPREFIX_NAME ".RECIPEPREFIX" #define RECIPEPREFIX_DEFAULT '\t' extern char cmd_prefix; extern unsigned int job_slots; extern int job_fds[2]; extern int job_rfd; #ifndef NO_FLOAT extern double max_load_average; #else extern int max_load_average; #endif /*! Value of argv[0] which seems to get modified. Can we merge this with program below? */ extern char *argv0; /*! Our initial arguments -- used for debugger restart execvp. */ extern const char * const *global_argv; extern char *starting_directory; /*! Our current directory before processing any -C options. */ extern char *directory_before_chdir; /*! Value of the MAKELEVEL variable at startup (or 0). */ extern unsigned int makelevel; extern char *version_string, *remote_description, *make_host; extern unsigned int commands_started; extern int handling_fatal_signal; #ifndef MIN #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif #ifndef MAX #define MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) #endif /* Set up heap debugging library dmalloc. */ #ifdef HAVE_DMALLOC_H #include #endif #ifndef initialize_main # ifdef __EMX__ # define initialize_main(pargc, pargv) \ { _wildcard(pargc, pargv); _response(pargc, pargv); } # else # define initialize_main(pargc, pargv) # endif #endif #ifdef __EMX__ # if !defined chdir # define chdir _chdir2 # endif # if !defined getcwd # define getcwd _getcwd2 # endif /* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of chdir() and getcwd(). This avoids some error messages for the make testsuite but restricts the drive letter support. */ # ifdef NO_CHDIR2 # warning NO_CHDIR2: usage of drive letters restricted # undef chdir # undef getcwd # endif #endif #ifndef initialize_main # define initialize_main(pargc, pargv) #endif /* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag properly according to POSIX. So, we try to wrap common system calls with checks for EINTR. Note that there are still plenty of system calls that can fail with EINTR but this, reportedly, gets the vast majority of failure cases. If you still experience failures you'll need to either get a system where SA_RESTART works, or you need to avoid -j. */ #define EINTRLOOP(_v,_c) while (((_v)=_c)==-1 && errno==EINTR) /* While system calls that return integers are pretty consistent about returning -1 on failure and setting errno in that case, functions that return pointers are not always so well behaved. Sometimes they return NULL for expected behavior: one good example is readdir() which returns NULL at the end of the directory--and _doesn't_ reset errno. So, we have to do it ourselves here. */ #endif /*MAKE_H*/ remake-4.1+dbg1.3~dfsg.1/make.lnk000066400000000000000000000005641317072305000164230ustar00rootroot00000000000000FROM LIB:cres.o "commands.o"+"job.o"+"dir.o"+"file.o"+"misc.o"+"main.o"+"read.o"+"remake.o"+"rule.o"+"implicit.o"+"default.o"+"variable.o"+"expand.o"+"function.o"+"vpath.o"+"version.o"+"ar.o"+"arscan.o"+"signame.o"+"remote-stub.o"+"getopt.o"+"getopt1.o"+"alloca.o"+"amiga.o"+"hash.o"+"strcache.o"+"output.o" TO "make.new" LIB glob/glob.lib LIB:sc.lib LIB:amiga.lib QUIET remake-4.1+dbg1.3~dfsg.1/make_msvc_net2003.sln000066400000000000000000000016331317072305000206340ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_msvc.net2003", "make_msvc_net2003.vcproj", "{E96B5060-3240-4723-91C9-E64F1C877A04}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.ActiveCfg = Debug|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Debug.Build.0 = Debug|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.ActiveCfg = Release|Win32 {E96B5060-3240-4723-91C9-E64F1C877A04}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal remake-4.1+dbg1.3~dfsg.1/make_msvc_net2003.vcproj000066400000000000000000000166711317072305000213530ustar00rootroot00000000000000 remake-4.1+dbg1.3~dfsg.1/makefile.com000066400000000000000000000114011317072305000172450ustar00rootroot00000000000000$! $! Makefile.com - builds GNU Make for VMS $! $! P1 = LIST will provide compiler listings. $! P2 = DEBUG will build an image with debug information $! P3 = WALL will enable all warning messages (some are suppressed since $! one macro intentionally causes an error condition) $! $! In case of problems with the install you might contact me at $! zinser@decus.de (preferred) or zinser@sysdev.deutsche-boerse.com $ $! hb $! But don't ask Martin Zinser about the lines, I added/changed. $! In case of an error do some cleanup $ on error then $ goto cleanup $! in case somebody set up her/his own symbol for cc $ set symbol/scope=(nolocal,noglobal) $! $! Just some general constants... $! $ true = 1 $ false = 0 $ tmpnam = "temp_" + f$getjpi("","pid") $ tt = tmpnam + ".txt" $ tc = tmpnam + ".c" $! $! Look for the compiler used $! $ lval = "" $ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" $ then $ if f$trnlnm("SYS").eqs."" then def/nolog sys sys$library: $ ccopt = "" $ else $ ccopt = "/decc/prefix=(all,except=(globfree,glob))" $ if f$trnlnm("SYS").eqs."" $ then $ if f$trnlnm("DECC$LIBRARY_INCLUDE").nes."" $ then $ define sys decc$library_include: $ else $ if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]DECC$RTLDEF.DIR").nes."" - then lval = "SYS$COMMON:[DECC$LIB.REFERENCE.DECC$RTLDEF]," $ if f$search("SYS$COMMON:[DECC$LIB.REFERENCE]SYS$STARLET_C.DIR").nes."" - then lval = lval+"SYS$COMMON:[DECC$LIB.REFERENCE.SYS$STARLET_C]," $ lval=lval+"SYS$LIBRARY:" $ define sys 'lval $ endif $ endif $ endif $! $! $ if (p1 .eqs. "LIST") $ then $ ccopt = ccopt + "/list/show=(expan,inclu)" $ endif $! $! Should we build a debug image $! $ if (p2.eqs."DEBUG") $ then $ ccopt = ccopt + "/noopt/debug" $ lopt = "/debug" $ else $ lopt = "" $ endif $! $! Do we want to see all warnings $! $ if (p3.nes."WALL") $ then $ gosub check_cc_qual $ endif $ filelist = "alloca ar arscan commands default dir expand file function " + - "guile hash implicit job load main misc read remake " + - "remote-stub rule output signame variable version " + - "vmsfunctions vmsify vpath " + - "[.glob]glob [.glob]fnmatch getopt1 getopt strcache" $! $ copy config.h-vms config.h $ n=0 $ open/write optf make.opt $ loop: $ cfile = f$elem(n," ",filelist) $ if cfile .eqs. " " then goto linkit $ write sys$output "Compiling ''cfile'..." $ call compileit 'cfile' $ n = n + 1 $ goto loop $ linkit: $ close optf $ link/exe=make make.opt/opt'lopt $ goto cleanup $ $ cleanup: $ if f$trnlnm("SYS").nes."" then $ deassign sys $ if f$trnlnm("OPTF").nes."" then $ close optf $ if f$search("make.opt").nes."" then $ del make.opt;* $ exit $! $!----------------------------------------------------------------------------- $! $! Check if this is a define relating to the properties of the C/C++ $! compiler $! $CHECK_CC_QUAL: $ open/write tmpc 'tc $ ccqual = "/warn=(disable=questcompare)" $ write tmpc "#include " $ write tmpc "unsigned int i = 1;" $ write tmpc "int main(){" $ write tmpc "if (i < 0){printf(""Mission impossible\n"");}}" $ close tmpc $ gosub cc_qual_check $ return $! $!----------------------------------------------------------------------------- $! $! Check for properties of C/C++ compiler $! $CC_QUAL_CHECK: $ cc_qual = false $ set message/nofac/noident/nosever/notext $ cc 'ccqual' 'tmpnam' $ if $status then cc_qual = true $ set message/fac/ident/sever/text $ delete/nolog 'tmpnam'.*;* $ if cc_qual then ccopt = ccopt + ccqual $ return $!----------------------------------------------------------------------------- $! $ compileit : subroutine $ ploc = f$locate("]",p1) $ if ploc .lt. f$length(p1) $ then $ objdir = f$extract(0, ploc+1, p1) $ write optf p1 $ else $ objdir := [] $ write optf objdir+p1 $ endif $ cc'ccopt'/include=([],[.glob])/obj='objdir' - /define=("allocated_variable_expand_for_file=alloc_var_expand_for_file","unlink=remove","HAVE_CONFIG_H","VMS") - 'p1' $ exit $ endsubroutine : compileit $! $!----------------------------------------------------------------------------- $!Copyright (C) 1996-2014 Free Software Foundation, Inc. $!This file is part of GNU Make. $! $!GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY $!WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS $!FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/makeint.h000066400000000000000000000505231317072305000166010ustar00rootroot00000000000000/* Miscellaneous global declarations and portability cruft for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because makeint.h was found in $srcdir). */ #ifndef REMAKE_MAKEINT_H #define REMAKE_MAKEINT_H #include #undef HAVE_CONFIG_H #define HAVE_CONFIG_H 1 /* Specify we want GNU source code. This must be defined before any system headers are included. */ #define _GNU_SOURCE 1 /* AIX requires this to be the first thing in the file. */ #if HAVE_ALLOCA_H # include #else # ifdef _AIX #pragma alloca # else # if !defined(__GNUC__) && !defined(WINDOWS32) # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #endif /* Disable assert() unless we're a maintainer. Some asserts are compute-intensive. */ #ifndef MAKE_MAINTAINER_MODE # define NDEBUG 1 #endif /* Include the externally-visible content. Be sure to use the local one, and not one installed on the system. Define GMK_BUILDING_MAKE for proper selection of dllexport/dllimport declarations for MS-Windows. */ #ifdef WINDOWS32 # define GMK_BUILDING_MAKE #endif #include "gnumake.h" #ifdef CRAY /* This must happen before #include so that the declaration therein is changed. */ # define signal bsdsignal #endif /* If we're compiling for the dmalloc debugger, turn off string inlining. */ #if defined(HAVE_DMALLOC_H) && defined(__GNUC__) # define __NO_STRING_INLINES #endif #include #include #include #include #include #ifdef HAVE_SYS_TIMEB_H /* SCO 3.2 "devsys 4.2" has a prototype for 'ftime' in that bombs unless has been included first. */ # include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #ifndef errno extern int errno; #endif #ifndef isblank # define isblank(c) ((c) == ' ' || (c) == '\t') #endif #ifdef HAVE_UNISTD_H # include /* Ultrix's unistd.h always defines _POSIX_VERSION, but you only get POSIX.1 behavior with 'cc -YPOSIX', which predefines POSIX itself! */ # if defined (_POSIX_VERSION) && !defined (ultrix) && !defined (VMS) # define POSIX 1 # endif #endif /* Some systems define _POSIX_VERSION but are not really POSIX.1. */ #if (defined (butterfly) || defined (__arm) || (defined (__mips) && defined (_SYSTYPE_SVR3)) || (defined (sequent) && defined (i386))) # undef POSIX #endif #if !defined (POSIX) && defined (_AIX) && defined (_POSIX_SOURCE) # define POSIX 1 #endif #ifndef RETSIGTYPE # define RETSIGTYPE void #endif #ifndef sigmask # define sigmask(sig) (1 << ((sig) - 1)) #endif #ifndef HAVE_SA_RESTART # define SA_RESTART 0 #endif #ifdef HAVE_LIMITS_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifndef PATH_MAX # ifndef POSIX # define PATH_MAX MAXPATHLEN # endif #endif #ifndef MAXPATHLEN # define MAXPATHLEN 1024 #endif #ifdef PATH_MAX # define GET_PATH_MAX PATH_MAX # define PATH_VAR(var) char var[PATH_MAX] #else # define NEED_GET_PATH_MAX 1 # define GET_PATH_MAX (get_path_max ()) # define PATH_VAR(var) char *var = alloca (GET_PATH_MAX) unsigned int get_path_max (void); #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #ifndef USHRT_MAX # define USHRT_MAX 65535 #endif /* Nonzero if the integer type T is signed. Use <= to avoid GCC warnings about always-false expressions. */ #define INTEGER_TYPE_SIGNED(t) ((t) -1 <= 0) /* The minimum and maximum values for the integer type T. Use ~ (t) 0, not -1, for portability to 1's complement hosts. */ #define INTEGER_TYPE_MINIMUM(t) \ (! INTEGER_TYPE_SIGNED (t) ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)) #define INTEGER_TYPE_MAXIMUM(t) (~ (t) 0 - INTEGER_TYPE_MINIMUM (t)) #ifndef CHAR_MAX # define CHAR_MAX INTEGER_TYPE_MAXIMUM (char) #endif #ifdef STAT_MACROS_BROKEN # ifdef S_ISREG # undef S_ISREG # endif # ifdef S_ISDIR # undef S_ISDIR # endif #endif /* STAT_MACROS_BROKEN. */ #ifndef S_ISREG # define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #ifdef VMS # include # include # include # include # include /* Needed to use alloca on VMS. */ # include #endif #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of 'format' and 'printf' attributes are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #define UNUSED __attribute__ ((unused)) #if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) # include # include # define ANSI_STRING 1 #else /* No standard headers. */ # ifdef HAVE_STRING_H # include # define ANSI_STRING 1 # else # include # endif # ifdef HAVE_MEMORY_H # include # endif # ifdef HAVE_STDLIB_H # include # else void *malloc (int); void *realloc (void *, int); void free (void *); void abort (void) __attribute__ ((noreturn)); void exit (int) __attribute__ ((noreturn)); # endif /* HAVE_STDLIB_H. */ #endif /* Standard headers. */ /* These should be in stdlib.h. Make sure we have them. */ #ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE # define EXIT_FAILURE 1 #endif #ifndef ANSI_STRING /* SCO Xenix has a buggy macro definition in . */ #undef strerror #if !defined(__DECC) char *strerror (int errnum); #endif #endif /* !ANSI_STRING. */ #undef ANSI_STRING #if HAVE_INTTYPES_H # include #endif #if HAVE_STDINT_H # include #endif #define FILE_TIMESTAMP uintmax_t #if !defined(HAVE_STRSIGNAL) char *strsignal (int signum); #endif /* ISDIGIT offers the following features: - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. NOTE! Make relies on this behavior, don't change it! - It's typically faster. POSIX 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 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) (c) - '0' <= 9) /* Test if two strings are equal. Is this worthwhile? Should be profiled. */ #define streq(a, b) \ ((a) == (b) || \ (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) /* Test if two strings are equal, but match case-insensitively on systems which have case-insensitive filesystems. Should only be used for filenames! */ #ifdef HAVE_CASE_INSENSITIVE_FS # define patheq(a, b) \ ((a) == (b) \ || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ && (*(a) == '\0' || !strcasecmp ((a) + 1, (b) + 1)))) #else # define patheq(a, b) streq(a, b) #endif #define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) #if defined(__GNUC__) || defined(ENUM_BITFIELDS) # define ENUM_BITFIELD(bits) :bits #else # define ENUM_BITFIELD(bits) #endif /* Handle gettext and locales. */ #if HAVE_LOCALE_H # include #else # define setlocale(category, locale) #endif #include #define _(msgid) gettext (msgid) #define N_(msgid) gettext_noop (msgid) #define S_(msg1,msg2,num) ngettext (msg1,msg2,num) /* Handle other OSs. To overcome an issue parsing paths in a DOS/Windows environment when built in a unix based environment, override the PATH_SEPARATOR_CHAR definition unless being built for Cygwin. */ #if defined(HAVE_DOS_PATHS) && !defined(__CYGWIN__) # undef PATH_SEPARATOR_CHAR # define PATH_SEPARATOR_CHAR ';' #elif !defined(PATH_SEPARATOR_CHAR) # if defined (VMS) # define PATH_SEPARATOR_CHAR ',' # else # define PATH_SEPARATOR_CHAR ':' # endif #endif /* This is needed for getcwd() and chdir(), on some W32 systems. */ #if defined(HAVE_DIRECT_H) # include #endif #ifdef WINDOWS32 # include # include # define pipe(_p) _pipe((_p), 512, O_BINARY) # define kill(_pid,_sig) w32_kill((_pid),(_sig)) /* MSVC and Watcom C don't have ftruncate. */ # if defined(_MSC_VER) || defined(__WATCOMC__) # define ftruncate(_fd,_len) _chsize(_fd,_len) # endif /* MinGW64 doesn't have _S_ISDIR. */ # ifndef _S_ISDIR # define _S_ISDIR(m) S_ISDIR(m) # endif void sync_Path_environment (void); int w32_kill (pid_t pid, int sig); int find_and_set_default_shell (const char *token); /* indicates whether or not we have Bourne shell */ extern int no_default_sh_exe; /* is default_shell unixy? */ extern int unixy_shell; /* We don't have a preferred fixed value for LOCALEDIR. */ # ifndef LOCALEDIR # define LOCALEDIR NULL # endif /* Include only the minimal stuff from windows.h. */ #define WIN32_LEAN_AND_MEAN #endif /* WINDOWS32 */ #define ANY_SET(_v,_m) (((_v)&(_m)) != 0) #define NONE_SET(_v,_m) (! ANY_SET ((_v),(_m))) #define MAP_NUL 0x0001 #define MAP_BLANK 0x0002 #define MAP_SPACE 0x0004 #define MAP_COMMENT 0x0008 #define MAP_SEMI 0x0010 #define MAP_EQUALS 0x0020 #define MAP_COLON 0x0040 #define MAP_PERCENT 0x0080 #define MAP_PIPE 0x0100 #define MAP_DOT 0x0200 #define MAP_COMMA 0x0400 /* These are the valid characters for a user-defined function. */ #define MAP_USERFUNC 0x2000 /* This means not only a '$', but skip the variable reference. */ #define MAP_VARIABLE 0x4000 /* The set of characters which are directory separators is OS-specific. */ #define MAP_DIRSEP 0x8000 #ifdef VMS # define MAP_VMSCOMMA MAP_COMMA #else # define MAP_VMSCOMMA 0x0000 #endif #define STOP_SET(_v,_m) ANY_SET (stopchar_map[(unsigned char)(_v)],(_m)) #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) # define SET_STACK_SIZE #endif #ifdef SET_STACK_SIZE # include extern struct rlimit stack_limit; #endif #define NILF ((gmk_floc *)0) #define CSTRLEN(_s) (sizeof (_s)-1) #define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s) /* The number of bytes needed to represent the largest integer as a string. */ #define INTSTR_LENGTH CSTRLEN ("18446744073709551616") #define DEFAULT_TTYNAME "true" #ifdef HAVE_TTYNAME # define TTYNAME(_f) ttyname (_f) #else # define TTYNAME(_f) DEFAULT_TTYNAME #endif const char *concat (unsigned int, ...); void message (int prefix, size_t length, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); void error (const gmk_floc *flocp, size_t length, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); void fatal (const gmk_floc *flocp, size_t length, const char *fmt, ...) __attribute__ ((noreturn, __format__ (__printf__, 3, 4))); #define O(_t,_a,_f) _t((_a), 0, (_f)) #define OS(_t,_a,_f,_s) _t((_a), strlen (_s), (_f), (_s)) #define OSS(_t,_a,_f,_s1,_s2) _t((_a), strlen (_s1) + strlen (_s2), \ (_f), (_s1), (_s2)) #define OSSS(_t,_a,_f,_s1,_s2,_s3) _t((_a), strlen (_s1) + strlen (_s2) + strlen (_s3), \ (_f), (_s1), (_s2), (_s3)) #define ON(_t,_a,_f,_n) _t((_a), INTSTR_LENGTH, (_f), (_n)) #define ONN(_t,_a,_f,_n1,_n2) _t((_a), INTSTR_LENGTH*2, (_f), (_n1), (_n2)) #define OSN(_t,_a,_f,_s,_n) _t((_a), strlen (_s) + INTSTR_LENGTH, \ (_f), (_s), (_n)) #define ONS(_t,_a,_f,_n,_s) _t((_a), INTSTR_LENGTH + strlen (_s), \ (_f), (_n), (_s)) #define OUT_OF_MEM() O (fatal, NILF, _("virtual memory exhausted")) void die (int) __attribute__ ((noreturn)); void pfatal_with_name (const char *) __attribute__ ((noreturn)); void perror_with_name (const char *, const char *); #define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s)) void *xmalloc (unsigned int); void *xcalloc (unsigned int); void *xrealloc (void *, unsigned int); char *xstrdup (const char *); char *xstrndup (const char *, unsigned int); char *find_next_token (const char **, unsigned int *); char *next_token (const char *); char *end_of_token (const char *); void collapse_continuations (char *); char *lindex (const char *, const char *, int); int alpha_compare (const void *, const void *); void print_spaces (unsigned int); char *find_percent (char *); const char *find_percent_cached (const char **); #ifndef NO_ARCHIVES int ar_name (const char *); void ar_parse_name (const char *, char **, char **); int ar_touch (const char *); int ar_member_date (const char *, time_t *); typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated, long int hdrpos, long int datapos, long int size, long int date, int uid, int gid, int mode, const void *arg); long int ar_scan (const char *archive, ar_member_func_t function, const void *arg); int ar_name_equal (const char *name, const char *mem, int truncated); #ifndef VMS int ar_member_touch (const char *arname, const char *memname); #endif #endif int dir_file_exists_p (const char *, const char *); int file_exists_p (const char *); int file_impossible_p (const char *); void file_impossible (const char *); const char *dir_name (const char *); void hash_init_directories (void); void define_default_variables (void); void undefine_default_variables (void); void set_default_suffixes (void); void install_default_suffix_rules (void); void install_default_implicit_rules (void); void build_vpath_lists (void); void construct_vpath_list (char *pattern, char *dirpath); const char *vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index); int gpath_search (const char *file, unsigned int len); void construct_include_path (const char **arg_dirs); void user_access (void); void make_access (void); void child_access (void); char *strip_whitespace (const char **begpp, const char **endpp); /* String caching */ void strcache_init (void); void strcache_print_stats (const char *prefix); int strcache_iscached (const char *str); const char *strcache_add (const char *str); const char *strcache_add_len (const char *str, unsigned int len); int strcache_setbufsize (unsigned int size); /* Guile support */ int guile_gmake_setup (const gmk_floc *flocp); /* Loadable object support. Sets to the strcached name of the loaded file. */ typedef int (*load_func_t)(const gmk_floc *flocp); int load_file (const gmk_floc *flocp, const char **filename, int noerror); void unload_file (const char *name); /* We omit these declarations on non-POSIX systems which define _POSIX_VERSION, because such systems often declare them in header files anyway. */ #if !defined (__GNU_LIBRARY__) && !defined (POSIX) && !defined (_POSIX_VERSION) && !defined(WINDOWS32) long int atol (); # ifndef VMS long int lseek (); # endif #endif /* Not GNU C library or POSIX. */ #ifdef HAVE_GETCWD # if !defined(VMS) && !defined(__DECC) char *getcwd (); # endif #else char *getwd (); # define getcwd(buf, len) getwd (buf) #endif #if !HAVE_STRCASECMP # if HAVE_STRICMP # define strcasecmp stricmp # elif HAVE_STRCMPI # define strcasecmp strcmpi # else /* Create our own, in misc.c */ int strcasecmp (const char *s1, const char *s2); # endif #endif #if !HAVE_STRNCASECMP # if HAVE_STRNICMP # define strncasecmp strnicmp # elif HAVE_STRNCMPI # define strncasecmp strncmpi # else /* Create our own, in misc.c */ int strncasecmp (const char *s1, const char *s2, int n); # endif #endif extern const gmk_floc *reading_file; extern const gmk_floc **expanding_var; extern char **environ; extern unsigned short stopchar_map[]; extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; extern int print_data_base_flag, question_flag, touch_flag, always_make_flag; extern int env_overrides, no_builtin_rules_flag, no_builtin_variables_flag; extern int print_version_flag, print_directory_flag, check_symlink_flag; extern int warn_undefined_variables_flag, trace_flag, posix_pedantic; extern int not_parallel, second_expansion, clock_skew_detected; extern int rebuilding_makefiles, one_shell, output_sync, verify_flag; /* can we run commands via 'sh -c xxx' or must we use batch files? */ extern int batch_mode_shell; /* Resetting the command script introduction prefix character. */ #define RECIPEPREFIX_NAME ".RECIPEPREFIX" #define RECIPEPREFIX_DEFAULT '\t' extern char cmd_prefix; extern unsigned int job_slots; extern int job_fds[2]; extern int job_rfd; #ifndef NO_FLOAT extern double max_load_average; #else extern int max_load_average; #endif #ifdef WINDOWS32 extern char *program; #else extern const char *program; #endif #ifdef VMS const char *vms_command(const char *argv0); const char *vms_progname(const char *argv0); #endif extern char *starting_directory; extern unsigned int makelevel; extern char *version_string, *remote_description, *make_host; extern unsigned int commands_started; extern int handling_fatal_signal; #ifndef MIN #define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) #endif #ifndef MAX #define MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) #endif #ifdef VMS /* These are the VMS __posix_exit compliant exit codes, constructed out of STS$M_INHIB_MSG, C facility code, a POSIX condition code mask, MAKE_NNN<<3 and the coresponding VMS severity, here STS$K_SUCCESS and STS$K_ERROR. */ # define MAKE_SUCCESS 0x1035a001 # define MAKE_TROUBLE 0x1035a00a # define MAKE_FAILURE 0x1035a012 #else # define MAKE_SUCCESS 0 # define MAKE_TROUBLE 1 # define MAKE_FAILURE 2 #endif /* Set up heap debugging library dmalloc. */ #ifdef HAVE_DMALLOC_H #include #endif #ifndef initialize_main # ifdef __EMX__ # define initialize_main(pargc, pargv) \ { _wildcard(pargc, pargv); _response(pargc, pargv); } # else # define initialize_main(pargc, pargv) # endif #endif #ifdef __EMX__ # if !defined chdir # define chdir _chdir2 # endif # if !defined getcwd # define getcwd _getcwd2 # endif /* NO_CHDIR2 causes make not to use _chdir2() and _getcwd2() instead of chdir() and getcwd(). This avoids some error messages for the make testsuite but restricts the drive letter support. */ # ifdef NO_CHDIR2 # warning NO_CHDIR2: usage of drive letters restricted # undef chdir # undef getcwd # endif #endif #ifndef initialize_main # define initialize_main(pargc, pargv) #endif /* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag properly according to POSIX. So, we try to wrap common system calls with checks for EINTR. Note that there are still plenty of system calls that can fail with EINTR but this, reportedly, gets the vast majority of failure cases. If you still experience failures you'll need to either get a system where SA_RESTART works, or you need to avoid -j. */ #define EINTRLOOP(_v,_c) while (((_v)=_c)==-1 && errno==EINTR) /* While system calls that return integers are pretty consistent about returning -1 on failure and setting errno in that case, functions that return pointers are not always so well behaved. Sometimes they return NULL for expected behavior: one good example is readdir() which returns NULL at the end of the directory--and _doesn't_ reset errno. So, we have to do it ourselves here. */ #define ENULLLOOP(_v,_c) do { errno = 0; (_v) = _c; } \ while((_v)==0 && errno==EINTR) #endif /* REMAKE_MAKEINT_H */ remake-4.1+dbg1.3~dfsg.1/misc.c000066400000000000000000000377071317072305000161100ustar00rootroot00000000000000/* Miscellaneous generic support functions for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "dep.h" #include "debug.h" /* GNU make no longer supports pre-ANSI89 environments. */ #include #ifdef HAVE_FCNTL_H # include #else # include #endif /* Compare strings *S1 and *S2. Return negative if the first is less, positive if it is greater, zero if they are equal. */ int alpha_compare (const void *v1, const void *v2) { const char *s1 = *((char **)v1); const char *s2 = *((char **)v2); if (*s1 != *s2) return *s1 - *s2; return strcmp (s1, s2); } /* Discard each backslash-newline combination from LINE. Backslash-backslash-newline combinations become backslash-newlines. This is done by copying the text at LINE into itself. */ void collapse_continuations (char *line) { char *in, *out, *p; in = strchr (line, '\n'); if (in == 0) return; out = in; while (out > line && out[-1] == '\\') --out; while (*in != '\0') { /* BS_WRITE gets the number of quoted backslashes at the end just before IN, and BACKSLASH gets nonzero if the next character is quoted. */ unsigned int backslash = 0; unsigned int bs_write = 0; for (p = in - 1; p >= line && *p == '\\'; --p) { if (backslash) ++bs_write; backslash = !backslash; /* It should be impossible to go back this far without exiting, but if we do, we can't get the right answer. */ if (in == out - 1) abort (); } /* Output the appropriate number of backslashes. */ while (bs_write-- > 0) *out++ = '\\'; /* Skip the newline. */ ++in; if (backslash) { /* Backslash/newline handling: In traditional GNU make all trailing whitespace, consecutive backslash/newlines, and any leading whitespace on the next line is reduced to a single space. In POSIX, each backslash/newline and is replaced by a space. */ in = next_token (in); if (! posix_pedantic) while (out > line && isblank ((unsigned char)out[-1])) --out; *out++ = ' '; } else /* If the newline isn't quoted, put it in the output. */ *out++ = '\n'; /* Now copy the following line to the output. Stop when we find backslashes followed by a newline. */ while (*in != '\0') if (*in == '\\') { p = in + 1; while (*p == '\\') ++p; if (*p == '\n') { in = p; break; } while (in < p) *out++ = *in++; } else *out++ = *in++; } *out = '\0'; } /* Print N spaces (used in debug for target-depth). */ void print_spaces (unsigned int n) { while (n-- > 0) putchar (' '); } /* Return a string whose contents concatenate the NUM strings provided This string lives in static, re-used memory. */ const char * concat (unsigned int num, ...) { static unsigned int rlen = 0; static char *result = NULL; unsigned int ri = 0; va_list args; va_start (args, num); while (num-- > 0) { const char *s = va_arg (args, const char *); unsigned int l = xstrlen (s); if (l == 0) continue; if (ri + l > rlen) { rlen = ((rlen ? rlen : 60) + l) * 2; result = xrealloc (result, rlen); } memcpy (result + ri, s, l); ri += l; } va_end (args); /* Get some more memory if we don't have enough space for the terminating '\0'. */ if (ri == rlen) { rlen = (rlen ? rlen : 60) * 2; result = xrealloc (result, rlen); } result[ri] = '\0'; return result; } #ifndef HAVE_STRERROR #undef strerror char * strerror (int errnum) { extern int errno, sys_nerr; #ifndef __DECC extern char *sys_errlist[]; #endif static char buf[] = "Unknown error 12345678901234567890"; if (errno < sys_nerr) return sys_errlist[errnum]; sprintf (buf, _("Unknown error %d"), errnum); return buf; } #endif /* Limited INDEX: Search through the string STRING, which ends at LIMIT, for the character C. Returns a pointer to the first occurrence, or nil if none is found. Like INDEX except that the string searched ends where specified instead of at the first null. */ char * lindex (const char *s, const char *limit, int c) { while (s < limit) if (*s++ == c) return (char *)(s - 1); return 0; } /* Return the address of the first whitespace or null in the string S. */ char * end_of_token (const char *s) { while (! STOP_SET (*s, MAP_BLANK|MAP_NUL)) ++s; return (char *)s; } /* Return the address of the first nonwhitespace or null in the string S. */ char * next_token (const char *s) { while (isblank ((unsigned char)*s)) ++s; return (char *)s; } /* Find the next token in PTR; return the address of it, and store the length of the token into *LENGTHPTR if LENGTHPTR is not nil. Set *PTR to the end of the token, so this function can be called repeatedly in a loop. */ char * find_next_token (const char **ptr, unsigned int *lengthptr) { const char *p = next_token (*ptr); if (*p == '\0') return 0; *ptr = end_of_token (p); if (lengthptr != 0) *lengthptr = *ptr - p; return (char *)p; } /* Copy a chain of 'struct dep'. For 2nd expansion deps, dup the name. */ struct dep * copy_dep_chain (const struct dep *d) { struct dep *firstnew = 0; struct dep *lastnew = 0; while (d != 0) { struct dep *c = xmalloc (sizeof (struct dep)); memcpy (c, d, sizeof (struct dep)); if (c->need_2nd_expansion) c->name = xstrdup (c->name); c->next = 0; if (firstnew == 0) firstnew = lastnew = c; else lastnew = lastnew->next = c; d = d->next; } return firstnew; } /* Free a chain of 'struct dep'. */ void free_dep_chain (struct dep *d) { while (d != 0) { struct dep *df = d; d = d->next; free_dep (df); } } /* Free a chain of struct nameseq. For struct dep chains use free_dep_chain. */ void free_ns_chain (struct nameseq *ns) { while (ns != 0) { struct nameseq *t = ns; ns = ns->next; free (t); } } #if !HAVE_STRCASECMP && !HAVE_STRICMP && !HAVE_STRCMPI /* If we don't have strcasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strcasecmp (const char *s1, const char *s2) { while (1) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } } #endif #if !HAVE_STRNCASECMP && !HAVE_STRNICMP && !HAVE_STRNCMPI /* If we don't have strncasecmp() (from POSIX), or anything that can substitute for it, define our own version. */ int strncasecmp (const char *s1, const char *s2, int n) { while (n-- > 0) { int c1 = (int) *(s1++); int c2 = (int) *(s2++); if (isalpha (c1)) c1 = tolower (c1); if (isalpha (c2)) c2 = tolower (c2); if (c1 != '\0' && c1 == c2) continue; return (c1 - c2); } return 0; } #endif #ifdef GETLOADAVG_PRIVILEGED #ifdef POSIX /* Hopefully if a system says it's POSIX.1 and has the setuid and setgid functions, they work as POSIX.1 says. Some systems (Alpha OSF/1 1.2, for example) which claim to be POSIX.1 also have the BSD setreuid and setregid functions, but they don't work as in BSD and only the POSIX.1 way works. */ #undef HAVE_SETREUID #undef HAVE_SETREGID #else /* Not POSIX. */ /* Some POSIX.1 systems have the seteuid and setegid functions. In a POSIX-like system, they are the best thing to use. However, some non-POSIX systems have them too but they do not work in the POSIX style and we must use setreuid and setregid instead. */ #undef HAVE_SETEUID #undef HAVE_SETEGID #endif /* POSIX. */ #ifndef HAVE_UNISTD_H extern int getuid (), getgid (), geteuid (), getegid (); extern int setuid (), setgid (); #ifdef HAVE_SETEUID extern int seteuid (); #else #ifdef HAVE_SETREUID extern int setreuid (); #endif /* Have setreuid. */ #endif /* Have seteuid. */ #ifdef HAVE_SETEGID extern int setegid (); #else #ifdef HAVE_SETREGID extern int setregid (); #endif /* Have setregid. */ #endif /* Have setegid. */ #endif /* No . */ /* Keep track of the user and group IDs for user- and make- access. */ static int user_uid = -1, user_gid = -1, make_uid = -1, make_gid = -1; #define access_inited (user_uid != -1) static enum { make, user } current_access; /* Under -d, write a message describing the current IDs. */ static void log_access (const char *flavor) { if (! ISDB (DB_JOBS)) return; /* All the other debugging messages go to stdout, but we write this one to stderr because it might be run in a child fork whose stdout is piped. */ fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"), flavor, (unsigned long) geteuid (), (unsigned long) getuid (), (unsigned long) getegid (), (unsigned long) getgid ()); fflush (stderr); } static void init_access (void) { #ifndef VMS user_uid = getuid (); user_gid = getgid (); make_uid = geteuid (); make_gid = getegid (); /* Do these ever fail? */ if (user_uid == -1 || user_gid == -1 || make_uid == -1 || make_gid == -1) pfatal_with_name ("get{e}[gu]id"); log_access (_("Initialized access")); current_access = make; #endif } #endif /* GETLOADAVG_PRIVILEGED */ /* Give the process appropriate permissions for access to user data (i.e., to stat files, or to spawn a child process). */ void user_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == user) return; /* We are in "make access" mode. This means that the effective user and group IDs are those of make (if it was installed setuid or setgid). We now want to set the effective user and group IDs to the real IDs, which are the IDs of the process that exec'd make. */ #ifdef HAVE_SETEUID /* Modern systems have the seteuid/setegid calls which set only the effective IDs, which is ideal. */ if (seteuid (user_uid) < 0) pfatal_with_name ("user_access: seteuid"); #else /* Not HAVE_SETEUID. */ #ifndef HAVE_SETREUID /* System V has only the setuid/setgid calls to set user/group IDs. There is an effective ID, which can be set by setuid/setgid. It can be set (unless you are root) only to either what it already is (returned by geteuid/getegid, now in make_uid/make_gid), the real ID (return by getuid/getgid, now in user_uid/user_gid), or the saved set ID (what the effective ID was before this set-ID executable (make) was exec'd). */ if (setuid (user_uid) < 0) pfatal_with_name ("user_access: setuid"); #else /* HAVE_SETREUID. */ /* In 4BSD, the setreuid/setregid calls set both the real and effective IDs. They may be set to themselves or each other. So you have two alternatives at any one time. If you use setuid/setgid, the effective will be set to the real, leaving only one alternative. Using setreuid/setregid, however, you can toggle between your two alternatives by swapping the values in a single setreuid or setregid call. */ if (setreuid (make_uid, user_uid) < 0) pfatal_with_name ("user_access: setreuid"); #endif /* Not HAVE_SETREUID. */ #endif /* HAVE_SETEUID. */ #ifdef HAVE_SETEGID if (setegid (user_gid) < 0) pfatal_with_name ("user_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("user_access: setgid"); #else if (setregid (make_gid, user_gid) < 0) pfatal_with_name ("user_access: setregid"); #endif #endif current_access = user; log_access (_("User access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for access to make data (i.e., the load average). */ void make_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) init_access (); if (current_access == make) return; /* See comments in user_access, above. */ #ifdef HAVE_SETEUID if (seteuid (make_uid) < 0) pfatal_with_name ("make_access: seteuid"); #else #ifndef HAVE_SETREUID if (setuid (make_uid) < 0) pfatal_with_name ("make_access: setuid"); #else if (setreuid (user_uid, make_uid) < 0) pfatal_with_name ("make_access: setreuid"); #endif #endif #ifdef HAVE_SETEGID if (setegid (make_gid) < 0) pfatal_with_name ("make_access: setegid"); #else #ifndef HAVE_SETREGID if (setgid (make_gid) < 0) pfatal_with_name ("make_access: setgid"); #else if (setregid (user_gid, make_gid) < 0) pfatal_with_name ("make_access: setregid"); #endif #endif current_access = make; log_access (_("Make access")); #endif /* GETLOADAVG_PRIVILEGED */ } /* Give the process appropriate permissions for a child process. This is like user_access, but you can't get back to make_access. */ void child_access (void) { #ifdef GETLOADAVG_PRIVILEGED if (!access_inited) abort (); /* Set both the real and effective UID and GID to the user's. They cannot be changed back to make's. */ #ifndef HAVE_SETREUID if (setuid (user_uid) < 0) pfatal_with_name ("child_access: setuid"); #else if (setreuid (user_uid, user_uid) < 0) pfatal_with_name ("child_access: setreuid"); #endif #ifndef HAVE_SETREGID if (setgid (user_gid) < 0) pfatal_with_name ("child_access: setgid"); #else if (setregid (user_gid, user_gid) < 0) pfatal_with_name ("child_access: setregid"); #endif log_access (_("Child access")); #endif /* GETLOADAVG_PRIVILEGED */ } #ifdef NEED_GET_PATH_MAX unsigned int get_path_max (void) { static unsigned int value; if (value == 0) { long int x = pathconf ("/", _PC_PATH_MAX); if (x > 0) value = x; else return MAXPATHLEN; } return value; } #endif /* Map of possible stop characters for searching strings. */ #ifndef UCHAR_MAX # define UCHAR_MAX 255 #endif unsigned short stopchar_map[UCHAR_MAX + 1] = {0}; /* This character map locate stop chars when parsing GNU makefiles. Each element is true if we should stop parsing on that character. */ extern void initialize_stopchar_map () { int i; stopchar_map[(int)'\0'] = MAP_NUL; stopchar_map[(int)'#'] = MAP_COMMENT; stopchar_map[(int)';'] = MAP_SEMI; stopchar_map[(int)'='] = MAP_EQUALS; stopchar_map[(int)':'] = MAP_COLON; stopchar_map[(int)'%'] = MAP_PERCENT; stopchar_map[(int)'|'] = MAP_PIPE; stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC; stopchar_map[(int)','] = MAP_COMMA; stopchar_map[(int)'$'] = MAP_VARIABLE; stopchar_map[(int)'-'] = MAP_USERFUNC; stopchar_map[(int)'_'] = MAP_USERFUNC; stopchar_map[(int)'/'] = MAP_DIRSEP; #if defined(VMS) stopchar_map[(int)']'] = MAP_DIRSEP; #elif defined(HAVE_DOS_PATHS) stopchar_map[(int)'\\'] = MAP_DIRSEP; #endif for (i = 1; i <= UCHAR_MAX; ++i) { if (isblank(i)) stopchar_map[i] = MAP_BLANK; if (isspace(i)) stopchar_map[i] |= MAP_SPACE; if (isalnum(i)) stopchar_map[i] = MAP_USERFUNC; } } remake-4.1+dbg1.3~dfsg.1/mock.c000066400000000000000000000007331317072305000160730ustar00rootroot00000000000000#include "mock.h" #include "debug.h" #include "debugger.h" void die (int status) { exit (status); } debug_return_t enter_debugger (target_stack_node_t *p, file_t *p_target, int errcode, debug_enter_reason_t reason) { printf("%p %p %d %u\n", p, p_target, errcode, reason); return continue_execution; } /*! Show target information: location and name. */ extern void print_file_target_prefix (const file_t *p_target) { printf("%p\n", p_target); } remake-4.1+dbg1.3~dfsg.1/mock.h000066400000000000000000000001221317072305000160700ustar00rootroot00000000000000#include extern void die (int status); extern void fatal (int status); remake-4.1+dbg1.3~dfsg.1/output.c000066400000000000000000000423741317072305000165110ustar00rootroot00000000000000/* Output to stdout / stderr for GNU make Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "globals.h" #include "job.h" /* GNU make no longer supports pre-ANSI89 environments. */ #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_FCNTL_H # include #else # include #endif #ifdef WINDOWS32 # include # include # include "sub_proc.h" #endif /* WINDOWS32 */ struct output *output_context = NULL; unsigned int stdio_traced = 0; #define OUTPUT_NONE (-1) #define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0) #ifdef HAVE_FCNTL # define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF)) #else # define STREAM_OK(_s) 1 #endif /* Write a string to the current STDOUT or STDERR. */ static void _outputs (struct output *out, int is_err, const char *msg) { if (! out || ! out->syncout) { FILE *f = is_err ? stderr : stdout; fputs (msg, f); fflush (f); } else { int fd = is_err ? out->err : out->out; int len = strlen (msg); int r; EINTRLOOP (r, lseek (fd, 0, SEEK_END)); while (1) { EINTRLOOP (r, write (fd, msg, len)); if (r == len || r <= 0) break; len -= r; msg += r; } } } /* Write a message indicating that we've just entered or left (according to ENTERING) the current directory. */ int log_working_directory (int entering) { static char *buf = NULL; static unsigned int len = 0; unsigned int need; const char *fmt; char *p; /* Get enough space for the longest possible output. */ need = strlen (program) + INTSTR_LENGTH + 2 + 1; if (starting_directory) need += strlen (starting_directory); /* Use entire sentences to give the translators a fighting chance. */ if (makelevel == 0) if (starting_directory == 0) if (entering) fmt = _("%s: Entering an unknown directory\n"); else fmt = _("%s: Leaving an unknown directory\n"); else if (entering) fmt = _("%s: Entering directory '%s'\n"); else fmt = _("%s: Leaving directory '%s'\n"); else if (starting_directory == 0) if (entering) fmt = _("%s[%u]: Entering an unknown directory\n"); else fmt = _("%s[%u]: Leaving an unknown directory\n"); else if (entering) fmt = _("%s[%u]: Entering directory '%s'\n"); else fmt = _("%s[%u]: Leaving directory '%s'\n"); need += strlen (fmt); if (need > len) { buf = xrealloc (buf, need); len = need; } p = buf; if (print_data_base_flag) { *(p++) = '#'; *(p++) = ' '; } if (makelevel == 0) if (starting_directory == 0) sprintf (p, fmt , program); else sprintf (p, fmt, program, starting_directory); else if (starting_directory == 0) sprintf (p, fmt, program, makelevel); else sprintf (p, fmt, program, makelevel, starting_directory); _outputs (NULL, 0, buf); return 1; } /* Set a file descriptor to be in O_APPEND mode. If it fails, just ignore it. */ static void set_append_mode (int fd) { #if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND) int flags = fcntl (fd, F_GETFL, 0); if (flags >= 0) fcntl (fd, F_SETFL, flags | O_APPEND); #endif } #ifndef NO_OUTPUT_SYNC /* Semaphore for use in -j mode with output_sync. */ static sync_handle_t sync_handle = -1; #define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0) /* Set up the sync handle. Disables output_sync on error. */ static int sync_init () { int combined_output = 0; #ifdef WINDOWS32 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr)) || (sync_handle = create_mutex ()) == -1) { perror_with_name ("output-sync suppressed: ", "stderr"); output_sync = 0; } else { combined_output = same_stream (stdout, stderr); prepare_mutex_handle_string (sync_handle); } #else if (STREAM_OK (stdout)) { struct stat stbuf_o, stbuf_e; sync_handle = fileno (stdout); combined_output = (fstat (fileno (stdout), &stbuf_o) == 0 && fstat (fileno (stderr), &stbuf_e) == 0 && stbuf_o.st_dev == stbuf_e.st_dev && stbuf_o.st_ino == stbuf_e.st_ino); } else if (STREAM_OK (stderr)) sync_handle = fileno (stderr); else { perror_with_name ("output-sync suppressed: ", "stderr"); output_sync = 0; } #endif return combined_output; } /* Support routine for output_sync() */ static void pump_from_tmp (int from, FILE *to) { static char buffer[8192]; #ifdef WINDOWS32 int prev_mode; /* "from" is opened by open_tmpfd, which does it in binary mode, so we need the mode of "to" to match that. */ prev_mode = _setmode (fileno (to), _O_BINARY); #endif if (lseek (from, 0, SEEK_SET) == -1) perror ("lseek()"); while (1) { int len; EINTRLOOP (len, read (from, buffer, sizeof (buffer))); if (len < 0) perror ("read()"); if (len <= 0) break; if (fwrite (buffer, len, 1, to) < 1) { perror ("fwrite()"); break; } fflush (to); } #ifdef WINDOWS32 /* Switch "to" back to its original mode, so that log messages by Make have the same EOL format as without --output-sync. */ _setmode (fileno (to), prev_mode); #endif } /* Obtain the lock for writing output. */ static void * acquire_semaphore (void) { static struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 1; if (fcntl (sync_handle, F_SETLKW, &fl) != -1) return &fl; perror ("fcntl()"); return NULL; } /* Release the lock for writing output. */ static void release_semaphore (void *sem) { struct flock *flp = (struct flock *)sem; flp->l_type = F_UNLCK; if (fcntl (sync_handle, F_SETLKW, flp) == -1) perror ("fcntl()"); } /* Returns a file descriptor to a temporary file. The file is automatically closed/deleted on exit. Don't use a FILE* stream. */ int output_tmpfd () { int fd = -1; FILE *tfile = tmpfile (); if (! tfile) pfatal_with_name ("tmpfile"); /* Create a duplicate so we can close the stream. */ fd = dup (fileno (tfile)); if (fd < 0) pfatal_with_name ("dup"); fclose (tfile); set_append_mode (fd); return fd; } /* Adds file descriptors to the child structure to support output_sync; one for stdout and one for stderr as long as they are open. If stdout and stderr share a device they can share a temp file too. Will reset output_sync on error. */ static void setup_tmpfile (struct output *out) { /* Is make's stdout going to the same place as stderr? */ static int combined_output = -1; if (combined_output < 0) combined_output = sync_init (); if (STREAM_OK (stdout)) { int fd = output_tmpfd (); if (fd < 0) goto error; CLOSE_ON_EXEC (fd); out->out = fd; } if (STREAM_OK (stderr)) { if (out->out != OUTPUT_NONE && combined_output) out->err = out->out; else { int fd = output_tmpfd (); if (fd < 0) goto error; CLOSE_ON_EXEC (fd); out->err = fd; } } return; /* If we failed to create a temp file, disable output sync going forward. */ error: output_close (out); output_sync = 0; } /* Synchronize the output of jobs in -j mode to keep the results of each job together. This is done by holding the results in temp files, one for stdout and potentially another for stderr, and only releasing them to "real" stdout/stderr when a semaphore can be obtained. */ void output_dump (struct output *out) { int outfd_not_empty = FD_NOT_EMPTY (out->out); int errfd_not_empty = FD_NOT_EMPTY (out->err); if (outfd_not_empty || errfd_not_empty) { int traced = 0; /* Try to acquire the semaphore. If it fails, dump the output unsynchronized; still better than silently discarding it. We want to keep this lock for as little time as possible. */ void *sem = acquire_semaphore (); /* Log the working directory for this dump. */ if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE) traced = log_working_directory (1); if (outfd_not_empty) pump_from_tmp (out->out, stdout); if (errfd_not_empty && out->err != out->out) pump_from_tmp (out->err, stderr); if (traced) log_working_directory (0); /* Exit the critical section. */ if (sem) release_semaphore (sem); /* Truncate and reset the output, in case we use it again. */ if (out->out != OUTPUT_NONE) { int e; lseek (out->out, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->out, 0)); } if (out->err != OUTPUT_NONE && out->err != out->out) { int e; lseek (out->err, 0, SEEK_SET); EINTRLOOP (e, ftruncate (out->err, 0)); } } } #endif /* NO_OUTPUT_SYNC */ /* Provide support for temporary files. */ #ifndef HAVE_STDLIB_H # ifdef HAVE_MKSTEMP int mkstemp (char *template); # else char *mktemp (char *template); # endif #endif FILE * output_tmpfile (char **name, const char *template) { #ifdef HAVE_FDOPEN int fd; #endif #if defined HAVE_MKSTEMP || defined HAVE_MKTEMP # define TEMPLATE_LEN strlen (template) #else # define TEMPLATE_LEN L_tmpnam #endif *name = xmalloc (TEMPLATE_LEN + 1); strcpy (*name, template); #if defined HAVE_MKSTEMP && defined HAVE_FDOPEN /* It's safest to use mkstemp(), if we can. */ fd = mkstemp (*name); if (fd == -1) return 0; return fdopen (fd, "w"); #else # ifdef HAVE_MKTEMP (void) mktemp (*name); # else (void) tmpnam (*name); # endif # ifdef HAVE_FDOPEN /* Can't use mkstemp(), but guard against a race condition. */ fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600); if (fd == -1) return 0; return fdopen (fd, "w"); # else /* Not secure, but what can we do? */ return fopen (*name, "w"); # endif #endif } /* This code is stolen from gnulib. If/when we abandon the requirement to work with K&R compilers, we can remove this (and perhaps other parts of GNU make!) and migrate to using gnulib directly. This is called only through atexit(), which means die() has already been invoked. So, call exit() here directly. Apparently that works...? */ /* Close standard output, exiting with status 'exit_failure' on failure. If a program writes *anything* to stdout, that program should close stdout 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 stdout. The last printf can succeed in writing to the internal stream buffer, and yet the fclose(stdout) 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 stdout -- just let the internal stream state record the failure. That's what the ferror test is checking below. It's important to detect such failures and exit nonzero because many tools (most notably 'make' and other build-management systems) depend on being able to detect failure in other tools via their exit status. */ static void close_stdout (void) { int prev_fail = ferror (stdout); int fclose_fail = fclose (stdout); if (prev_fail || fclose_fail) { if (fclose_fail) perror_with_name (_("write error: stdout"), ""); else O (error, NILF, _("write error: stdout")); exit (MAKE_TROUBLE); } } void output_init (struct output *out) { if (out) { out->out = out->err = OUTPUT_NONE; out->syncout = !!output_sync; return; } /* Configure this instance of make. Be sure stdout is line-buffered. */ #ifdef HAVE_SETVBUF # ifdef SETVBUF_REVERSED setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ); # else /* setvbuf not reversed. */ /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */ setvbuf (stdout, 0, _IOLBF, BUFSIZ); # endif /* setvbuf reversed. */ #elif HAVE_SETLINEBUF setlinebuf (stdout); #endif /* setlinebuf missing. */ /* Force stdout/stderr into append mode. This ensures parallel jobs won't lose output due to overlapping writes. */ set_append_mode (fileno (stdout)); set_append_mode (fileno (stderr)); #ifdef HAVE_ATEXIT if (STREAM_OK (stdout)) atexit (close_stdout); #endif } void output_close (struct output *out) { if (! out) { if (stdio_traced) log_working_directory (0); return; } #ifndef NO_OUTPUT_SYNC output_dump (out); #endif if (out->out >= 0) close (out->out); if (out->err >= 0 && out->err != out->out) close (out->err); output_init (out); } /* We're about to generate output: be sure it's set up. */ void output_start () { #ifndef NO_OUTPUT_SYNC /* If we're syncing output make sure the temporary file is set up. */ if (output_context && output_context->syncout) if (! OUTPUT_ISSET(output_context)) setup_tmpfile (output_context); #endif /* If we're not syncing this output per-line or per-target, make sure we emit the "Entering..." message where appropriate. */ if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE) if (! stdio_traced && print_directory_flag) stdio_traced = log_working_directory (1); } void outputs (int is_err, const char *msg) { if (! msg || *msg == '\0') return; output_start (); _outputs (output_context, is_err, msg); } static struct fmtstring { char *buffer; size_t size; } fmtbuf = { NULL, 0 }; static char * get_buffer (size_t need) { /* Make sure we have room. NEED includes space for \0. */ if (need > fmtbuf.size) { fmtbuf.size += need * 2; fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size); } fmtbuf.buffer[need-1] = '\0'; return fmtbuf.buffer; } /* Print a message on stdout. */ void message (int prefix, size_t len, const char *fmt, ...) { va_list args; char *p; len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1; p = get_buffer (len); if (prefix) { if (makelevel == 0) sprintf (p, "%s: ", program); else sprintf (p, "%s[%u]: ", program, makelevel); p += strlen (p); } va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, "\n"); assert (fmtbuf.buffer[len-1] == '\0'); outputs (0, fmtbuf.buffer); } /* Print an error message. */ void error (const gmk_floc *flocp, size_t len, const char *fmt, ...) { va_list args; char *p; len += (strlen (fmt) + strlen (program) + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0) + INTSTR_LENGTH + 4 + 1 + 1); p = get_buffer (len); if (flocp && flocp->filenm) sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno); else if (makelevel == 0) sprintf (p, "%s: ", program); else sprintf (p, "%s[%u]: ", program, makelevel); p += strlen (p); va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, "\n"); assert (fmtbuf.buffer[len-1] == '\0'); outputs (1, fmtbuf.buffer); } /* Print an error message and exit. */ void fatal (const gmk_floc *flocp, size_t len, const char *fmt, ...) { va_list args; const char *stop = _(". Stop.\n"); char *p; len += (strlen (fmt) + strlen (program) + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0) + INTSTR_LENGTH + 8 + strlen (stop) + 1); p = get_buffer (len); if (flocp && flocp->filenm) sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno); else if (makelevel == 0) sprintf (p, "%s: *** ", program); else sprintf (p, "%s[%u]: *** ", program, makelevel); p += strlen (p); va_start (args, fmt); vsprintf (p, fmt, args); va_end (args); strcat (p, stop); assert (fmtbuf.buffer[len-1] == '\0'); outputs (1, fmtbuf.buffer); die (MAKE_FAILURE); } /* Print an error message from errno. */ void perror_with_name (const char *str, const char *name) { const char *err = strerror (errno); OSSS (error, NILF, _("%s%s: %s"), str, name, err); } /* Print an error message from errno and exit. */ void pfatal_with_name (const char *name) { const char *err = strerror (errno); OSS (fatal, NILF, _("%s: %s"), name, err); /* NOTREACHED */ } remake-4.1+dbg1.3~dfsg.1/output.h000066400000000000000000000036421317072305000165110ustar00rootroot00000000000000/* Output to stdout / stderr for GNU make Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 REMAKE_OUTPUT_H #define REMAKE_OUTPUT_H struct output { int out; int err; unsigned int syncout:1; /* True if we want to synchronize output. */ }; extern struct output *output_context; extern unsigned int stdio_traced; #define OUTPUT_SET(_new) do{ output_context = (_new)->syncout ? (_new) : NULL; }while(0) #define OUTPUT_UNSET() do{ output_context = NULL; }while(0) #define OUTPUT_TRACED() do{ stdio_traced = 1; }while(0) #define OUTPUT_IS_TRACED() (!!stdio_traced) FILE *output_tmpfile (char **, const char *); /* Initialize and close a child output structure: if NULL do this program's output (this should only be done once). */ void output_init (struct output *out); void output_close (struct output *out); /* In situations where output may be about to be displayed but we're not sure if we've set it up yet, call this. */ void output_start (void); /* Show a message on stdout or stderr. Will start the output if needed. */ void outputs (int is_err, const char *msg); #ifndef NO_OUTPUT_SYNC int output_tmpfd (void); /* Dump any child output content to stdout, and reset it. */ void output_dump (struct output *out); #endif #endif /*REMAKE_OUTPUT_H*/ remake-4.1+dbg1.3~dfsg.1/po/000077500000000000000000000000001317072305000154115ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/po/.cvsignore000066400000000000000000000001771317072305000174160ustar00rootroot00000000000000*.gmo *.mo *.pot *.po Makefile Makefile.in Makefile.in.in Makevars.template Rules-quot stamp-po *.sed *.sin *.header POTFILES remake-4.1+dbg1.3~dfsg.1/po/.gitignore000066400000000000000000000003721317072305000174030ustar00rootroot00000000000000/*.gmo /*.po /*~ /Makefile /Makefile.in /Makefile.in.in /Makevars.template /POTFILES /Rules-quot /boldquot.sed /en@boldquot.header /en@quot.header /insert-header.sin /make.pot /quot.sed /remake.pot /remove-potcdate.sed /remove-potcdate.sin /stamp-po remake-4.1+dbg1.3~dfsg.1/po/ChangeLog000066400000000000000000000046751317072305000171770ustar00rootroot000000000000002009-09-16 Paul Smith * LINGUAS: Added new translation for Italian (it). 2008-05-17 Paul Smith * LINGUAS: Added new translation for Lithuanian (lt). 2007-08-15 Paul Smith * LINGUAS: The Kinyarwanda (rw) translation has disappeared from the translation site, so remove it. 2006-01-28 Paul D. Smith * LINGUAS: Added new translation for Vietnamese (vi). 2005-07-14 Paul D. Smith * LINGUAS: Added new translation for Indonesian (id). 2005-05-09 Paul D. Smith * POTFILES.in: Add new file vmsjobs.c. 2005-04-06 Paul D. Smith * LINGUAS: Added a new translation for Kinywarwanda (rw). 2005-02-09 Paul D. Smith * LINGUAS: Added a new translation for Irish (ga). 2005-02-01 Paul D. Smith * LINGUAS: Added a new translation for Finnish (fi). 2003-10-18 Paul D. Smith * LINGUAS: Added a new translation for Belarusian (be). 2002-12-19 Paul D. Smith * LINGUAS: Added a new translation for Ukrainian (uk). 2002-10-05 Paul D. Smith * POTFILES.in: Add variable.h as it has a translatable string. 2002-08-08 Paul D. Smith * LINGUAS: Add a new translation for Chinese (simplified) (zh_CN). 2002-08-02 Paul D. Smith * LINGUAS: Add a new translation for Swedish (sv). 2002-04-21 Paul D. Smith * LINGUAS, hr.po: Added new translation: Croatian. * da.po, de.po, es.po, fr.po, gl.po, he.po, ja.po, ko.po, nl.po, pl.po, pt_BR.po, ru.po, tr.po: Moved from i18n to here. * .cvsignore: Moved from i18n to here. * POTFILES.in, LINGUAS, Makevars: Created. Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/po/LINGUAS000066400000000000000000000002751317072305000164420ustar00rootroot00000000000000# Set of available languages: 25 languages be cs da de es fi fr ga gl he hr id it ja ko lt nl pl pt_BR ru sv tr uk vi zh_CN # Can't seem to get en@quot and en@boldquot to build properly? remake-4.1+dbg1.3~dfsg.1/po/Makevars000066400000000000000000000050121317072305000171030ustar00rootroot00000000000000# This is a -*-Makefile-*- # Copyright (C) 2002-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Free Software Foundation, Inc. # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = bug-make@gnu.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = remake-4.1+dbg1.3~dfsg.1/po/POTFILES.in000066400000000000000000000020011317072305000171570ustar00rootroot00000000000000# List of source files containing translatable strings. # Copyright (C) 2000-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . ar.c arscan.c commands.c debug.c dir.c expand.c file.c function.c getopt.c guile.c hash.c implicit.c job.c job.h load.c main.c makeint.h misc.c output.c print.c read.c remake.c remote-cstms.c rule.c signame.c strcache.c variable.c variable.h vpath.c remake-4.1+dbg1.3~dfsg.1/prepare_w32.bat000066400000000000000000000005051317072305000176140ustar00rootroot00000000000000@echo off @echo Windows32 CVS build preparation of config.h.W32 and NMakefile. if not exist config.h.W32 copy config.h.W32.template config.h.W32 if not exist config.h copy config.h.W32 config.h if not exist NMakefile copy NMakefile.template NMakefile @echo Preparation complete. Run build_w32.bat to compile and link. remake-4.1+dbg1.3~dfsg.1/print.c000066400000000000000000000262711317072305000163030ustar00rootroot00000000000000/* Output or logging functions for GNU Make. Copyright (C) 2005, 2007, 2008 R. Bernstein This file is part of GNU Make (remake variant). Copyright (C) 2004, 2005, 2007, 2008, Free Software Foundation, Inc. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "makeint.h" #include "make.h" #include "main.h" #include "commands.h" #include "debugger/cmd.h" #include "debug.h" #include "dep.h" #include "read.h" #include "print.h" #include /* Think of the below not as an enumeration but as #defines done in a way that we'll be able to use the value in a gdb. */ enum debug_print_enums_e debug_print_enums1; /* Write a message indicating what directory we are in and the make level number. */ static void err_log_working_directory (void) { static char *buf = NULL; static unsigned int len = 0; unsigned int need; const char *fmt; char *p; /* Get enough space for the longest possible output. */ need = strlen (program) + INTSTR_LENGTH + 2 + 1; if (starting_directory) need += strlen (starting_directory); /* Use entire sentences to give the translators a fighting chance. */ if (makelevel == 0) if (starting_directory == 0) fmt = _("%s\n"); else fmt = _("%s: directory '%s'\n"); else if (starting_directory == 0) fmt = _("%s[%u]: unknown directory\n"); else fmt = _("%s[%u]: directory '%s'\n"); need += strlen (fmt); if (need > len) { buf = xrealloc (buf, need); len = need; } p = buf; if (print_data_base_flag) { *(p++) = '#'; *(p++) = ' '; } if (makelevel == 0) if (starting_directory == 0) sprintf (p, fmt , program); else sprintf (p, fmt, program, starting_directory); else if (starting_directory == 0) sprintf (p, fmt, program, makelevel); else sprintf (p, fmt, program, makelevel, starting_directory); outputs (0, buf); } void err_with_stack (target_stack_node_t *p_call, const char *fmt, ...) { va_list args; gmk_floc *p_floc = NULL; file_t *p_target = NULL; if (p_call && p_call->p_target) { p_target = p_call->p_target; p_floc = &(p_target->floc); } if (p_floc && p_floc->filenm) fprintf (stderr, "%s:%lu: ", p_floc->filenm, p_floc->lineno); else { err_log_working_directory (); if (makelevel == 0) fprintf (stderr, "%s: ", program); else fprintf (stderr, "%s[%u]: ", program, makelevel); } va_start (args, fmt); vfprintf (stderr, fmt, args); va_end (args); putc ('\n', stderr); if (!no_extended_errors) { if (p_call) { putc ('\n', stdout); print_target_stack(p_call, -1, MAX_STACK_SHOW); } else if (p_stack_floc_top) { putc ('\n', stdout); print_floc_stack(-1, MAX_STACK_SHOW); } } fflush (stdout); fflush (stderr); if (debugger_on_error & DEBUGGER_ON_ERROR) enter_debugger(p_call, p_target, -1, DEBUG_ERROR_HIT); } /* Print an error message and exit. */ void fatal_err (target_stack_node_t *p_call, const char *fmt, ...) { va_list args; gmk_floc *p_floc = NULL; file_t *p_target = NULL; err_log_working_directory (); if (p_call && p_call->p_target) { p_target = p_call->p_target; p_floc = &(p_target->floc); } if (p_floc && p_floc->filenm) fprintf (stderr, "%s:%lu: *** ", p_floc->filenm, p_floc->lineno); else if (makelevel == 0) fprintf (stderr, "%s: *** ", program); else fprintf (stderr, "%s[%u]: *** ", program, makelevel); va_start (args, fmt); vfprintf (stderr, fmt, args); va_end (args); fputs (_(". Stop.\n"), stderr); if (!no_extended_errors) { if (p_call) print_target_stack(p_call, -1, MAX_STACK_SHOW); else if (p_stack_floc_top) print_floc_stack(-1, MAX_STACK_SHOW); } if ( (debugger_on_error & DEBUGGER_ON_FATAL) || debugger_enabled ) enter_debugger(p_call, p_target, 2, DEBUG_ERROR_HIT); die (MAKE_FAILURE); } #ifndef HAVE_STRERROR #undef strerror char * strerror (int errnum) { extern int errno, sys_nerr; #ifndef __DECC extern char *sys_errlist[]; #endif static char buf[] = "Unknown error 12345678901234567890"; if (errno < sys_nerr) return sys_errlist[errnum]; sprintf (buf, _("Unknown error %d"), errnum); return buf; } #endif /*! Under -d, write a message describing the current IDs. */ void log_access (char *flavor) { if (! ISDB (DB_JOBS)) return; /* All the other debugging messages go to stdout, but we write this one to stderr because it might be run in a child fork whose stdout is piped. */ fprintf (stderr, _("%s: user %lu (real %lu), group %lu (real %lu)\n"), flavor, (unsigned long) geteuid (), (unsigned long) getuid (), (unsigned long) getegid (), (unsigned long) getgid ()); fflush (stderr); } /*! Display a variable and its value. */ void print_variable (variable_t *p_v) { if (p_v) { const char *psz_origin = origin2str(p_v->origin); if (NULL != p_v->fileinfo.filenm) { printf(_("%s:%lu (origin: %s) %s = %s\n"), p_v->fileinfo.filenm, p_v->fileinfo.lineno, psz_origin, p_v->name, p_v->value); } else { printf("(origin %s) %s = %s\n", psz_origin, p_v->name, p_v->value); } } } /*! Display a variable and its value with all substitutions included. */ void print_variable_expand (variable_t *p_v) { if (p_v) { const char *psz_origin = origin2str(p_v->origin); if (NULL != p_v->fileinfo.filenm) { printf(_("%s:%lu (origin: %s) %s := %s\n"), p_v->fileinfo.filenm, p_v->fileinfo.lineno, psz_origin, p_v->name, variable_expand(p_v->value)); } else { printf("(origin %s) %s := %s\n", psz_origin, p_v->name, variable_expand(p_v->value)); } } } /*! Show a command before executing it. */ extern void print_target_prefix (const char *p_name) { printf(" %s", p_name); if (makelevel != 0) { printf ("[%u]", makelevel); } } /*! Show target information: location and name. */ extern void print_file_target_prefix (const file_t *p_target) { print_floc_prefix(&(p_target->floc)); print_target_prefix(p_target->name); } /*! Show a command before executing it. */ extern void print_floc_prefix (const gmk_floc *p_floc) { if (!p_floc) return; if (p_floc->filenm) { if (!basename_filenames && strlen(p_floc->filenm) && p_floc->filenm[0] != '/') printf("%s/", starting_directory); printf("%s:%lu", p_floc->filenm, p_floc->lineno); } else { if (!basename_filenames) printf("%s/", starting_directory); printf("??:%lu", p_floc->lineno); } } /*! Show a command before executing it. */ extern debug_return_t print_child_cmd (child_t *p_child, target_stack_node_t *p) { debug_return_t rc = continue_execution; if (!p_child) return continue_execution; if (i_debugger_stepping || p_child->file->tracing) { debug_enter_reason_t reason = DEBUG_STEP_HIT; if (i_debugger_stepping) reason = DEBUG_STEP_HIT; else if (p_child->file->tracing & BRK_BEFORE_PREREQ) reason = DEBUG_BRKPT_BEFORE_PREREQ; else if (p_child->file->tracing & BRK_BEFORE_PREREQ) reason = DEBUG_BRKPT_AFTER_PREREQ; rc=enter_debugger(p, p_child->file, 0, reason); } return rc; } void print_target_stack_entry (const file_t *p_target, int i, int i_pos) { gmk_floc floc; const char *psz_target_name = (p_target && p_target->name) ? p_target->name : "(null)"; /* If we don't have a line recorded for the target, but we do have one for the commands it runs, use that. */ if (p_target->floc.filenm) { memcpy(&floc, &(p_target->floc), sizeof(gmk_floc)); } else if (p_target->cmds) { memcpy(&floc, &(p_target->cmds->fileinfo.filenm), sizeof(gmk_floc)); /* HACK: is it okay to assume that the target is on the line before the first command? Or should we list the line that the command starts on - so we know we've faked the location? */ floc.lineno--; } else { floc.filenm = NULL; } if (floc.filenm) { if (i_pos != -1) { printf("%s", (i == i_pos) ? "=>" : " "); } printf ("#%d %s at ", i, psz_target_name); print_floc_prefix(&floc); } else { if (i_pos != -1) { printf("%s", (i == i_pos) ? "=>" : " "); } if (p_target->phony) printf ("#%d %s (.PHONY target)", i, psz_target_name); else printf ("#%d %s at ??", i, psz_target_name); } printf ("\n"); } /*! Display the target stack. i_pos is the position we are currently. i_max is the maximum number of entries to show. */ extern void print_target_stack (target_stack_node_t *p, int i_pos, int i_max) { int i=0; for ( ; p && i < i_max ; i++, p = p->p_parent ) { print_target_stack_entry (p->p_target, i, i_pos); } } /*! Display the Makefile read stack. i_pos is the position we are currently. i_max is the maximum number of entries to show. */ extern void print_floc_stack (int i_pos, int i_max) { int i=0; floc_stack_node_t *p; printf("\n"); for ( p=p_stack_floc_top; p && i < i_max ; i++, p = p->p_parent ) { if (i_pos != -1) { printf("%s", (i == i_pos) ? "=>" : " "); } printf ("#%d ", i); if (p->p_floc->filenm) { print_floc_prefix(p->p_floc); } printf ("\n"); } } /*! Print the file information. */ void print_file (file_t *p_file) { char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1]; printf("File %s:\n", p_file->name); file_timestamp_sprintf (buf, p_file->last_mtime); printf("\tLast modified: %s\n", buf); if (p_file->mtime_before_update != p_file->last_mtime) { file_timestamp_sprintf (buf, p_file->mtime_before_update); printf("\tBefore update: %s\n", buf); } printf("\tNumber of lines: %u\n", p_file->nlines); } /*! Print the list makefiles read by read_makefiles(). */ bool print_read_makefiles(const char *psz_filename) { dep_t *p_dep; if (!read_makefiles) return false; if (NULL == psz_filename) { for (p_dep = read_makefiles; p_dep; p_dep = p_dep->next) { if (p_dep->file) { print_file(p_dep->file); } } return true; } else { for (p_dep = read_makefiles; p_dep; p_dep = p_dep->next) { if (p_dep->file && 0 == strcmp(p_dep->file->name, psz_filename)) { print_file(p_dep->file); return true; } } } return false; } /*! Print the command line used to invoke Make. */ void print_cmdline (void) { unsigned int i; printf(_("Command-line invocation:")); printf("\n\t\""); if (global_argv[1]) { printf("%s", argv0); for (i = 1; global_argv[i]; i++) { printf(" %s", global_argv[i]); } printf("\""); } else { printf(_(" none")); } printf("\n"); } /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/print.h000066400000000000000000000067241317072305000163110ustar00rootroot00000000000000/* $Id: print.h,v 1.10 2005/12/23 03:29:34 rockyb Exp $ Copyright (C) 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2008 R. Bernstein This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file print.h * * \brief Header for output or logging functions for GNU Make. */ #ifndef PRINT_H #define PRINT_H #include "variable.h" #include "job.h" #include "trace.h" /*! Versions of error and fatal with the ability to show call-stack. */ void err_with_stack (target_stack_node_t *p_call, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); void fatal_err (target_stack_node_t *p_call, const char *fmt, ...); /* Think of the below not as an enumeration but as #defines done in a way that we'll be able to use the value in a gdb. */ enum debug_print_enums_e { MAX_STACK_SHOW = 1000, } debug_print_enums1; /*! Under -d, write a message describing the current IDs. */ extern void log_access (char *flavor); /*! Write a message indicating that we've just entered or left (according to ENTERING) the current directory. */ extern void log_working_directory (int); /*! Print an error message from errno. */ extern void perror_with_name (const char *, const char *); /*! Print an error message from errno and exit. */ extern void pfatal_with_name_err (const char *psz_name, int errnum); /*! Print an error message from errno and exit. */ extern void pfatal_with_name (const char *psz_name); /*! Display a variable and its value. */ extern void print_variable (variable_t *p_v); /*! Display a variable and its value with all substitutions included. */ extern void print_variable_expand (variable_t *p_v); /*! Display common file target prefix message output file target. */ extern void print_file_target_prefix (const file_t *p_target); /*! Display common target prefix message. */ extern void print_target_prefix (const char *p_name); /*! Display common prefix message output file target. */ extern void print_floc_prefix (const gmk_floc *p_floc); /*! Display common prefix message output file target. */ extern debug_return_t print_child_cmd (child_t *p_child, target_stack_node_t *p); extern void print_target_stack_entry(const file_t *p_target, int i, int i_pos); /*! Display the target stack i_pos is the position we are currently. i_max is the maximum number of entries to show. */ extern void print_target_stack (target_stack_node_t *p, int i_pos, int i_max); /*! Display the Makefile read stack. i_pos is the position we are currently. i_max is the maximum number of entries to show. */ extern void print_floc_stack (int i_pos, int i_max); /*! Print the list makefiles read by read_makefiles(). */ extern bool print_read_makefiles(const char *psz_filename); /*! Print the command line used to invode this program */ extern void print_cmdline (void); #endif /*PRINT_H*/ remake-4.1+dbg1.3~dfsg.1/profile.c000066400000000000000000000203061317072305000166000ustar00rootroot00000000000000/* Copyright (C) 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Compile with: gcc -g3 -I . -c -DSTANDALONE profile.c -o test-profile.o make mock.o gcc mock.o version.o alloc.o globals.o misc.o output.o file_basic.o hash.o strcache.o test-profile.o -o test-profile */ #include #include #include #include #include "profile.h" #include "hash.h" /* #define DEBUG_PROFILE */ /*! \brief Node for an item in the target call stack */ typedef struct profile_call { const file_t *p_target; struct profile_call *p_next; } profile_call_t; struct profile_entry { uint64_t elapsed_time; /* runtime in milliseconds */ const char *name; gmk_floc floc; /* location in Makefile - for tracing */ profile_call_t *calls; /* List of targets this target calls. */ }; typedef struct profile_entry profile_entry_t; static struct hash_table profile_table; static unsigned long profile_table_entry_hash_1 (const void *key) { return_ISTRING_HASH_1 (((profile_entry_t *) key)->name); } static unsigned long profile_table_entry_hash_2 (const void *key) { return_ISTRING_HASH_2 (((profile_entry_t *) key)->name); } static int profile_hash_cmp (const void *x, const void *y) { return_ISTRING_COMPARE (((profile_entry_t *) x)->name, ((profile_entry_t *) y)->name); } static profile_entry_t * add_profile_entry (const file_t *target) { /* Look up the string in the hash. If it's there, return it. */ profile_entry_t *new; profile_entry_t **slot; profile_entry_t *profile_entry; new = xcalloc (sizeof (profile_entry_t)); new->name = target->name; slot = (profile_entry_t **) hash_find_slot (&profile_table, new); profile_entry = *slot; if (!HASH_VACANT (profile_entry)) { free(new); return profile_entry; } /* Not there yet. So finish initializing data and add it into the profile hash table. */ new->calls = NULL; memcpy(&(new->floc), &(target->floc), sizeof(gmk_floc)); hash_insert_at (&profile_table, new, slot); return new; } #define CALLGRIND_FILE_PREFIX "callgrind.out." #define CALLGRIND_FILE_TEMPLATE CALLGRIND_FILE_PREFIX "%d" /* + 10 is more than enough since 2**64 ~= 10**9 */ #define CALLGRIND_FILENAME_LEN sizeof(CALLGRIND_FILE_PREFIX) + 20 char callgrind_fname[CALLGRIND_FILENAME_LEN]; static FILE *callgrind_fd; #define CALLGRIND_PREAMBLE_TEMPLATE1 "version: 1\n\ creator: %s\n" #define CALLGRIND_PREAMBLE_TEMPLATE2 "pid: %u\n\ \n\ desc: Trigger: %s\n\ desc: Node: Targets\n\ \n\ positions: line\n\ events: 100usec\n" #ifndef HAVE_GETTIMEOFDAY # error Somebody has to work out how to handle if getimeofday is not around #endif extern bool get_time(struct timeval *t) { return (0 != gettimeofday(t, NULL)); } static inline uint64_t time_in_100micro(struct timeval *time) { return ((time->tv_sec * (uint64_t)10000) + (uint64_t) (time->tv_usec / 100)); } extern uint64_t time_diff(struct timeval *start_time, struct timeval *finish_time) { struct timeval diff_time; diff_time.tv_sec = finish_time->tv_sec - start_time->tv_sec; diff_time.tv_usec = finish_time->tv_usec; if (diff_time.tv_usec < start_time->tv_usec) { diff_time.tv_usec += 1000000; diff_time.tv_sec--; } diff_time.tv_usec -= start_time->tv_usec; return time_in_100micro(&diff_time); } static struct timeval program_start_time; static struct timeval program_finish_time; static bool time_error; static pid_t callgrind_pid; extern bool init_callgrind(const char *creator, const char *const *argv) { size_t len; unsigned int i; callgrind_pid = getpid(); len = sprintf(callgrind_fname, CALLGRIND_FILE_TEMPLATE, callgrind_pid); time_error = get_time(&program_start_time); if (len >= CALLGRIND_FILENAME_LEN) { printf("Error in generating name\n"); return false; } callgrind_fd = fopen(callgrind_fname, "w"); if (NULL == callgrind_fd) { printf("Error in opening callgrind file %s\n", callgrind_fname); return false; } hash_init (&profile_table, 1000, profile_table_entry_hash_1, profile_table_entry_hash_2, profile_hash_cmp); fprintf(callgrind_fd, CALLGRIND_PREAMBLE_TEMPLATE1, creator); fprintf(callgrind_fd, "cmd:"); for (i = 0; argv[i]; i++) { fprintf(callgrind_fd, " %s", argv[i]); } fprintf(callgrind_fd, "\n"); return true; } #if 0 /* Could use this for name compression */ static unsigned int next_file_num = 0; static unsigned int next_fn_num = 1; #endif extern void add_target(file_t *target, file_t *prev) { profile_entry_t *p = add_profile_entry(target); p->elapsed_time = target->elapsed_time; if (prev) { profile_entry_t *q = add_profile_entry(prev); if (q) { profile_call_t *new = CALLOC(profile_call_t, 1); new->p_target = target; new->p_next = q->calls; q->calls = new; } } } #ifdef DEBUG_PROFILE static void print_profile_entry (const void *item) { const profile_entry_t *p = item; profile_call_t *c; printf("name: %s, file: %s, line: %" PRIu64 ", time: %" PRIu64 "\n", p->name, p->floc.filenm, p->floc.lineno, p->elapsed_time); for (c = p->calls; c; c = c->p_next) { printf("calls: %s\n", c->p_target->name); } } /* Print all profile entries */ static void print_profile(struct hash_table *hash_table) { hash_map (hash_table, print_profile_entry); } #endif static void callgrind_profile_entry (const void *item) { const profile_entry_t *p = item; profile_call_t *c; if (p->floc.filenm) fprintf(callgrind_fd, "fl=%s\n\n", p->floc.filenm); fprintf(callgrind_fd, "fn=%s\n", p->name); fprintf(callgrind_fd, "%" PRIu64 " %" PRIu64 "\n", (uint64_t) p->floc.lineno, p->elapsed_time == 0 ? 1 : p->elapsed_time); for (c = p->calls; c; c = c->p_next) { if (c->p_target->floc.filenm) fprintf(callgrind_fd, "cfi=%s\n", c->p_target->floc.filenm); fprintf(callgrind_fd, "cfn=%s\n", c->p_target->name); fprintf(callgrind_fd, "calls=1 %" PRIu64 "\n", (uint64_t) p->floc.lineno); fprintf(callgrind_fd, "%" PRIu64 " %" PRIu64 "\n", (uint64_t) p->floc.lineno, c->p_target->elapsed_time == 0 ? 1 : c->p_target->elapsed_time); } fprintf(callgrind_fd, "\n"); } /* Print all profile entries */ void callgrind_profile_data(struct hash_table *hash_table) { hash_map (hash_table, callgrind_profile_entry); } extern void close_callgrind(const char *program_status) { fprintf(callgrind_fd, CALLGRIND_PREAMBLE_TEMPLATE2, callgrind_pid, program_status); if (!time_error) { time_error = time_error || get_time(&program_finish_time); } if (!time_error) { fprintf(callgrind_fd, "summary: %" PRIu64 "\n\n", time_diff(&program_start_time, &program_finish_time)); } #ifdef DEBUG_PROFILE print_profile(&profile_table); #endif callgrind_profile_data(&profile_table); printf("Created callgrind profiling data file: %s\n", callgrind_fname); fclose(callgrind_fd); } #ifdef STANDALONE #include "config.h" #include "types.h" int main(int argc, const char * const* argv) { bool rc = init_callgrind(PACKAGE_TARNAME " " PACKAGE_VERSION, argv); init_hash_files(); if (rc) { file_t *target = enter_file("Makefile"); file_t *target2, *target3; target->floc.filenm = "Makefile"; target2 = enter_file("all"); target2->floc.filenm = "Makefile"; target2->floc.lineno = 5; target2->elapsed_time = 500; add_target(target2, NULL); target3 = enter_file("all-recursive"); target3->floc.filenm = "Makefile"; target3->floc.lineno = 5; target3->elapsed_time = 1000; add_target(target3, target2); close_callgrind("Program termination"); } return rc; } #endif remake-4.1+dbg1.3~dfsg.1/profile.h000066400000000000000000000021531317072305000166050ustar00rootroot00000000000000/* Copyright (C) 2015 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "filedef.h" extern bool init_callgrind(const char *creator, const char *const *argv); extern void add_target(file_t *target, file_t *prev); extern void close_callgrind(const char *program_status); extern bool get_time(struct timeval *t); extern uint64_t time_diff(struct timeval *start_time, struct timeval *finish_time); remake-4.1+dbg1.3~dfsg.1/profile/000077500000000000000000000000001317072305000164335ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/profile/README.md000066400000000000000000000015131317072305000177120ustar00rootroot00000000000000Profiling --------- You can get timing and callgraph information for a specific *remake* run by using the `--profile` option. When that is used, the file `callgrind.out`.*pid* is produced and this is in the file format that `valgrind --tool=callgrind` uses. See the [callgrind format manual](http://valgrind.org/docs/manual/cl-format.html) for some information on this. Programs that can interpret this are: * [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html) * [gprof2dot](http://github.com/jrfonseca/gprof2dot) * [callgrind-annotate](http://valgrind.org/docs/manual/cl-manual.html#cl-manual.callgrind_annotate-options) If there are other programs out there, let me know and I'll add to the list above. To assist using *graph2dot* to produce a *png* file, I've put together a little shell script to perform a pipe to dot. remake-4.1+dbg1.3~dfsg.1/profile/call2png.sh000077500000000000000000000005401317072305000204730ustar00rootroot00000000000000#!/bin/bash if (( $# != 1 )) ; then echo "Usage $0 callgrind-file" fi callgrind_file=$1 if [[ ! -r $callgrind_file ]] ; then echo "Can't find callgrind-file $callgrind_file" fi png_file=${callgrind_file}.png gprof2dot -f callgrind $callgrind_file | dot -Tpng -o $png_file rc=$? if (( $rc == 0 )) ; then echo "created $png_file" fi exit $rc remake-4.1+dbg1.3~dfsg.1/read.c000066400000000000000000003124341317072305000160610ustar00rootroot00000000000000/* Reading and parsing of makefiles for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "globals.h" #include "debugger/cmd.h" #include #include #include "filedef.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #include "debug.h" #include "hash.h" #ifdef WINDOWS32 #include #include "sub_proc.h" #else /* !WINDOWS32 */ #ifndef _AMIGA #ifndef VMS #include #else struct passwd *getpwnam (char *name); #endif #endif #endif /* !WINDOWS32 */ /* A 'struct ebuffer' controls the origin of the makefile we are currently eval'ing. */ struct ebuffer { char *buffer; /* Start of the current line in the buffer. */ char *bufnext; /* Start of the next line in the buffer. */ char *bufstart; /* Start of the entire buffer. */ unsigned int size; /* Malloc'd size of buffer. */ FILE *fp; /* File, or NULL if this is an internal buffer. */ gmk_floc floc; /* Info on the file in fp (if any). */ }; /* Track the modifiers we can have on variable assignments */ struct vmodifiers { unsigned int assign_v:1; unsigned int define_v:1; unsigned int undefine_v:1; unsigned int export_v:1; unsigned int override_v:1; unsigned int private_v:1; }; /* Types of "words" that can be read in a makefile. */ enum make_word_type { w_bogus, w_eol, w_static, w_variable, w_colon, w_dcolon, w_semicolon, w_varassign }; /* A 'struct conditionals' contains the information describing all the active conditionals in a makefile. The global variable 'conditionals' contains the conditionals information for the current makefile. It is initialized from the static structure 'toplevel_conditionals' and is later changed to new structures for included makefiles. */ struct conditionals { unsigned int if_cmds; /* Depth of conditional nesting. */ unsigned int allocated; /* Elts allocated in following arrays. */ char *ignoring; /* Are we ignoring or interpreting? 0=interpreting, 1=not yet interpreted, 2=already interpreted */ char *seen_else; /* Have we already seen an 'else'? */ }; static struct conditionals toplevel_conditionals; static struct conditionals *conditionals = &toplevel_conditionals; /* Default directories to search for include files in */ static const char *default_include_directories[] = { #if defined(WINDOWS32) && !defined(INCLUDEDIR) /* This completely up to the user when they install MSVC or other packages. This is defined as a placeholder. */ # define INCLUDEDIR "." #endif INCLUDEDIR, #ifndef _AMIGA "/usr/gnu/include", "/usr/local/include", "/usr/include", #endif 0 }; /* List of directories to search for include files in */ static const char **include_directories; /*! The chain of makefiles read by read_makefile. */ extern dep_t *read_makefiles; dep_t *read_makefiles = NULL; /* Maximum length of an element of the above. */ static unsigned int max_incl_len; static int eval_makefile (const char *filename, int flags); static void eval (struct ebuffer *buffer, int flags); static long readline (struct ebuffer *ebuf); static void do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf); static struct variable *do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf); static int conditional_line (char *line, int len, const gmk_floc *flocp); static void record_files (struct nameseq *filenames, const char *pattern, const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, char *target_description, char prefix, const gmk_floc *flocp); static void record_target_var (struct nameseq *filenames, char *defn, enum variable_origin origin, struct vmodifiers *vmod, const gmk_floc *flocp); static enum make_word_type get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length); static void remove_comments (char *line, char **description, char **prev_description, unsigned long lineno); static char *find_char_unquote (char *string, int map); static char *unescape_char (char *string, int c); /* Compare a word, both length and contents. P must point to the word to be tested, and WLEN must be the length. */ #define word1eq(s) (wlen == CSTRLEN (s) && strneq (s, p, CSTRLEN (s))) /* Read in all the makefiles and return a chain of targets to rebuild. */ struct dep * read_all_makefiles (const char **makefiles) { unsigned int num_makefiles = 0; /* Create *_LIST variables, to hold the makefiles, targets, and variables we will be reading. */ define_variable_cname ("MAKEFILE_LIST", "", o_file, 0); if (b_debugger_preread && i_debugger_stepping && !in_debugger) enter_debugger (NULL, NULL, 0, DEBUG_READ_HIT); DB (DB_BASIC, (_("Reading makefiles...\n"))); /* If there's a non-null variable MAKEFILES, its value is a list of files to read first thing. But don't let it prevent reading the default makefiles and don't let the default goal come from there. */ { char *value; char *name, *p; unsigned int length; { /* Turn off --warn-undefined-variables while we expand MAKEFILES. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; value = allocated_variable_expand ("$(MAKEFILES)"); warn_undefined_variables_flag = save; } /* Set NAME to the start of next token and LENGTH to its length. MAKEFILES is updated for finding remaining tokens. */ p = value; while ((name = find_next_token ((const char **)&p, &length)) != 0) { if (*p != '\0') *p++ = '\0'; eval_makefile (name, RM_NO_DEFAULT_GOAL|RM_INCLUDED|RM_DONTCARE); } free (value); } /* Read makefiles specified with -f switches. */ if (makefiles != 0) while (*makefiles != 0) { struct dep *tail = read_makefiles; struct dep *d; if (! eval_makefile (*makefiles, 0)) perror_with_name ("", *makefiles); /* Find the first element eval_makefile() added to read_files. */ d = read_makefiles; while (d->next != tail) d = d->next; /* Reuse the storage allocated for the read_file. */ *makefiles = dep_name (d); ++num_makefiles; ++makefiles; } /* If there were no -f switches, try the default names. */ if (num_makefiles == 0) { static const char *default_makefiles[] = #ifdef VMS /* all lower case since readdir() (the vms version) 'lowercasifies' */ { "makefile.vms", "gnumakefile.", "makefile.", 0 }; #else #ifdef _AMIGA { "GNUmakefile", "Makefile", "SMakefile", 0 }; #else /* !Amiga && !VMS */ #ifdef WINDOWS32 { "GNUmakefile", "makefile", "Makefile", "makefile.mak", 0 }; #else /* !Amiga && !VMS && !WINDOWS32 */ { "GNUmakefile", "makefile", "Makefile", 0 }; #endif /* !Amiga && !VMS && !WINDOWS32 */ #endif /* AMIGA */ #endif /* VMS */ const char **p = default_makefiles; while (*p != 0 && !file_exists_p (*p)) ++p; if (*p != 0) { if (! eval_makefile (*p, 0)) perror_with_name ("", *p); } else { /* No default makefile was found. Add the default makefiles to the 'read_files' chain so they will be updated if possible. */ struct dep *tail = read_makefiles; /* Add them to the tail, after any MAKEFILES variable makefiles. */ while (tail != 0 && tail->next != 0) tail = tail->next; for (p = default_makefiles; *p != 0; ++p) { struct dep *d = alloc_dep (); d->file = enter_file (strcache_add (*p)); d->dontcare = 1; /* Tell update_goal_chain to bail out as soon as this file is made, and main not to die if we can't make this file. */ d->changed = RM_DONTCARE; if (tail == 0) read_makefiles = d; else tail->next = d; tail = d; } if (tail != 0) tail->next = 0; } } return read_makefiles; } /* Install a new conditional and return the previous one. */ static struct conditionals * install_conditionals (struct conditionals *new) { struct conditionals *save = conditionals; memset (new, '\0', sizeof (*new)); conditionals = new; return save; } /* Free the current conditionals and reinstate a saved one. */ static void restore_conditionals (struct conditionals *saved) { /* Free any space allocated by conditional_line. */ free (conditionals->ignoring); free (conditionals->seen_else); /* Restore state. */ conditionals = saved; } static int eval_makefile (const char *filename, int flags) { struct dep *deps; struct ebuffer ebuf; const gmk_floc *curfile; char *expanded = 0; int makefile_errno; ebuf.floc.filenm = filename; /* Use the original file name. */ ebuf.floc.lineno = 1; if (ISDB (DB_VERBOSE|DB_READ_MAKEFILES)) { printf (_("Reading makefile '%s'"), filename); if (flags & RM_NO_DEFAULT_GOAL) printf (_(" (no default goal)")); if (flags & RM_INCLUDED) printf (_(" (search path)")); if (flags & RM_DONTCARE) printf (_(" (don't care)")); if (flags & RM_NO_TILDE) printf (_(" (no ~ expansion)")); puts ("..."); } /* First, get a stream to read. */ /* Expand ~ in FILENAME unless it came from 'include', in which case it was already done. */ if (!(flags & RM_NO_TILDE) && filename[0] == '~') { expanded = remake_tilde_expand (filename); if (expanded != 0) filename = expanded; } ENULLLOOP (ebuf.fp, fopen (filename, "r")); /* Save the error code so we print the right message later. */ makefile_errno = errno; /* Check for unrecoverable errors: out of mem or FILE slots. */ switch (makefile_errno) { #ifdef EMFILE case EMFILE: #endif #ifdef ENFILE case ENFILE: #endif case ENOMEM: { const char *err = strerror (makefile_errno); OS (fatal, reading_file, "%s", err); } } /* If the makefile wasn't found and it's either a makefile from the 'MAKEFILES' variable or an included makefile, search the included makefile search path for this makefile. */ if (ebuf.fp == 0 && (flags & RM_INCLUDED) && *filename != '/') { unsigned int i; for (i = 0; include_directories[i] != 0; ++i) { const char *included = concat (3, include_directories[i], "/", filename); ebuf.fp = fopen (included, "r"); if (ebuf.fp) { filename = included; break; } } } /* Now we have the final name for this makefile. Enter it into the cache. */ filename = strcache_add (filename); /* Add FILENAME to the chain of read makefiles. */ deps = alloc_dep (); deps->next = read_makefiles; read_makefiles = deps; deps->file = lookup_file (filename); if (deps->file == 0) deps->file = enter_file (filename); filename = deps->file->name; deps->changed = flags; if (flags & RM_DONTCARE) deps->dontcare = 1; free (expanded); /* If the makefile can't be found at all, give up entirely. */ if (ebuf.fp == 0) { /* If we did some searching, errno has the error from the last attempt, rather from FILENAME itself. Restore it in case the caller wants to use it in a message. */ errno = makefile_errno; return 0; } /* Set close-on-exec to avoid leaking the makefile to children, such as $(shell ...). */ #ifdef HAVE_FILENO CLOSE_ON_EXEC (fileno (ebuf.fp)); #endif /* Add this makefile to the list. */ do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file, f_append, 0); if (b_debugger_preread && i_debugger_stepping && !in_debugger) { enter_debugger (NULL, NULL, 0, DEBUG_READ_HIT); } /* Evaluate the makefile */ ebuf.size = 200; ebuf.buffer = ebuf.bufnext = ebuf.bufstart = xmalloc (ebuf.size); curfile = reading_file; reading_file = &ebuf.floc; eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL)); reading_file = curfile; deps->file->nlines = ebuf.floc.lineno; fclose (ebuf.fp); free (ebuf.bufstart); alloca (0); return 1; } void eval_buffer (char *buffer, const gmk_floc *floc) { struct ebuffer ebuf; struct conditionals *saved; struct conditionals new; const gmk_floc *curfile; /* Evaluate the buffer */ ebuf.size = strlen (buffer); ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer; ebuf.fp = NULL; if (floc) ebuf.floc = *floc; else if (reading_file) ebuf.floc = *reading_file; else { ebuf.floc.filenm = NULL; ebuf.floc.lineno = 1; } curfile = reading_file; reading_file = &ebuf.floc; saved = install_conditionals (&new); eval (&ebuf, 1); restore_conditionals (saved); reading_file = curfile; alloca (0); } /* Check LINE to see if it's a variable assignment or undefine. It might use one of the modifiers "export", "override", "private", or it might be one of the conditional tokens like "ifdef", "include", etc. If it's not a variable assignment or undefine, VMOD.V_ASSIGN is 0. Returns LINE. Returns a pointer to the first non-modifier character, and sets VMOD based on the modifiers found if any, plus V_ASSIGN is 1. */ static char * parse_var_assignment (const char *line, struct vmodifiers *vmod) { const char *p; memset (vmod, '\0', sizeof (*vmod)); /* Find the start of the next token. If there isn't one we're done. */ line = next_token (line); if (*line == '\0') return (char *)line; p = line; while (1) { int wlen; const char *p2; struct variable v; p2 = parse_variable_definition (p, &v); /* If this is a variable assignment, we're done. */ if (p2) break; /* It's not a variable; see if it's a modifier. */ p2 = end_of_token (p); wlen = p2 - p; if (word1eq ("export")) vmod->export_v = 1; else if (word1eq ("override")) vmod->override_v = 1; else if (word1eq ("private")) vmod->private_v = 1; else if (word1eq ("define")) { /* We can't have modifiers after 'define' */ vmod->define_v = 1; p = next_token (p2); break; } else if (word1eq ("undefine")) { /* We can't have modifiers after 'undefine' */ vmod->undefine_v = 1; p = next_token (p2); break; } else /* Not a variable or modifier: this is not a variable assignment. */ return (char *)line; /* It was a modifier. Try the next word. */ p = next_token (p2); if (*p == '\0') return (char *)line; } /* Found a variable assignment or undefine. */ vmod->assign_v = 1; return (char *)p; } static unsigned long int target_description_lineno = 0; static unsigned long int prev_target_description_lineno = 0; /* Read file FILENAME as a makefile and add its contents to the data base. SET_DEFAULT is true if we are allowed to set the default goal. */ static void eval (struct ebuffer *ebuf, int set_default) { char *collapsed = 0; unsigned int collapsed_length = 0; unsigned int commands_len = 200; char *commands; unsigned int commands_idx = 0; unsigned int cmds_started, tgts_started; int ignoring = 0, in_ignored_define = 0; int no_targets = 0; /* Set when reading a rule without targets. */ struct nameseq *filenames = 0; char *depstr = 0; long nlines = 0; int two_colon = 0; char prefix = cmd_prefix; const char *pattern = 0; const char *pattern_percent; gmk_floc *fstart; gmk_floc fi; static char *target_description; /* Place to store most recent * target description */ static char *prev_target_description; /* Most of the time, we read two targets before processing the first. I think this happens because the second target signals the end of the first target. As a result, we need to save two descriptions to be able to use the previous description for the first target. For the last target of the file though, EOF signals the end of the target so we don't use prev_target_description. */ #define record_waiting_files() \ do \ { \ if (filenames != 0) \ { \ /* Have we seen two descriptions since this target or one? */ \ char *description = target_description_lineno > tgts_started ? \ prev_target_description : target_description; \ fi.lineno = tgts_started; \ record_files (filenames, pattern, pattern_percent, depstr, \ cmds_started, commands, commands_idx, two_colon, \ description, prefix, &fi); \ /* Don't use the target_description values more than once. */ \ if (target_description_lineno > tgts_started) \ prev_target_description = NULL; \ else \ target_description = NULL; \ filenames = 0; \ } \ commands_idx = 0; \ no_targets = 0; \ pattern = 0; \ } while (0) pattern_percent = 0; cmds_started = tgts_started = 1; fstart = &ebuf->floc; fi.filenm = ebuf->floc.filenm; /* Loop over lines in the file. The strategy is to accumulate target names in FILENAMES, dependencies in DEPS and commands in COMMANDS. These are used to define a rule when the start of the next rule (or eof) is encountered. When you see a "continue" in the loop below, that means we are moving on to the next line. If you see record_waiting_files(), then the statement we are parsing also finishes the previous rule. */ commands = xmalloc (200); prev_target_description = NULL; target_description = NULL; while (1) { unsigned int linelen; char *line; unsigned int wlen; char *p; char *p2; struct vmodifiers vmod; /* At the top of this loop, we are starting a brand new line. */ /* Grab the next line to be evaluated */ ebuf->floc.lineno += nlines; nlines = readline (ebuf); /* If there is nothing left to eval, we're done. */ if (nlines < 0) break; line = ebuf->buffer; /* If this is the first line, check for a UTF-8 BOM and skip it. */ if (ebuf->floc.lineno == 1 && line[0] == (char)0xEF && line[1] == (char)0xBB && line[2] == (char)0xBF) { line += 3; if (ISDB(DB_BASIC)) { if (ebuf->floc.filenm) printf (_("Skipping UTF-8 BOM in makefile '%s'\n"), ebuf->floc.filenm); else printf (_("Skipping UTF-8 BOM in makefile buffer\n")); } } /* If this line is empty, skip it. */ if (line[0] == '\0') continue; linelen = strlen (line); /* Check for a shell command line first. If it is not one, we can stop treating cmd_prefix specially. */ if (line[0] == cmd_prefix) { if (no_targets) /* Ignore the commands in a rule with no targets. */ continue; /* If there is no preceding rule line, don't treat this line as a command, even though it begins with a recipe prefix. SunOS 4 make appears to behave this way. */ if (filenames != 0) { if (ignoring) /* Yep, this is a shell command, and we don't care. */ continue; if (commands_idx == 0) cmds_started = ebuf->floc.lineno; /* Append this command line to the line being accumulated. Skip the initial command prefix character. */ if (linelen + commands_idx > commands_len) { commands_len = (linelen + commands_idx) * 2; commands = xrealloc (commands, commands_len); } memcpy (&commands[commands_idx], line + 1, linelen - 1); commands_idx += linelen - 1; commands[commands_idx++] = '\n'; continue; } } /* This line is not a shell command line. Don't worry about whitespace. Get more space if we need it; we don't need to preserve the current contents of the buffer. */ if (collapsed_length < linelen+1) { collapsed_length = linelen+1; free (collapsed); /* Don't need xrealloc: we don't need to preserve the content. */ collapsed = xmalloc (collapsed_length); } strcpy (collapsed, line); /* Collapse continuation lines. */ collapse_continuations (collapsed); remove_comments (collapsed, &target_description, &prev_target_description, ebuf->floc.lineno); /* Get rid if starting space (including formfeed, vtab, etc.) */ p = collapsed; while (isspace ((unsigned char)*p)) ++p; /* See if this is a variable assignment. We need to do this early, to allow variables with names like 'ifdef', 'export', 'private', etc. */ p = parse_var_assignment (p, &vmod); if (vmod.assign_v) { struct variable *v; enum variable_origin origin = vmod.override_v ? o_override : o_file; /* Variable assignment ends the previous rule. */ record_waiting_files (); /* If we're ignoring then we're done now. */ if (ignoring) { if (vmod.define_v) in_ignored_define = 1; continue; } if (vmod.undefine_v) { do_undefine (p, origin, ebuf); continue; } else if (vmod.define_v) v = do_define (p, origin, ebuf); else v = try_variable_definition (fstart, p, origin, 0); assert (v != NULL); if (vmod.export_v) v->export = v_export; if (vmod.private_v) v->private_var = 1; /* This line has been dealt with. */ continue; } /* If this line is completely empty, ignore it. */ if (*p == '\0') continue; p2 = end_of_token (p); wlen = p2 - p; p2 = next_token (p2); /* If we're in an ignored define, skip this line (but maybe get out). */ if (in_ignored_define) { /* See if this is an endef line (plus optional comment). */ if (word1eq ("endef") && STOP_SET (*p2, MAP_COMMENT|MAP_NUL)) in_ignored_define = 0; continue; } /* Check for conditional state changes. */ { int i = conditional_line (p, wlen, fstart); if (i != -2) { if (i == -1) O (fatal, fstart, _("invalid syntax in conditional")); ignoring = i; continue; } } /* Nothing to see here... move along. */ if (ignoring) continue; /* Manage the "export" keyword used outside of variable assignment as well as "unexport". */ if (word1eq ("export") || word1eq ("unexport")) { int exporting = *p == 'u' ? 0 : 1; /* Export/unexport ends the previous rule. */ record_waiting_files (); /* (un)export by itself causes everything to be (un)exported. */ if (*p2 == '\0') export_all_variables = exporting; else { unsigned int l; const char *cp; char *ap; /* Expand the line so we can use indirect and constructed variable names in an (un)export command. */ cp = ap = allocated_variable_expand (p2); for (p = find_next_token (&cp, &l); p != 0; p = find_next_token (&cp, &l)) { struct variable *v = lookup_variable (p, l); if (v == 0) v = define_variable_global (p, l, "", o_file, 0, fstart); v->export = exporting ? v_export : v_noexport; } free (ap); } continue; } /* Handle the special syntax for vpath. */ if (word1eq ("vpath")) { const char *cp; char *vpat; unsigned int l; /* vpath ends the previous rule. */ record_waiting_files (); cp = variable_expand (p2); p = find_next_token (&cp, &l); if (p != 0) { vpat = xstrndup (p, l); p = find_next_token (&cp, &l); /* No searchpath means remove all previous selective VPATH's with the same pattern. */ } else /* No pattern means remove all previous selective VPATH's. */ vpat = 0; construct_vpath_list (vpat, p); free (vpat); continue; } /* Handle include and variants. */ if (word1eq ("include") || word1eq ("-include") || word1eq ("sinclude")) { /* We have found an 'include' line specifying a nested makefile to be read at this point. */ struct conditionals *save; struct conditionals new_conditionals; struct nameseq *files; /* "-include" (vs "include") says no error if the file does not exist. "sinclude" is an alias for this from SGI. */ int noerror = (p[0] != 'i'); /* Include ends the previous rule. */ record_waiting_files (); p = allocated_variable_expand (p2); /* If no filenames, it's a no-op. */ if (*p == '\0') { free (p); continue; } /* Parse the list of file names. Don't expand archive references! */ p2 = p; files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL, PARSEFS_NOAR); free (p); /* Save the state of conditionals and start the included makefile with a clean slate. */ save = install_conditionals (&new_conditionals); /* Record the rules that are waiting so they will determine the default goal before those in the included makefile. */ record_waiting_files (); /* Read each included makefile. */ while (files != 0) { struct nameseq *next = files->next; const char *name = files->name; int r; free_ns (files); files = next; r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE | (noerror ? RM_DONTCARE : 0) | (set_default ? 0 : RM_NO_DEFAULT_GOAL))); if (!r && !noerror) { const char *err = strerror (errno); OSS (error, fstart, "%s: %s", name, err); } } /* Restore conditional state. */ restore_conditionals (save); continue; } /* Handle the load operations. */ if (word1eq ("load") || word1eq ("-load")) { /* A 'load' line specifies a dynamic object to load. */ struct nameseq *files; int noerror = (p[0] == '-'); /* Load ends the previous rule. */ record_waiting_files (); p = allocated_variable_expand (p2); /* If no filenames, it's a no-op. */ if (*p == '\0') { free (p); continue; } /* Parse the list of file names. Don't expand archive references or strip "./" */ p2 = p; files = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_NUL, NULL, PARSEFS_NOAR); free (p); /* Load each file. */ while (files != 0) { struct nameseq *next = files->next; const char *name = files->name; struct dep *deps; int r; /* Load the file. 0 means failure. */ r = load_file (&ebuf->floc, &name, noerror); if (! r && ! noerror) OS (fatal, &ebuf->floc, _("%s: failed to load"), name); free_ns (files); files = next; /* Return of -1 means a special load: don't rebuild it. */ if (r == -1) continue; /* It succeeded, so add it to the list "to be rebuilt". */ deps = alloc_dep (); deps->next = read_makefiles; read_makefiles = deps; deps->file = lookup_file (name); if (deps->file == 0) deps->file = enter_file (name); deps->file->loaded = 1; } continue; } /* This line starts with a tab but was not caught above because there was no preceding target, and the line might have been usable as a variable definition. But now we know it is definitely lossage. */ if (line[0] == cmd_prefix) O (fatal, fstart, _("recipe commences before first target")); /* This line describes some target files. This is complicated by the existence of target-specific variables, because we can't expand the entire line until we know if we have one or not. So we expand the line word by word until we find the first ':', then check to see if it's a target-specific variable. In this algorithm, 'lb_next' will point to the beginning of the unexpanded parts of the input buffer, while 'p2' points to the parts of the expanded buffer we haven't searched yet. */ { enum make_word_type wtype; char *cmdleft, *semip, *lb_next; unsigned int plen = 0; char *colonp; const char *end, *beg; /* Helpers for whitespace stripping. */ /* Record the previous rule. */ record_waiting_files (); tgts_started = fstart->lineno; /* Search the line for an unquoted ; that is not after an unquoted #. */ cmdleft = find_char_unquote (line, MAP_SEMI|MAP_COMMENT|MAP_VARIABLE); if (cmdleft != 0 && *cmdleft == '#') { /* We found a comment before a semicolon. */ *cmdleft = '\0'; cmdleft = 0; } else if (cmdleft != 0) /* Found one. Cut the line short there before expanding it. */ *(cmdleft++) = '\0'; semip = cmdleft; collapse_continuations (line); /* We can't expand the entire line, since if it's a per-target variable we don't want to expand it. So, walk from the beginning, expanding as we go, and looking for "interesting" chars. The first word is always expandable. */ wtype = get_next_mword (line, NULL, &lb_next, &wlen); switch (wtype) { case w_eol: if (cmdleft != 0) O (fatal, fstart, _("missing rule before recipe")); /* This line contained something but turned out to be nothing but whitespace (a comment?). */ continue; case w_colon: case w_dcolon: /* We accept and ignore rules without targets for compatibility with SunOS 4 make. */ no_targets = 1; continue; default: break; } p2 = variable_expand_string (NULL, lb_next, wlen); while (1) { lb_next += wlen; if (cmdleft == 0) { /* Look for a semicolon in the expanded line. */ cmdleft = find_char_unquote (p2, MAP_SEMI); if (cmdleft != 0) { unsigned long p2_off = p2 - variable_buffer; unsigned long cmd_off = cmdleft - variable_buffer; char *pend = p2 + strlen (p2); /* Append any remnants of lb, then cut the line short at the semicolon. */ *cmdleft = '\0'; /* One school of thought says that you shouldn't expand here, but merely copy, since now you're beyond a ";" and into a command script. However, the old parser expanded the whole line, so we continue that for backwards-compatibility. Also, it wouldn't be entirely consistent, since we do an unconditional expand below once we know we don't have a target-specific variable. */ (void)variable_expand_string (pend, lb_next, (long)-1); lb_next += strlen (lb_next); p2 = variable_buffer + p2_off; cmdleft = variable_buffer + cmd_off + 1; } } colonp = find_char_unquote (p2, MAP_COLON); #ifdef HAVE_DOS_PATHS /* The drive spec brain-damage strikes again... */ /* Note that the only separators of targets in this context are whitespace and a left paren. If others are possible, they should be added to the string in the call to index. */ while (colonp && (colonp[1] == '/' || colonp[1] == '\\') && colonp > p2 && isalpha ((unsigned char)colonp[-1]) && (colonp == p2 + 1 || strchr (" \t(", colonp[-2]) != 0)) colonp = find_char_unquote (colonp + 1, MAP_COLON); #endif if (colonp != 0) break; wtype = get_next_mword (lb_next, NULL, &lb_next, &wlen); if (wtype == w_eol) break; p2 += strlen (p2); *(p2++) = ' '; p2 = variable_expand_string (p2, lb_next, wlen); /* We don't need to worry about cmdleft here, because if it was found in the variable_buffer the entire buffer has already been expanded... we'll never get here. */ } p2 = next_token (variable_buffer); /* If the word we're looking at is EOL, see if there's _anything_ on the line. If not, a variable expanded to nothing, so ignore it. If so, we can't parse this line so punt. */ if (wtype == w_eol) { if (*p2 == '\0') continue; /* There's no need to be ivory-tower about this: check for one of the most common bugs found in makefiles... */ if (cmd_prefix == '\t' && strneq (line, " ", 8)) O (fatal, fstart, _("missing separator (did you mean TAB instead of 8 spaces?)")); else O (fatal, fstart, _("missing separator")); } /* Make the colon the end-of-string so we know where to stop looking for targets. Start there again once we're done. */ *colonp = '\0'; filenames = PARSE_SIMPLE_SEQ (&p2, struct nameseq); *colonp = ':'; p2 = colonp; if (!filenames) { /* We accept and ignore rules without targets for compatibility with SunOS 4 make. */ no_targets = 1; continue; } /* This should never be possible; we handled it above. */ assert (*p2 != '\0'); ++p2; /* Is this a one-colon or two-colon entry? */ two_colon = *p2 == ':'; if (two_colon) p2++; /* Test to see if it's a target-specific variable. Copy the rest of the buffer over, possibly temporarily (we'll expand it later if it's not a target-specific variable). PLEN saves the length of the unparsed section of p2, for later. */ if (*lb_next != '\0') { unsigned int l = p2 - variable_buffer; plen = strlen (p2); variable_buffer_output (p2+plen, lb_next, strlen (lb_next)+1); p2 = variable_buffer + l; } p2 = parse_var_assignment (p2, &vmod); if (vmod.assign_v) { /* If there was a semicolon found, add it back, plus anything after it. */ if (semip) { unsigned int l = p2 - variable_buffer; *(--semip) = ';'; collapse_continuations (semip); variable_buffer_output (p2 + strlen (p2), semip, strlen (semip)+1); p2 = variable_buffer + l; } record_target_var (filenames, p2, vmod.override_v ? o_override : o_file, &vmod, fstart); filenames = 0; continue; } /* This is a normal target, _not_ a target-specific variable. Unquote any = in the dependency list. */ find_char_unquote (lb_next, MAP_EQUALS); /* Remember the command prefix for this target. */ prefix = cmd_prefix; /* We have some targets, so don't ignore the following commands. */ no_targets = 0; /* Expand the dependencies, etc. */ if (*lb_next != '\0') { unsigned int l = p2 - variable_buffer; (void) variable_expand_string (p2 + plen, lb_next, (long)-1); p2 = variable_buffer + l; /* Look for a semicolon in the expanded line. */ if (cmdleft == 0) { cmdleft = find_char_unquote (p2, MAP_SEMI); if (cmdleft != 0) *(cmdleft++) = '\0'; } } /* Is this a static pattern rule: 'target: %targ: %dep; ...'? */ p = strchr (p2, ':'); while (p != 0 && p[-1] == '\\') { char *q = &p[-1]; int backslash = 0; while (*q-- == '\\') backslash = !backslash; if (backslash) p = strchr (p + 1, ':'); else break; } #ifdef _AMIGA /* Here, the situation is quite complicated. Let's have a look at a couple of targets: install: dev:make dev:make: make dev:make:: xyz The rule is that it's only a target, if there are TWO :'s OR a space around the :. */ if (p && !(isspace ((unsigned char)p[1]) || !p[1] || isspace ((unsigned char)p[-1]))) p = 0; #endif #ifdef HAVE_DOS_PATHS { int check_again; do { check_again = 0; /* For DOS-style paths, skip a "C:\..." or a "C:/..." */ if (p != 0 && (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1]) && (p == p2 + 1 || strchr (" \t:(", p[-2]) != 0)) { p = strchr (p + 1, ':'); check_again = 1; } } while (check_again); } #endif if (p != 0) { struct nameseq *target; target = PARSE_FILE_SEQ (&p2, struct nameseq, MAP_COLON, NULL, PARSEFS_NOGLOB); ++p2; if (target == 0) O (fatal, fstart, _("missing target pattern")); else if (target->next != 0) O (fatal, fstart, _("multiple target patterns")); pattern_percent = find_percent_cached (&target->name); pattern = target->name; if (pattern_percent == 0) O (fatal, fstart, _("target pattern contains no '%%'")); free_ns (target); } else pattern = 0; /* Strip leading and trailing whitespaces. */ beg = p2; end = beg + strlen (beg) - 1; strip_whitespace (&beg, &end); /* Put all the prerequisites here; they'll be parsed later. */ if (beg <= end && *beg != '\0') depstr = xstrndup (beg, end - beg + 1); else depstr = 0; commands_idx = 0; if (cmdleft != 0) { /* Semicolon means rest of line is a command. */ unsigned int l = strlen (cmdleft); cmds_started = fstart->lineno; /* Add this command line to the buffer. */ if (l + 2 > commands_len) { commands_len = (l + 2) * 2; commands = xrealloc (commands, commands_len); } memcpy (commands, cmdleft, l); commands_idx += l; commands[commands_idx++] = '\n'; } /* Determine if this target should be made default. We used to do this in record_files() but because of the delayed target recording and because preprocessor directives are legal in target's commands it is too late. Consider this fragment for example: foo: ifeq ($(.DEFAULT_GOAL),foo) ... endif Because the target is not recorded until after ifeq directive is evaluated the .DEFAULT_GOAL does not contain foo yet as one would expect. Because of this we have to move the logic here. */ if (set_default && default_goal_var->value[0] == '\0') { struct dep *d; struct nameseq *t = filenames; for (; t != 0; t = t->next) { int reject = 0; const char *name = t->name; /* We have nothing to do if this is an implicit rule. */ if (strchr (name, '%') != 0) break; /* See if this target's name does not start with a '.', unless it contains a slash. */ if (*name == '.' && strchr (name, '/') == 0 #ifdef HAVE_DOS_PATHS && strchr (name, '\\') == 0 #endif ) continue; /* If this file is a suffix, don't let it be the default goal file. */ for (d = suffix_file->deps; d != 0; d = d->next) { register struct dep *d2; if (*dep_name (d) != '.' && streq (name, dep_name (d))) { reject = 1; break; } for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next) { unsigned int l = strlen (dep_name (d2)); if (!strneq (name, dep_name (d2), l)) continue; if (streq (name + l, dep_name (d))) { reject = 1; break; } } if (reject) break; } if (!reject) { define_variable_global (".DEFAULT_GOAL", 13, t->name, o_file, 0, NILF); break; } } } continue; } /* We get here except in the case that we just read a rule line. Record now the last rule we read, so following spurious commands are properly diagnosed. */ record_waiting_files (); } #undef word1eq if (conditionals->if_cmds) O (fatal, fstart, _("missing 'endif'")); /* At eof, record the last rule. */ record_waiting_files (); free (collapsed); free (commands); } /* Remove comments from LINE. This is done by copying the text at LINE onto itself. */ static void remove_comments (char *line, char **target_description, char **prev_target_description, unsigned long lineno) { char *comment; comment = find_char_unquote (line, MAP_COMMENT); if (comment != 0) { if (show_tasks_flag || show_targets_flag) { if (0 == strncmp(comment, "#: ", 3) && target_description) { *prev_target_description = *target_description; prev_target_description_lineno = target_description_lineno; *target_description = xstrdup(&comment[3]); target_description_lineno = lineno; } } /* Cut off the line at the #. */ *comment = '\0'; } } /* Execute a 'undefine' directive. The undefine line has already been read, and NAME is the name of the variable to be undefined. */ static void do_undefine (char *name, enum variable_origin origin, struct ebuffer *ebuf) { char *p, *var; /* Expand the variable name and find the beginning (NAME) and end. */ var = allocated_variable_expand (name); name = next_token (var); if (*name == '\0') O (fatal, &ebuf->floc, _("empty variable name")); p = name + strlen (name) - 1; while (p > name && isblank ((unsigned char)*p)) --p; p[1] = '\0'; undefine_variable_global (name, p - name + 1, origin); free (var); } /* Execute a 'define' directive. The first line has already been read, and NAME is the name of the variable to be defined. The following lines remain to be read. */ static struct variable * do_define (char *name, enum variable_origin origin, struct ebuffer *ebuf) { struct variable *v; struct variable var; gmk_floc defstart; int nlevels = 1; unsigned int length = 100; char *definition = xmalloc (length); unsigned int idx = 0; char *p, *n; defstart = ebuf->floc; p = parse_variable_definition (name, &var); if (p == NULL) /* No assignment token, so assume recursive. */ var.flavor = f_recursive; else { if (var.value[0] != '\0') O (error, &defstart, _("extraneous text after 'define' directive")); /* Chop the string before the assignment token to get the name. */ var.name[var.length] = '\0'; } /* Expand the variable name and find the beginning (NAME) and end. */ n = allocated_variable_expand (name); name = next_token (n); if (name[0] == '\0') O (fatal, &defstart, _("empty variable name")); p = name + strlen (name) - 1; while (p > name && isblank ((unsigned char)*p)) --p; p[1] = '\0'; /* Now read the value of the variable. */ while (1) { unsigned int len; char *line; long nlines = readline (ebuf); /* If there is nothing left to be eval'd, there's no 'endef'!! */ if (nlines < 0) O (fatal, &defstart, _("missing 'endef', unterminated 'define'")); ebuf->floc.lineno += nlines; line = ebuf->buffer; collapse_continuations (line); /* If the line doesn't begin with a tab, test to see if it introduces another define, or ends one. Stop if we find an 'endef' */ if (line[0] != cmd_prefix) { p = next_token (line); len = strlen (p); /* If this is another 'define', increment the level count. */ if ((len == 6 || (len > 6 && isblank ((unsigned char)p[6]))) && strneq (p, "define", 6)) ++nlevels; /* If this is an 'endef', decrement the count. If it's now 0, we've found the last one. */ else if ((len == 5 || (len > 5 && isblank ((unsigned char)p[5]))) && strneq (p, "endef", 5)) { p += 5; remove_comments (p, NULL, NULL, 0); if (*(next_token (p)) != '\0') O (error, &ebuf->floc, _("extraneous text after 'endef' directive")); if (--nlevels == 0) break; } } /* Add this line to the variable definition. */ len = strlen (line); if (idx + len + 1 > length) { length = (idx + len) * 2; definition = xrealloc (definition, length + 1); } memcpy (&definition[idx], line, len); idx += len; /* Separate lines with a newline. */ definition[idx++] = '\n'; } /* We've got what we need; define the variable. */ if (idx == 0) definition[0] = '\0'; else definition[idx - 1] = '\0'; v = do_variable_definition (&defstart, name, definition, origin, var.flavor, 0); free (definition); free (n); return (v); } /* Interpret conditional commands "ifdef", "ifndef", "ifeq", "ifneq", "else" and "endif". LINE is the input line, with the command as its first word. FILENAME and LINENO are the filename and line number in the current makefile. They are used for error messages. Value is -2 if the line is not a conditional at all, -1 if the line is an invalid conditional, 0 if following text should be interpreted, 1 if following text should be ignored. */ static int conditional_line (char *line, int len, const gmk_floc *flocp) { const char *cmdname; enum { c_ifdef, c_ifndef, c_ifeq, c_ifneq, c_else, c_endif } cmdtype; unsigned int i; unsigned int o; /* Compare a word, both length and contents. */ #define word1eq(s) (len == CSTRLEN (s) && strneq (s, line, CSTRLEN (s))) #define chkword(s, t) if (word1eq (s)) { cmdtype = (t); cmdname = (s); } /* Make sure this line is a conditional. */ chkword ("ifdef", c_ifdef) else chkword ("ifndef", c_ifndef) else chkword ("ifeq", c_ifeq) else chkword ("ifneq", c_ifneq) else chkword ("else", c_else) else chkword ("endif", c_endif) else return -2; /* Found one: skip past it and any whitespace after it. */ line = next_token (line + len); #define EXTRATEXT() OS (error, flocp, _("extraneous text after '%s' directive"), cmdname) #define EXTRACMD() OS (fatal, flocp, _("extraneous '%s'"), cmdname) /* An 'endif' cannot contain extra text, and reduces the if-depth by 1 */ if (cmdtype == c_endif) { if (*line != '\0') EXTRATEXT (); if (!conditionals->if_cmds) EXTRACMD (); --conditionals->if_cmds; goto DONE; } /* An 'else' statement can either be simple, or it can have another conditional after it. */ if (cmdtype == c_else) { const char *p; if (!conditionals->if_cmds) EXTRACMD (); o = conditionals->if_cmds - 1; if (conditionals->seen_else[o]) O (fatal, flocp, _("only one 'else' per conditional")); /* Change the state of ignorance. */ switch (conditionals->ignoring[o]) { case 0: /* We've just been interpreting. Never do it again. */ conditionals->ignoring[o] = 2; break; case 1: /* We've never interpreted yet. Maybe this time! */ conditionals->ignoring[o] = 0; break; } /* It's a simple 'else'. */ if (*line == '\0') { conditionals->seen_else[o] = 1; goto DONE; } /* The 'else' has extra text. That text must be another conditional and cannot be an 'else' or 'endif'. */ /* Find the length of the next word. */ for (p = line+1; ! STOP_SET (*p, MAP_SPACE|MAP_NUL); ++p) ; len = p - line; /* If it's 'else' or 'endif' or an illegal conditional, fail. */ if (word1eq ("else") || word1eq ("endif") || conditional_line (line, len, flocp) < 0) EXTRATEXT (); else { /* conditional_line() created a new level of conditional. Raise it back to this level. */ if (conditionals->ignoring[o] < 2) conditionals->ignoring[o] = conditionals->ignoring[o+1]; --conditionals->if_cmds; } goto DONE; } if (conditionals->allocated == 0) { conditionals->allocated = 5; conditionals->ignoring = xmalloc (conditionals->allocated); conditionals->seen_else = xmalloc (conditionals->allocated); } o = conditionals->if_cmds++; if (conditionals->if_cmds > conditionals->allocated) { conditionals->allocated += 5; conditionals->ignoring = xrealloc (conditionals->ignoring, conditionals->allocated); conditionals->seen_else = xrealloc (conditionals->seen_else, conditionals->allocated); } /* Record that we have seen an 'if...' but no 'else' so far. */ conditionals->seen_else[o] = 0; /* Search through the stack to see if we're already ignoring. */ for (i = 0; i < o; ++i) if (conditionals->ignoring[i]) { /* We are already ignoring, so just push a level to match the next "else" or "endif", and keep ignoring. We don't want to expand variables in the condition. */ conditionals->ignoring[o] = 1; return 1; } if (cmdtype == c_ifdef || cmdtype == c_ifndef) { char *var; struct variable *v; char *p; /* Expand the thing we're looking up, so we can use indirect and constructed variable names. */ var = allocated_variable_expand (line); /* Make sure there's only one variable name to test. */ p = end_of_token (var); i = p - var; p = next_token (p); if (*p != '\0') return -1; var[i] = '\0'; v = lookup_variable (var, i); conditionals->ignoring[o] = ((v != 0 && *v->value != '\0') == (cmdtype == c_ifndef)); free (var); } else { /* "ifeq" or "ifneq". */ char *s1, *s2; unsigned int l; char termin = *line == '(' ? ',' : *line; if (termin != ',' && termin != '"' && termin != '\'') return -1; s1 = ++line; /* Find the end of the first string. */ if (termin == ',') { int count = 0; for (; *line != '\0'; ++line) if (*line == '(') ++count; else if (*line == ')') --count; else if (*line == ',' && count <= 0) break; } else while (*line != '\0' && *line != termin) ++line; if (*line == '\0') return -1; if (termin == ',') { /* Strip blanks after the first string. */ char *p = line++; while (isblank ((unsigned char)p[-1])) --p; *p = '\0'; } else *line++ = '\0'; s2 = variable_expand (s1); /* We must allocate a new copy of the expanded string because variable_expand re-uses the same buffer. */ l = strlen (s2); s1 = alloca (l + 1); memcpy (s1, s2, l + 1); if (termin != ',') /* Find the start of the second string. */ line = next_token (line); termin = termin == ',' ? ')' : *line; if (termin != ')' && termin != '"' && termin != '\'') return -1; /* Find the end of the second string. */ if (termin == ')') { int count = 0; s2 = next_token (line); for (line = s2; *line != '\0'; ++line) { if (*line == '(') ++count; else if (*line == ')') { if (count <= 0) break; else --count; } } } else { ++line; s2 = line; while (*line != '\0' && *line != termin) ++line; } if (*line == '\0') return -1; *line = '\0'; line = next_token (++line); if (*line != '\0') EXTRATEXT (); s2 = variable_expand (s2); conditionals->ignoring[o] = (streq (s1, s2) == (cmdtype == c_ifneq)); } DONE: /* Search through the stack to see if we're ignoring. */ for (i = 0; i < conditionals->if_cmds; ++i) if (conditionals->ignoring[i]) return 1; return 0; } /* Record target-specific variable values for files FILENAMES. TWO_COLON is nonzero if a double colon was used. The links of FILENAMES are freed, and so are any names in it that are not incorporated into other data structures. If the target is a pattern, add the variable to the pattern-specific variable value list. */ static void record_target_var (struct nameseq *filenames, char *defn, enum variable_origin origin, struct vmodifiers *vmod, const gmk_floc *flocp) { struct nameseq *nextf; struct variable_set_list *global; global = current_variable_set_list; /* If the variable is an append version, store that but treat it as a normal recursive variable. */ for (; filenames != 0; filenames = nextf) { struct variable *v; const char *name = filenames->name; const char *percent; struct pattern_var *p; nextf = filenames->next; free_ns (filenames); /* If it's a pattern target, then add it to the pattern-specific variable list. */ percent = find_percent_cached (&name); if (percent) { /* Get a reference for this pattern-specific variable struct. */ p = create_pattern_var (name, percent); p->variable.fileinfo = *flocp; /* I don't think this can fail since we already determined it was a variable definition. */ v = assign_variable_definition (&p->variable, defn); assert (v != 0); v->origin = origin; if (v->flavor == f_simple) v->value = allocated_variable_expand (v->value); else v->value = xstrdup (v->value); } else { struct file *f; /* Get a file reference for this file, and initialize it. We don't want to just call enter_file() because that allocates a new entry if the file is a double-colon, which we don't want in this situation. */ f = lookup_file (name); if (!f) f = enter_file (strcache_add (name)); else if (f->double_colon) f = f->double_colon; initialize_file_variables (f, 1); current_variable_set_list = f->variables; v = try_variable_definition (flocp, defn, origin, 1); if (!v) O (fatal, flocp, _("Malformed target-specific variable definition")); current_variable_set_list = global; } /* Set up the variable to be *-specific. */ v->per_target = 1; v->private_var = vmod->private_v; v->export = vmod->export_v ? v_export : v_default; /* If it's not an override, check to see if there was a command-line setting. If so, reset the value. */ if (v->origin != o_override) { struct variable *gv; int len = strlen (v->name); gv = lookup_variable (v->name, len); if (gv && v != gv && (gv->origin == o_env_override || gv->origin == o_command)) { free (v->value); v->value = xstrdup (gv->value); v->origin = gv->origin; v->recursive = gv->recursive; v->append = 0; } } } } /* Record a description line for files FILENAMES, with dependencies DEPS, commands to execute described by COMMANDS and COMMANDS_IDX, coming from FILENAME:COMMANDS_STARTED. TWO_COLON is nonzero if a double colon was used. If not nil, PATTERN is the '%' pattern to make this a static pattern rule, and PATTERN_PERCENT is a pointer to the '%' within it. The links of FILENAMES are freed, and so are any names in it that are not incorporated into other data structures. */ static void record_files (struct nameseq *filenames, const char *pattern, const char *pattern_percent, char *depstr, unsigned int cmds_started, char *commands, unsigned int commands_idx, int two_colon, char *target_description, char prefix, const gmk_floc *flocp) { struct commands *cmds; struct dep *deps; const char *implicit_percent; const char *name; /* If we've already snapped deps, that means we're in an eval being resolved after the makefiles have been read in. We can't add more rules at this time, since they won't get snapped and we'll get core dumps. See Savannah bug # 12124. */ if (snapped_deps) O (fatal, flocp, _("prerequisites cannot be defined in recipes")); /* Determine if this is a pattern rule or not. */ name = filenames->name; implicit_percent = find_percent_cached (&name); /* If there's a recipe, set up a struct for it. */ if (commands_idx > 0) { cmds = xmalloc (sizeof (struct commands)); cmds->fileinfo.filenm = flocp->filenm; cmds->fileinfo.lineno = cmds_started; cmds->commands = xstrndup (commands, commands_idx); cmds->command_lines = 0; cmds->recipe_prefix = prefix; } else cmds = 0; /* If there's a prereq string then parse it--unless it's eligible for 2nd expansion: if so, snap_deps() will do it. */ if (depstr == 0) deps = 0; else { depstr = unescape_char (depstr, ':'); if (second_expansion && strchr (depstr, '$')) { deps = alloc_dep (); deps->name = depstr; deps->need_2nd_expansion = 1; deps->staticpattern = pattern != 0; } else { deps = split_prereqs (depstr); free (depstr); /* We'll enter static pattern prereqs later when we have the stem. We don't want to enter pattern rules at all so that we don't think that they ought to exist (make manual "Implicit Rule Search Algorithm", item 5c). */ if (! pattern && ! implicit_percent) deps = enter_prereqs (deps, NULL); } } /* For implicit rules, _all_ the targets must have a pattern. That means we can test the first one to see if we're working with an implicit rule; if so we handle it specially. */ if (implicit_percent) { struct nameseq *nextf; const char **targets, **target_pats; unsigned int c; if (pattern != 0) O (fatal, flocp, _("mixed implicit and static pattern rules")); /* Count the targets to create an array of target names. We already have the first one. */ nextf = filenames->next; free_ns (filenames); filenames = nextf; for (c = 1; nextf; ++c, nextf = nextf->next) ; targets = xmalloc (c * sizeof (const char *)); target_pats = xmalloc (c * sizeof (const char *)); targets[0] = name; target_pats[0] = implicit_percent; c = 1; while (filenames) { name = filenames->name; implicit_percent = find_percent_cached (&name); if (implicit_percent == 0) O (fatal, flocp, _("mixed implicit and normal rules")); targets[c] = name; target_pats[c] = implicit_percent; ++c; nextf = filenames->next; free_ns (filenames); filenames = nextf; } create_pattern_rule (targets, target_pats, c, two_colon, deps, cmds, 1); return; } /* Walk through each target and create it in the database. We already set up the first target, above. */ while (1) { struct nameseq *nextf = filenames->next; struct file *f; struct dep *this = 0; free_ns (filenames); /* Check for special targets. Do it here instead of, say, snap_deps() so that we can immediately use the value. */ if (streq (name, ".POSIX")) { posix_pedantic = 1; define_variable_cname (".SHELLFLAGS", "-ec", o_default, 0); /* These default values are based on IEEE Std 1003.1-2008. */ define_variable_cname ("ARFLAGS", "-rv", o_default, 0); define_variable_cname ("CC", "c99", o_default, 0); define_variable_cname ("CFLAGS", "-O", o_default, 0); define_variable_cname ("FC", "fort77", o_default, 0); define_variable_cname ("FFLAGS", "-O 1", o_default, 0); define_variable_cname ("SCCSGETFLAGS", "-s", o_default, 0); } else if (streq (name, ".SECONDEXPANSION")) second_expansion = 1; #if !defined (__MSDOS__) && !defined (__EMX__) else if (streq (name, ".ONESHELL")) one_shell = 1; #endif /* If this is a static pattern rule: 'targets: target%pattern: prereq%pattern; recipe', make sure the pattern matches this target name. */ if (pattern && !pattern_matches (pattern, pattern_percent, name)) OS (error, flocp, _("target '%s' doesn't match the target pattern"), name); else if (deps) /* If there are multiple targets, copy the chain DEPS for all but the last one. It is not safe for the same deps to go in more than one place in the database. */ this = nextf != 0 ? copy_dep_chain (deps) : deps; /* Find or create an entry in the file database for this target. */ if (!two_colon) { /* Single-colon. Combine this rule with the file's existing record, if any. */ f = enter_file (strcache_add (name)); f->description = target_description; f->floc.filenm = flocp->filenm; f->floc.lineno = flocp->lineno; if (f->double_colon) OS (fatal, flocp, _("target file '%s' has both : and :: entries"), f->name); /* If CMDS == F->CMDS, this target was listed in this rule more than once. Just give a warning since this is harmless. */ if (cmds != 0 && cmds == f->cmds) OS (error, flocp, _("target '%s' given more than once in the same rule"), f->name); /* Check for two single-colon entries both with commands. Check is_target so that we don't lose on files such as .c.o whose commands were preinitialized. */ else if (cmds != 0 && f->cmds != 0 && f->is_target) { size_t l = strlen (f->name); error (&cmds->fileinfo, l, _("warning: overriding recipe for target '%s'"), f->name); error (&f->cmds->fileinfo, l, _("warning: ignoring old recipe for target '%s'"), f->name); } /* Defining .DEFAULT with no deps or cmds clears it. */ if (f == default_file && this == 0 && cmds == 0) f->cmds = 0; if (cmds != 0) f->cmds = cmds; /* Defining .SUFFIXES with no dependencies clears out the list of suffixes. */ if (f == suffix_file && this == 0) { free_dep_chain (f->deps); f->deps = 0; } } else { /* Double-colon. Make a new record even if there already is one. */ f = lookup_file (name); /* Check for both : and :: rules. Check is_target so we don't lose on default suffix rules or makefiles. */ if (f != 0 && f->is_target && !f->double_colon) OS (fatal, flocp, _("target file '%s' has both : and :: entries"), f->name); f = enter_file (strcache_add (name)); f->description = target_description; f->floc.filenm = flocp->filenm; f->floc.lineno = flocp->lineno; /* If there was an existing entry and it was a double-colon entry, enter_file will have returned a new one, making it the prev pointer of the old one, and setting its double_colon pointer to the first one. */ if (f->double_colon == 0) /* This is the first entry for this name, so we must set its double_colon pointer to itself. */ f->double_colon = f; f->cmds = cmds; } f->is_target = 1; /* If this is a static pattern rule, set the stem to the part of its name that matched the '%' in the pattern, so you can use $* in the commands. If we didn't do it before, enter the prereqs now. */ if (pattern) { static const char *percent = "%"; char *buffer = variable_expand (""); char *o = patsubst_expand_pat (buffer, name, pattern, percent, pattern_percent+1, percent+1); f->stem = strcache_add_len (buffer, o - buffer); if (this) { if (! this->need_2nd_expansion) this = enter_prereqs (this, f->stem); else this->stem = f->stem; } } /* Add the dependencies to this file entry. */ if (this != 0) { /* Add the file's old deps and the new ones in THIS together. */ if (f->deps == 0) f->deps = this; else if (cmds != 0) { struct dep *d = this; /* If this rule has commands, put these deps first. */ while (d->next != 0) d = d->next; d->next = f->deps; f->deps = this; } else { struct dep *d = f->deps; /* A rule without commands: put its prereqs at the end. */ while (d->next != 0) d = d->next; d->next = this; } } name = f->name; /* All done! Set up for the next one. */ if (nextf == 0) break; filenames = nextf; /* Reduce escaped percents. If there are any unescaped it's an error */ name = filenames->name; if (find_percent_cached (&name)) O (error, flocp, _("*** mixed implicit and normal rules: deprecated syntax")); } } /* Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero). Backslashes quote STOPCHAR, blanks if BLANK is nonzero, and backslash. Quoting backslashes are removed from STRING by compacting it into itself. Returns a pointer to the first unquoted STOPCHAR if there is one, or nil if there are none. STOPCHARs inside variable references are ignored if IGNOREVARS is true. STOPCHAR _cannot_ be '$' if IGNOREVARS is true. */ static char * find_char_unquote (char *string, int map) { unsigned int string_len = 0; char *p = string; /* Always stop on NUL. */ map |= MAP_NUL; while (1) { while (! STOP_SET (*p, map)) ++p; if (*p == '\0') break; /* If we stopped due to a variable reference, skip over its contents. */ if (STOP_SET (*p, MAP_VARIABLE)) { char openparen = p[1]; p += 2; /* Skip the contents of a non-quoted, multi-char variable ref. */ if (openparen == '(' || openparen == '{') { unsigned int pcount = 1; char closeparen = (openparen == '(' ? ')' : '}'); while (*p) { if (*p == openparen) ++pcount; else if (*p == closeparen) if (--pcount == 0) { ++p; break; } ++p; } } /* Skipped the variable reference: look for STOPCHARS again. */ continue; } if (p > string && p[-1] == '\\') { /* Search for more backslashes. */ int i = -2; while (&p[i] >= string && p[i] == '\\') --i; ++i; /* Only compute the length if really needed. */ if (string_len == 0) string_len = strlen (string); /* The number of backslashes is now -I. Copy P over itself to swallow half of them. */ memmove (&p[i], &p[i/2], (string_len - (p - string)) - (i/2) + 1); p += i/2; if (i % 2 == 0) /* All the backslashes quoted each other; the STOPCHAR was unquoted. */ return p; /* The STOPCHAR was quoted by a backslash. Look for another. */ } else /* No backslash in sight. */ return p; } /* Never hit a STOPCHAR or blank (with BLANK nonzero). */ return 0; } /* Unescape a character in a string. The string is compressed onto itself. */ static char * unescape_char (char *string, int c) { char *p = string; char *s = string; while (*s != '\0') { if (*s == '\\') { char *e = s; int l; /* We found a backslash. See if it's escaping our character. */ while (*e == '\\') ++e; l = e - s; if (*e != c || l%2 == 0) { /* It's not; just take it all without unescaping. */ memmove (p, s, l); p += l; } else if (l > 1) { /* It is, and there's >1 backslash. Take half of them. */ l /= 2; memmove (p, s, l); p += l; } s = e; } *(p++) = *(s++); } *p = '\0'; return string; } /* Search PATTERN for an unquoted % and handle quoting. */ char * find_percent (char *pattern) { return find_char_unquote (pattern, MAP_PERCENT); } /* Search STRING for an unquoted % and handle quoting. Returns a pointer to the % or NULL if no % was found. This version is used with strings in the string cache: if there's a need to modify the string a new version will be added to the string cache and *STRING will be set to that. */ const char * find_percent_cached (const char **string) { const char *p = *string; char *new = 0; int slen = 0; /* If the first char is a % return now. This lets us avoid extra tests inside the loop. */ if (*p == '%') return p; while (1) { while (! STOP_SET (*p, MAP_PERCENT|MAP_NUL)) ++p; if (*p == '\0') break; /* See if this % is escaped with a backslash; if not we're done. */ if (p[-1] != '\\') break; { /* Search for more backslashes. */ char *pv; int i = -2; while (&p[i] >= *string && p[i] == '\\') --i; ++i; /* At this point we know we'll need to allocate a new string. Make a copy if we haven't yet done so. */ if (! new) { slen = strlen (*string); new = alloca (slen + 1); memcpy (new, *string, slen + 1); p = new + (p - *string); *string = new; } /* At this point *string, p, and new all point into the same string. Get a non-const version of p so we can modify new. */ pv = new + (p - *string); /* The number of backslashes is now -I. Copy P over itself to swallow half of them. */ memmove (&pv[i], &pv[i/2], (slen - (pv - new)) - (i/2) + 1); p += i/2; /* If the backslashes quoted each other; the % was unquoted. */ if (i % 2 == 0) break; } } /* If we had to change STRING, add it to the strcache. */ if (new) { *string = strcache_add (*string); p = *string + (p - new); } /* If we didn't find a %, return NULL. Otherwise return a ptr to it. */ return (*p == '\0') ? NULL : p; } /* Find the next line of text in an eval buffer, combining continuation lines into one line. Return the number of actual lines read (> 1 if continuation lines). Returns -1 if there's nothing left in the buffer. After this function, ebuf->buffer points to the first character of the line we just found. */ /* Read a line of text from a STRING. Since we aren't really reading from a file, don't bother with linenumbers. */ static unsigned long readstring (struct ebuffer *ebuf) { char *eol; /* If there is nothing left in this buffer, return 0. */ if (ebuf->bufnext >= ebuf->bufstart + ebuf->size) return -1; /* Set up a new starting point for the buffer, and find the end of the next logical line (taking into account backslash/newline pairs). */ eol = ebuf->buffer = ebuf->bufnext; while (1) { int backslash = 0; const char *bol = eol; const char *p; /* Find the next newline. At EOS, stop. */ p = eol = strchr (eol , '\n'); if (!eol) { ebuf->bufnext = ebuf->bufstart + ebuf->size + 1; return 0; } /* Found a newline; if it's escaped continue; else we're done. */ while (p > bol && *(--p) == '\\') backslash = !backslash; if (!backslash) break; ++eol; } /* Overwrite the newline char. */ *eol = '\0'; ebuf->bufnext = eol+1; return 0; } static long readline (struct ebuffer *ebuf) { char *p; char *end; char *start; long nlines = 0; /* The behaviors between string and stream buffers are different enough to warrant different functions. Do the Right Thing. */ if (!ebuf->fp) return readstring (ebuf); /* When reading from a file, we always start over at the beginning of the buffer for each new line. */ p = start = ebuf->bufstart; end = p + ebuf->size; *p = '\0'; while (fgets (p, end - p, ebuf->fp) != 0) { char *p2; unsigned long len; int backslash; len = strlen (p); if (len == 0) { /* This only happens when the first thing on the line is a '\0'. It is a pretty hopeless case, but (wonder of wonders) Athena lossage strikes again! (xmkmf puts NULs in its makefiles.) There is nothing really to be done; we synthesize a newline so the following line doesn't appear to be part of this line. */ O (error, &ebuf->floc, _("warning: NUL character seen; rest of line ignored")); p[0] = '\n'; len = 1; } /* Jump past the text we just read. */ p += len; /* If the last char isn't a newline, the whole line didn't fit into the buffer. Get some more buffer and try again. */ if (p[-1] != '\n') goto more_buffer; /* We got a newline, so add one to the count of lines. */ ++nlines; #if !defined(WINDOWS32) && !defined(__MSDOS__) && !defined(__EMX__) /* Check to see if the line was really ended with CRLF; if so ignore the CR. */ if ((p - start) > 1 && p[-2] == '\r') { --p; memmove (p-1, p, strlen (p) + 1); } #endif backslash = 0; for (p2 = p - 2; p2 >= start; --p2) { if (*p2 != '\\') break; backslash = !backslash; } if (!backslash) { p[-1] = '\0'; break; } /* It was a backslash/newline combo. If we have more space, read another line. */ if (end - p >= 80) continue; /* We need more space at the end of our buffer, so realloc it. Make sure to preserve the current offset of p. */ more_buffer: { unsigned long off = p - start; ebuf->size *= 2; start = ebuf->buffer = ebuf->bufstart = xrealloc (start, ebuf->size); p = start + off; end = start + ebuf->size; *p = '\0'; } } if (ferror (ebuf->fp)) pfatal_with_name (ebuf->floc.filenm); /* If we found some lines, return how many. If we didn't, but we did find _something_, that indicates we read the last line of a file with no final newline; return 1. If we read nothing, we're at EOF; return -1. */ return nlines ? nlines : p == ebuf->bufstart ? -1 : 1; } /* Parse the next "makefile word" from the input buffer, and return info about it. A "makefile word" is one of: w_bogus Should never happen w_eol End of input w_static A static word; cannot be expanded w_variable A word containing one or more variables/functions w_colon A colon w_dcolon A double-colon w_semicolon A semicolon w_varassign A variable assignment operator (=, :=, ::=, +=, ?=, or !=) Note that this function is only used when reading certain parts of the makefile. Don't use it where special rules hold sway (RHS of a variable, in a command list, etc.) */ static enum make_word_type get_next_mword (char *buffer, char *delim, char **startp, unsigned int *length) { enum make_word_type wtype = w_bogus; char *p = buffer, *beg; char c; /* Skip any leading whitespace. */ while (isblank ((unsigned char)*p)) ++p; beg = p; c = *(p++); switch (c) { case '\0': wtype = w_eol; break; case ';': wtype = w_semicolon; break; case '=': wtype = w_varassign; break; case ':': wtype = w_colon; switch (*p) { case ':': ++p; if (p[1] != '=') wtype = w_dcolon; else { wtype = w_varassign; ++p; } break; case '=': ++p; wtype = w_varassign; break; } break; case '+': case '?': case '!': if (*p == '=') { ++p; wtype = w_varassign; break; } default: if (delim && strchr (delim, c)) wtype = w_static; break; } /* Did we find something? If so, return now. */ if (wtype != w_bogus) goto done; /* This is some non-operator word. A word consists of the longest string of characters that doesn't contain whitespace, one of [:=#], or [?+!]=, or one of the chars in the DELIM string. */ /* We start out assuming a static word; if we see a variable we'll adjust our assumptions then. */ wtype = w_static; /* We already found the first value of "c", above. */ while (1) { char closeparen; int count; switch (c) { case '\0': case ' ': case '\t': case '=': goto done_word; case ':': #ifdef HAVE_DOS_PATHS /* A word CAN include a colon in its drive spec. The drive spec is allowed either at the beginning of a word, or as part of the archive member name, like in "libfoo.a(d:/foo/bar.o)". */ if (!(p - beg >= 2 && (*p == '/' || *p == '\\') && isalpha ((unsigned char)p[-2]) && (p - beg == 2 || p[-3] == '('))) #endif goto done_word; case '$': c = *(p++); if (c == '$') break; /* This is a variable reference, so note that it's expandable. Then read it to the matching close paren. */ wtype = w_variable; if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else /* This is a single-letter variable reference. */ break; for (count=0; *p != '\0'; ++p) { if (*p == c) ++count; else if (*p == closeparen && --count < 0) { ++p; break; } } break; case '?': case '+': if (*p == '=') goto done_word; break; case '\\': switch (*p) { case ':': case ';': case '=': case '\\': ++p; break; } break; default: if (delim && strchr (delim, c)) goto done_word; break; } c = *(p++); } done_word: --p; done: if (startp) *startp = beg; if (length) *length = p - beg; return wtype; } /* Construct the list of include directories from the arguments and the default list. */ void construct_include_path (const char **arg_dirs) { #ifdef VAXC /* just don't ask ... */ stat_t stbuf; #else struct stat stbuf; #endif const char **dirs; const char **cpp; unsigned int idx; /* Compute the number of pointers we need in the table. */ idx = sizeof (default_include_directories) / sizeof (const char *); if (arg_dirs) for (cpp = arg_dirs; *cpp != 0; ++cpp) ++idx; #ifdef __MSDOS__ /* Add one for $DJDIR. */ ++idx; #endif dirs = xmalloc (idx * sizeof (const char *)); idx = 0; max_incl_len = 0; /* First consider any dirs specified with -I switches. Ignore any that don't exist. Remember the maximum string length. */ if (arg_dirs) while (*arg_dirs != 0) { const char *dir = *(arg_dirs++); char *expanded = 0; int e; if (dir[0] == '~') { expanded = remake_tilde_expand (dir); if (expanded != 0) dir = expanded; } EINTRLOOP (e, stat (dir, &stbuf)); if (e == 0 && S_ISDIR (stbuf.st_mode)) { unsigned int len = strlen (dir); /* If dir name is written with trailing slashes, discard them. */ while (len > 1 && dir[len - 1] == '/') --len; if (len > max_incl_len) max_incl_len = len; dirs[idx++] = strcache_add_len (dir, len); } free (expanded); } /* Now add the standard default dirs at the end. */ #ifdef __MSDOS__ { /* The environment variable $DJDIR holds the root of the DJGPP directory tree; add ${DJDIR}/include. */ struct variable *djdir = lookup_variable ("DJDIR", 5); if (djdir) { unsigned int len = strlen (djdir->value) + 8; char *defdir = alloca (len + 1); strcat (strcpy (defdir, djdir->value), "/include"); dirs[idx++] = strcache_add (defdir); if (len > max_incl_len) max_incl_len = len; } } #endif for (cpp = default_include_directories; *cpp != 0; ++cpp) { int e; EINTRLOOP (e, stat (*cpp, &stbuf)); if (e == 0 && S_ISDIR (stbuf.st_mode)) { unsigned int len = strlen (*cpp); /* If dir name is written with trailing slashes, discard them. */ while (len > 1 && (*cpp)[len - 1] == '/') --len; if (len > max_incl_len) max_incl_len = len; dirs[idx++] = strcache_add_len (*cpp, len); } } dirs[idx] = 0; /* Now add each dir to the .INCLUDE_DIRS variable. */ for (cpp = dirs; *cpp != 0; ++cpp) do_variable_definition (NILF, ".INCLUDE_DIRS", *cpp, o_default, f_append, 0); include_directories = dirs; } /* Expand ~ or ~USER at the beginning of NAME. Return a newly malloc'd string or 0. */ char * remake_tilde_expand (const char *name) { #ifndef VMS if (name[1] == '/' || name[1] == '\0') { extern char *getenv (); char *home_dir; int is_variable; { /* Turn off --warn-undefined-variables while we expand HOME. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; home_dir = allocated_variable_expand ("$(HOME)"); warn_undefined_variables_flag = save; } is_variable = home_dir[0] != '\0'; if (!is_variable) { free (home_dir); home_dir = getenv ("HOME"); } # if !defined(_AMIGA) && !defined(WINDOWS32) if (home_dir == 0 || home_dir[0] == '\0') { extern char *getlogin (); char *logname = getlogin (); home_dir = 0; if (logname != 0) { struct passwd *p = getpwnam (logname); if (p != 0) home_dir = p->pw_dir; } } # endif /* !AMIGA && !WINDOWS32 */ if (home_dir != 0) { char *new = xstrdup (concat (2, home_dir, name + 1)); if (is_variable) free (home_dir); return new; } } # if !defined(_AMIGA) && !defined(WINDOWS32) else { struct passwd *pwent; char *userend = strchr (name + 1, '/'); if (userend != 0) *userend = '\0'; pwent = getpwnam (name + 1); if (pwent != 0) { if (userend == 0) return xstrdup (pwent->pw_dir); else return xstrdup (concat (3, pwent->pw_dir, "/", userend + 1)); } else if (userend != 0) *userend = '/'; } # endif /* !AMIGA && !WINDOWS32 */ #endif /* !VMS */ return 0; } /* Parse a string into a sequence of filenames represented as a chain of struct nameseq's and return that chain. Optionally expand the strings via glob(). The string is passed as STRINGP, the address of a string pointer. The string pointer is updated to point at the first character not parsed, which either is a null char or equals STOPCHAR. SIZE is how big to construct chain elements. This is useful if we want them actually to be other structures that have room for additional info. PREFIX, if non-null, is added to the beginning of each filename. FLAGS allows one or more of the following bitflags to be set: PARSEFS_NOSTRIP - Do no strip './'s off the beginning PARSEFS_NOAR - Do not check filenames for archive references PARSEFS_NOGLOB - Do not expand globbing characters PARSEFS_EXISTS - Only return globbed files that actually exist (cannot also set NOGLOB) PARSEFS_NOCACHE - Do not add filenames to the strcache (caller frees) */ void * parse_file_seq (char **stringp, unsigned int size, int stopmap, const char *prefix, int flags) { extern void dir_setup_glob (glob_t *glob); /* tmp points to tmpbuf after the prefix, if any. tp is the end of the buffer. */ static char *tmpbuf = NULL; int cachep = NONE_SET (flags, PARSEFS_NOCACHE); struct nameseq *new = 0; struct nameseq **newp = &new; #define NEWELT(_n) do { \ const char *__n = (_n); \ *newp = xcalloc (size); \ (*newp)->name = (cachep ? strcache_add (__n) : xstrdup (__n)); \ newp = &(*newp)->next; \ } while(0) char *p; glob_t gl; char *tp; /* Always stop on NUL. */ stopmap |= MAP_NUL; if (size < sizeof (struct nameseq)) size = sizeof (struct nameseq); if (NONE_SET (flags, PARSEFS_NOGLOB)) dir_setup_glob (&gl); /* Get enough temporary space to construct the largest possible target. */ { static int tmpbuf_len = 0; int l = strlen (*stringp) + 1; if (l > tmpbuf_len) { tmpbuf = xrealloc (tmpbuf, l); tmpbuf_len = l; } } tp = tmpbuf; /* Parse STRING. P will always point to the end of the parsed content. */ p = *stringp; while (1) { const char *name; const char **nlist = 0; char *tildep = 0; int globme = 1; #ifndef NO_ARCHIVES char *arname = 0; char *memname = 0; #endif char *s; int nlen; int i; /* Skip whitespace; at the end of the string or STOPCHAR we're done. */ p = next_token (p); if (STOP_SET (*p, stopmap)) break; /* There are names left, so find the end of the next name. Throughout this iteration S points to the start. */ s = p; p = find_char_unquote (p, stopmap|MAP_VMSCOMMA|MAP_BLANK); #ifdef VMS /* convert comma separated list to space separated */ if (p && *p == ',') *p =' '; #endif #ifdef _AMIGA if (p && STOP_SET (*p, stopmap & MAP_COLON) && !(isspace ((unsigned char)p[1]) || !p[1] || isspace ((unsigned char)p[-1]))) p = find_char_unquote (p+1, stopmap|MAP_VMSCOMMA|MAP_BLANK); #endif #ifdef HAVE_DOS_PATHS /* For DOS paths, skip a "C:\..." or a "C:/..." until we find the first colon which isn't followed by a slash or a backslash. Note that tokens separated by spaces should be treated as separate tokens since make doesn't allow path names with spaces */ if (stopmap | MAP_COLON) while (p != 0 && !isspace ((unsigned char)*p) && (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1])) p = find_char_unquote (p + 1, stopmap|MAP_VMSCOMMA|MAP_BLANK); #endif if (p == 0) p = s + strlen (s); /* Strip leading "this directory" references. */ if (NONE_SET (flags, PARSEFS_NOSTRIP)) #ifdef VMS /* Skip leading '[]'s. */ while (p - s > 2 && s[0] == '[' && s[1] == ']') #else /* Skip leading './'s. */ while (p - s > 2 && s[0] == '.' && s[1] == '/') #endif { /* Skip "./" and all following slashes. */ s += 2; while (*s == '/') ++s; } /* Extract the filename just found, and skip it. Set NAME to the string, and NLEN to its length. */ if (s == p) { /* The name was stripped to empty ("./"). */ #if defined(VMS) continue; #elif defined(_AMIGA) /* PDS-- This cannot be right!! */ tp[0] = '\0'; nlen = 0; #else tp[0] = '.'; tp[1] = '/'; tp[2] = '\0'; nlen = 2; #endif } else { #ifdef VMS /* VMS filenames can have a ':' in them but they have to be '\'ed but we need * to remove this '\' before we can use the filename. * xstrdup called because S may be read-only string constant. */ char *n = tp; while (s < p) { if (s[0] == '\\' && s[1] == ':') ++s; *(n++) = *(s++); } n[0] = '\0'; nlen = strlen (tp); #else nlen = p - s; memcpy (tp, s, nlen); tp[nlen] = '\0'; #endif } /* At this point, TP points to the element and NLEN is its length. */ #ifndef NO_ARCHIVES /* If this is the start of an archive group that isn't complete, set up to add the archive prefix for future files. A file list like: "libf.a(x.o y.o z.o)" needs to be expanded as: "libf.a(x.o) libf.a(y.o) libf.a(z.o)" TP == TMP means we're not already in an archive group. Ignore something starting with '(', as that cannot actually be an archive-member reference (and treating it as such results in an empty file name, which causes much lossage). Also if it ends in ")" then it's a complete reference so we don't need to treat it specially. Finally, note that archive groups must end with ')' as the last character, so ensure there's some word ending like that before considering this an archive group. */ if (NONE_SET (flags, PARSEFS_NOAR) && tp == tmpbuf && tp[0] != '(' && tp[nlen-1] != ')') { char *n = strchr (tp, '('); if (n) { /* This looks like the first element in an open archive group. A valid group MUST have ')' as the last character. */ const char *e = p; do { const char *o = e; e = next_token (e); /* Find the end of this word. We don't want to unquote and we don't care about quoting since we're looking for the last char in the word. */ while (! STOP_SET (*e, stopmap|MAP_BLANK|MAP_VMSCOMMA)) ++e; /* If we didn't move, we're done now. */ if (e == o) break; if (e[-1] == ')') { /* Found the end, so this is the first element in an open archive group. It looks like "lib(mem". Reset TP past the open paren. */ nlen -= (n + 1) - tp; tp = n + 1; /* We can stop looking now. */ break; } } while (*e != '\0'); /* If we have just "lib(", part of something like "lib( a b)", go to the next item. */ if (! nlen) continue; } } /* If we are inside an archive group, make sure it has an end. */ if (tp > tmpbuf) { if (tp[nlen-1] == ')') { /* This is the natural end; reset TP. */ tp = tmpbuf; /* This is just ")", something like "lib(a b )": skip it. */ if (nlen == 1) continue; } else { /* Not the end, so add a "fake" end. */ tp[nlen++] = ')'; tp[nlen] = '\0'; } } #endif /* If we're not globbing we're done: add it to the end of the chain. Go to the next item in the string. */ if (ANY_SET (flags, PARSEFS_NOGLOB)) { NEWELT (concat (2, prefix, tmpbuf)); continue; } /* If we get here we know we're doing glob expansion. TP is a string in tmpbuf. NLEN is no longer used. We may need to do more work: after this NAME will be set. */ name = tmpbuf; /* Expand tilde if applicable. */ if (tmpbuf[0] == '~') { tildep = remake_tilde_expand (tmpbuf); if (tildep != 0) name = tildep; } #ifndef NO_ARCHIVES /* If NAME is an archive member reference replace it with the archive file name, and save the member name in MEMNAME. We will glob on the archive name and then reattach MEMNAME later. */ if (NONE_SET (flags, PARSEFS_NOAR) && ar_name (name)) { ar_parse_name (name, &arname, &memname); name = arname; } #endif /* !NO_ARCHIVES */ /* glob() is expensive: don't call it unless we need to. */ if (NONE_SET (flags, PARSEFS_EXISTS) && strpbrk (name, "?*[") == NULL) { globme = 0; i = 1; nlist = &name; } else switch (glob (name, GLOB_NOSORT|GLOB_ALTDIRFUNC, NULL, &gl)) { case GLOB_NOSPACE: OUT_OF_MEM(); case 0: /* Success. */ i = gl.gl_pathc; nlist = (const char **)gl.gl_pathv; break; case GLOB_NOMATCH: /* If we want only existing items, skip this one. */ if (ANY_SET (flags, PARSEFS_EXISTS)) { i = 0; break; } /* FALLTHROUGH */ default: /* By default keep this name. */ i = 1; nlist = &name; break; } /* For each matched element, add it to the list. */ while (i-- > 0) #ifndef NO_ARCHIVES if (memname != 0) { /* Try to glob on MEMNAME within the archive. */ struct nameseq *found = ar_glob (nlist[i], memname, size); if (! found) /* No matches. Use MEMNAME as-is. */ NEWELT (concat (5, prefix, nlist[i], "(", memname, ")")); else { /* We got a chain of items. Attach them. */ if (*newp) (*newp)->next = found; else *newp = found; /* Find and set the new end. Massage names if necessary. */ while (1) { if (! cachep) found->name = xstrdup (concat (2, prefix, name)); else if (prefix) found->name = strcache_add (concat (2, prefix, name)); if (found->next == 0) break; found = found->next; } newp = &found->next; } } else #endif /* !NO_ARCHIVES */ NEWELT (concat (2, prefix, nlist[i])); if (globme) globfree (&gl); #ifndef NO_ARCHIVES free (arname); #endif free (tildep); } *stringp = p; return new; } remake-4.1+dbg1.3~dfsg.1/read.h000066400000000000000000000045351317072305000160660ustar00rootroot00000000000000/* $Id: read.h,v 1.7 2007/01/04 12:03:20 rockyb Exp $ Copyright (C) 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2008 R. Bernstein This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file read.h * * \brief Header for Reading and parsing of makefiles for GNU Make. */ #ifndef REMAKE_READ_H #define REMAKE_READ_H #include "dep.h" extern stringlist_t *include_directories; /*! Search STRING for an unquoted STOPCHAR or blank (if BLANK is nonzero). Backslashes quote STOPCHAR, blanks if BLANK is nonzero, and backslash. Quoting backslashes are removed from STRING by compacting it into itself. Returns a pointer to the first unquoted STOPCHAR if there is one, or nil if there are none. */ char *find_char_unquote (char *string, int stop1, int stop2, int blank); /*! Search PATTERN for an unquoted %. */ char *find_percent (char *pattern); /*! Expand ~ or ~USER at the beginning of NAME. Return a newly malloc'd string or 0. */ char *make_tilde_expand (char *name); /*! Given a chain of struct nameseq's describing a sequence of filenames, in reverse of the intended order, return a new chain describing the result of globbing the filenames. The new chain is in forward order. The links of the old chain are freed or used in the new chain. Likewise for the names in the old chain. SIZE is how big to construct chain elements. This is useful if we want them actually to be other structures that have room for additional info. */ nameseq_t * multi_glob (struct nameseq *chain, unsigned int size); /*! Read a Makefile and save information in our database about it. */ extern int eval_makefile (const char *filename, int flags); #endif /*REMAKE_READ_H*/ remake-4.1+dbg1.3~dfsg.1/remake.c000066400000000000000000001613751317072305000164200ustar00rootroot00000000000000/* Basic dependency engine for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "globals.h" #include "profile.h" #include "debugger/cmd.h" #include "filedef.h" #include "job.h" #include "commands.h" #include "dep.h" #include "variable.h" #include "debug.h" #include #ifdef HAVE_FCNTL_H #include #else #include #endif #ifdef VMS #include #endif #ifdef WINDOWS32 #include #endif extern int try_implicit_rule (struct file *file, unsigned int depth); /* The test for circular dependencies is based on the 'updating' bit in 'struct file'. However, double colon targets have separate 'struct file's; make sure we always use the base of the double colon chain. */ #define start_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating = 1) #define finish_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating = 0) #define is_updating(_f) (((_f)->double_colon ? (_f)->double_colon : (_f))\ ->updating) /* Incremented when a command is started (under -n, when one would be). */ unsigned int commands_started = 0; /* Current value for pruning the scan of the goal chain (toggle 0/1). */ static unsigned int considered; static enum update_status update_file (struct file *file, unsigned int depth, target_stack_node_t *p_call_stack); static enum update_status update_file_1 (struct file *file, unsigned int depth, target_stack_node_t *p_call_stack); static enum update_status check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr, target_stack_node_t *p_call_stack); static enum update_status touch_file (struct file *file); static void remake_file (struct file *file, target_stack_node_t *p_call_stack); static FILE_TIMESTAMP name_mtime (const char *name); static const char *library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr); /* Remake all the goals in the 'struct dep' chain GOALS. Return -1 if nothing was done, 0 if all goals were updated successfully, or 1 if a goal failed. If rebuilding_makefiles is nonzero, these goals are makefiles, so -t, -q, and -n should be disabled for them unless they were also command-line targets, and we should only make one goal at a time and return as soon as one goal whose 'changed' member is nonzero is successfully made. */ enum update_status update_goal_chain (struct dep *goals) { int t = touch_flag, q = question_flag, n = just_print_flag; enum update_status status = us_none; #define MTIME(file) (rebuilding_makefiles ? file_mtime_no_search (file) \ : file_mtime (file)) /* Duplicate the chain so we can remove things from it. */ goals = copy_dep_chain (goals); { /* Clear the 'changed' flag of each goal in the chain. We will use the flag below to notice when any commands have actually been run for a target. When no commands have been run, we give an "up to date" diagnostic. */ struct dep *g; for (g = goals; g != 0; g = g->next) g->changed = 0; } /* All files start with the considered bit 0, so the global value is 1. */ considered = 1; /* Update all the goals until they are all finished. */ while (goals != 0) { register struct dep *g, *lastgoal; /* Start jobs that are waiting for the load to go down. */ start_waiting_jobs (NULL); /* Wait for a child to die. */ reap_children (1, 0, NULL); lastgoal = 0; g = goals; while (g != 0) { /* Iterate over all double-colon entries for this file. */ struct file *file; int stop = 0, any_not_updated = 0; for (file = g->file->double_colon ? g->file->double_colon : g->file; file != NULL; file = file->prev) { unsigned int ocommands_started; enum update_status fail; file->dontcare = g->dontcare; check_renamed (file); if (rebuilding_makefiles) { if (file->cmd_target) { touch_flag = t; question_flag = q; just_print_flag = n; } else touch_flag = question_flag = just_print_flag = 0; } /* Save the old value of 'commands_started' so we can compare later. It will be incremented when any commands are actually run. */ ocommands_started = commands_started; fail = update_file (file, rebuilding_makefiles ? 1 : 0, NULL); check_renamed (file); /* Set the goal's 'changed' flag if any commands were started by calling update_file above. We check this flag below to decide when to give an "up to date" diagnostic. */ if (commands_started > ocommands_started) g->changed = 1; stop = 0; if ((fail || file->updated) && status < us_question) { /* We updated this goal. Update STATUS and decide whether to stop. */ if (file->update_status) { /* Updating failed, or -q triggered. The STATUS value tells our caller which. */ status = file->update_status; /* If -q just triggered, stop immediately. It doesn't matter how much more we run, since we already know the answer to return. */ stop = (question_flag && !keep_going_flag && !rebuilding_makefiles); } else { FILE_TIMESTAMP mtime = MTIME (file); check_renamed (file); if (file->updated && g->changed && mtime != file->mtime_before_update) { /* Updating was done. If this is a makefile and just_print_flag or question_flag is set (meaning -n or -q was given and this file was specified as a command-line target), don't change STATUS. If STATUS is changed, we will get re-exec'd, and enter an infinite loop. */ if (!rebuilding_makefiles || (!just_print_flag && !question_flag)) status = us_success; if (rebuilding_makefiles && file->dontcare) /* This is a default makefile; stop remaking. */ stop = 1; } } } /* Keep track if any double-colon entry is not finished. When they are all finished, the goal is finished. */ any_not_updated |= !file->updated; file->dontcare = 0; if (stop) break; } /* Reset FILE since it is null at the end of the loop. */ file = g->file; if (stop || !any_not_updated) { /* If we have found nothing whatever to do for the goal, print a message saying nothing needs doing. */ if (!rebuilding_makefiles /* If the update_status is success, we updated successfully or not at all. G->changed will have been set above if any commands were actually started for this goal. */ && file->update_status == us_success && !g->changed /* Never give a message under -s or -q. */ && !silent_flag && !question_flag) { OS (message, 1, ((file->phony || file->cmds == 0) ? _("Nothing to be done for '%s'.") : _("'%s' is up to date.")), file->name); if ( debugger_enabled && b_debugger_goal ) enter_debugger(NULL, file, -2, DEBUG_GOAL_UPDATED_HIT); } /* This goal is finished. Remove it from the chain. */ if (lastgoal == 0) goals = g->next; else lastgoal->next = g->next; /* Free the storage. */ free (g); g = lastgoal == 0 ? goals : lastgoal->next; if (stop) break; } else { lastgoal = g; g = g->next; } } /* If we reached the end of the dependency graph toggle the considered flag for the next pass. */ if (g == 0) considered = !considered; } if (rebuilding_makefiles) { touch_flag = t; question_flag = q; just_print_flag = n; } return status; } /* If FILE is not up to date, execute the commands for it. Return 0 if successful, non-0 if unsuccessful; but with some flag settings, just call 'exit' if unsuccessful. DEPTH is the depth in recursions of this function. We increment it during the consideration of our dependencies, then decrement it again after finding out whether this file is out of date. If there are multiple double-colon entries for FILE, each is considered in turn. */ static enum update_status update_file (struct file *file, unsigned int depth, target_stack_node_t *p_call_stack) { enum update_status status = us_success; struct file *f; f = file->double_colon ? file->double_colon : file; /* Prune the dependency graph: if we've already been here on _this_ pass through the dependency graph, we don't have to go any further. We won't reap_children until we start the next pass, so no state change is possible below here until then. */ if (f->considered == considered) { /* Check for the case where a target has been tried and failed but the diagnostics haven't been issued. If we need the diagnostics then we will have to continue. */ if (!(f->updated && f->update_status > us_none && !f->dontcare && f->no_diag)) { DBF (DB_VERBOSE, _("Pruning file '%s'.\n")); return f->command_state == cs_finished ? f->update_status : 0; } } /* This loop runs until we start commands for a double colon rule, or until the chain is exhausted. */ for (; f != 0; f = f->prev) { enum update_status new; f->considered = considered; new = update_file_1 (f, depth, p_call_stack); check_renamed (f); /* Clean up any alloca() used during the update. */ alloca (0); /* If we got an error, don't bother with double_colon etc. */ if (new && !keep_going_flag) return new; if (f->command_state == cs_running || f->command_state == cs_deps_running) { /* Don't run the other :: rules for this file until this rule is finished. */ status = us_success; break; } if (new > status) status = new; } /* Process the remaining rules in the double colon chain so they're marked considered. Start their prerequisites, too. */ if (file->double_colon) for (; f != 0 ; f = f->prev) { struct dep *d; f->considered = considered; for (d = f->deps; d != 0; d = d->next) { enum update_status new = update_file (d->file, depth + 1, p_call_stack); if (new > status) new = status; } } return status; } /* Show a message stating the target failed to build. */ static void complain (struct file *file) { /* If this file has no_diag set then it means we tried to update it before in the dontcare mode and failed. The target that actually failed is not necessarily this file but could be one of its direct or indirect dependencies. So traverse this file's dependencies and find the one that actually caused the failure. */ struct dep *d; for (d = file->deps; d != 0; d = d->next) { if (d->file->updated && d->file->update_status > us_none && file->no_diag) { complain (d->file); break; } } if (d == 0) { /* Didn't find any dependencies to complain about. */ if (file->parent) { size_t l = strlen (file->name) + strlen (file->parent->name) + 4; if (!keep_going_flag) fatal (NILF, l, _("%sNo rule to make target '%s', needed by '%s'%s"), "", file->name, file->parent->name, ""); error (NILF, l, _("%sNo rule to make target '%s', needed by '%s'%s"), "*** ", file->name, file->parent->name, "."); } else { size_t l = strlen (file->name) + 4; if (!keep_going_flag) fatal (NILF, l, _("%sNo rule to make target '%s'%s"), "", file->name, ""); error (NILF, l, _("%sNo rule to make target '%s'%s"), "*** ", file->name, "."); } file->no_diag = 0; } } #define PROFILE_TIME \ if (profile_flag && !time_error) { \ time_error = time_error || get_time(&finish_time); \ file->elapsed_time = time_diff(&start_time, &finish_time); \ if (p_call_stack->p_parent) \ add_target(file, p_call_stack->p_parent->p_target); \ } #define INCR_PROFILE_TIME \ if (profile_flag && !time_error) { \ time_error = time_error || get_time(&finish_time); \ file->elapsed_time += time_diff(&start_time, &finish_time); \ } /* Consider a single 'struct file' and update it as appropriate. Return 0 on success, or non-0 on failure. */ static enum update_status update_file_1 (struct file *file, unsigned int depth, target_stack_node_t *p_call_stack) { enum update_status dep_status = us_success; FILE_TIMESTAMP this_mtime; int noexist, must_make, deps_changed; struct file *ofile; struct dep *d, *ad; struct dep amake; int running = 0; struct timeval finish_time; struct timeval start_time; bool time_error = false; if (profile_flag) time_error = time_error || get_time(&start_time); DBF (DB_VERBOSE, _("Considering target file '%s'.\n")); p_stack_top = p_call_stack = trace_push_target(p_call_stack, file); /* We don't want to step into file dependencies when there are no associated commands. There or too often too many of them. */ if ( (i_debugger_stepping && file->cmds) || (file->tracing & BRK_BEFORE_PREREQ) ) enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_BEFORE_PREREQ); if (file->updated) { if (file->update_status > us_none) { DBF (DB_VERBOSE, _("Recently tried and failed to update file '%s'.\n")); /* If the file we tried to make is marked no_diag then no message was printed about it when it failed during the makefile rebuild. If we're trying to build it again in the normal rebuild, print a message now. */ if (file->no_diag && !file->dontcare) complain (file); return file->update_status; } DBF (DB_VERBOSE, _("File '%s' was considered already.\n")); INCR_PROFILE_TIME; trace_pop_target(p_call_stack); return 0; } switch (file->command_state) { case cs_not_started: case cs_deps_running: break; case cs_running: DBF (DB_VERBOSE, _("Still updating file '%s'.\n")); INCR_PROFILE_TIME; trace_pop_target(p_call_stack); return 0; case cs_finished: DBF (DB_VERBOSE, _("Finished updating file '%s'.\n")); INCR_PROFILE_TIME; trace_pop_target(p_call_stack); return file->update_status; default: abort (); } /* Determine whether the diagnostics will be issued should this update fail. */ file->no_diag = file->dontcare; ++depth; /* Notice recursive update of the same file. */ start_updating (file); /* We might change file if we find a different one via vpath; remember this one to turn off updating. */ ofile = file; /* Looking at the file's modtime beforehand allows the possibility that its name may be changed by a VPATH search, and thus it may not need an implicit rule. If this were not done, the file might get implicit commands that apply to its initial name, only to have that name replaced with another found by VPATH search. */ this_mtime = file_mtime (file); check_renamed (file); noexist = this_mtime == NONEXISTENT_MTIME; if (noexist) { DBF (DB_BASIC, _("File '%s' does not exist.\n")); if (i_debugger_nexting && file->cmds) { enter_debugger(p_call_stack, file, 0, DEBUG_STEP_HIT); } } else if (ORDINARY_MTIME_MIN <= this_mtime && this_mtime <= ORDINARY_MTIME_MAX && file->low_resolution_time) { /* Avoid spurious rebuilds due to low resolution time stamps. */ int ns = FILE_TIMESTAMP_NS (this_mtime); if (ns != 0) OS (error, NILF, _("*** Warning: .LOW_RESOLUTION_TIME file '%s' has a high resolution time stamp"), file->name); this_mtime += FILE_TIMESTAMPS_PER_S - 1 - ns; } must_make = noexist; /* If file was specified as a target with no commands, come up with some default commands. */ if (!file->phony && file->cmds == 0 && !file->tried_implicit) { if (try_implicit_rule (file, depth)) DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); else DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target && default_file != 0 && default_file->cmds != 0) { DBF (DB_IMPLICIT, _("Using default recipe for '%s'.\n")); file->cmds = default_file->cmds; } /* Update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than this file. We need to walk our deps, AND the deps of any also_make targets to ensure everything happens in the correct order. */ amake.file = file; amake.next = file->also_make; ad = &amake; while (ad) { struct dep *lastd = 0; /* Find the deps we're scanning */ d = ad->file->deps; ad = ad->next; while (d) { enum update_status new; FILE_TIMESTAMP mtime; int maybe_make; int dontcare = 0; check_renamed (d->file); mtime = file_mtime (d->file); check_renamed (d->file); if (is_updating (d->file)) { OSS (error, NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); /* We cannot free D here because our the caller will still have a reference to it when we were called recursively via check_dep below. */ if (lastd == 0) file->deps = d->next; else lastd->next = d->next; d = d->next; continue; } d->file->parent = file; maybe_make = must_make; /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) { dontcare = d->file->dontcare; d->file->dontcare = file->dontcare; } new = check_dep (d->file, depth, this_mtime, &maybe_make, p_call_stack); if (new > dep_status) dep_status = new; /* Restore original dontcare flag. */ if (rebuilding_makefiles) d->file->dontcare = dontcare; if (! d->ignore_mtime) must_make = maybe_make; check_renamed (d->file); { register struct file *f = d->file; if (f->double_colon) f = f->double_colon; do { running |= (f->command_state == cs_running || f->command_state == cs_deps_running); f = f->prev; } while (f != 0); } if (dep_status && !keep_going_flag) break; if (!running) /* The prereq is considered changed if the timestamp has changed while it was built, OR it doesn't exist. */ d->changed = ((file_mtime (d->file) != mtime) || (mtime == NONEXISTENT_MTIME)); lastd = d; d = d->next; } } /* Now we know whether this target needs updating. If it does, update all the intermediate files we depend on. */ if (must_make || always_make_flag) { for (d = file->deps; d != 0; d = d->next) if (d->file->intermediate) { enum update_status new; int dontcare = 0; FILE_TIMESTAMP mtime = file_mtime (d->file); check_renamed (d->file); d->file->parent = file; /* Inherit dontcare flag from our parent. */ if (rebuilding_makefiles) { dontcare = d->file->dontcare; d->file->dontcare = file->dontcare; } /* We may have already considered this file, when we didn't know we'd need to update it. Force update_file() to consider it and not prune it. */ d->file->considered = !considered; new = update_file (d->file, depth, p_call_stack); if (new > dep_status) dep_status = new; /* Restore original dontcare flag. */ if (rebuilding_makefiles) d->file->dontcare = dontcare; check_renamed (d->file); { register struct file *f = d->file; if (f->double_colon) f = f->double_colon; do { running |= (f->command_state == cs_running || f->command_state == cs_deps_running); f = f->prev; } while (f != 0); } if (dep_status && !keep_going_flag) break; if (!running) d->changed = ((file->phony && file->cmds != 0) || file_mtime (d->file) != mtime); } } finish_updating (file); finish_updating (ofile); DBF (DB_VERBOSE, _("Finished prerequisites of target file '%s'.\n")); if ( file->tracing & BRK_AFTER_PREREQ ) enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_AFTER_PREREQ); if (running) { set_command_state (file, cs_deps_running); --depth; DBF (DB_VERBOSE, _("The prerequisites of '%s' are being made.\n")); INCR_PROFILE_TIME; trace_pop_target(p_call_stack); return 0; } /* If any dependency failed, give up now. */ if (dep_status) { /* I'm not sure if we can't just assign dep_status... */ file->update_status = dep_status == us_none ? us_failed : dep_status; notice_finished_file (file); --depth; DBF (DB_VERBOSE, _("Giving up on target file '%s'.\n")); PROFILE_TIME; if (depth == 0 && keep_going_flag && !just_print_flag && !question_flag) OS (error, NILF, _("Target '%s' not remade because of errors."), file->name); trace_pop_target(p_call_stack); return dep_status; } if (file->command_state == cs_deps_running) /* The commands for some deps were running on the last iteration, but they have finished now. Reset the command_state to not_started to simplify later bookkeeping. It is important that we do this only when the prior state was cs_deps_running, because that prior state was definitely propagated to FILE's also_make's by set_command_state (called above), but in another state an also_make may have independently changed to finished state, and we would confuse that file's bookkeeping (updated, but not_started is bogus state). */ set_command_state (file, cs_not_started); /* Now record which prerequisites are more recent than this file, so we can define $?. */ deps_changed = 0; for (d = file->deps; d != 0; d = d->next) { FILE_TIMESTAMP d_mtime = file_mtime (d->file); check_renamed (d->file); if (! d->ignore_mtime) { #if 1 /* %%% In version 4, remove this code completely to implement not remaking deps if their deps are newer than their parents. */ if (d_mtime == NONEXISTENT_MTIME && !d->file->intermediate) /* We must remake if this dep does not exist and is not intermediate. */ must_make = 1; #endif /* Set DEPS_CHANGED if this dep actually changed. */ deps_changed |= d->changed; } /* Set D->changed if either this dep actually changed, or its dependent, FILE, is older or does not exist. */ d->changed |= noexist || d_mtime > this_mtime; if (!noexist && ISDB (DB_BASIC|DB_VERBOSE)) { const char *fmt = 0; if (d->ignore_mtime) { if (ISDB (DB_VERBOSE)) fmt = _("Prerequisite '%s' is order-only for target '%s'.\n"); } else if (d_mtime == NONEXISTENT_MTIME) { if (ISDB (DB_BASIC)) fmt = _("Prerequisite '%s' of target '%s' does not exist.\n"); } else if (d->changed) { if (ISDB (DB_BASIC)) fmt = _("Prerequisite '%s' is newer than target '%s'.\n"); } else if (ISDB (DB_VERBOSE)) fmt = _("Prerequisite '%s' is older than target '%s'.\n"); if (fmt) { print_spaces (depth); printf (fmt, dep_name (d), file->name); fflush (stdout); } } } /* Here depth returns to the value it had when we were called. */ depth--; if (file->double_colon && file->deps == 0) { must_make = 1; DBF (DB_BASIC, _("Target '%s' is double-colon and has no prerequisites.\n")); } else if (!noexist && file->is_target && !deps_changed && file->cmds == 0 && !always_make_flag) { must_make = 0; DBF (DB_VERBOSE, _("No recipe for '%s' and no prerequisites actually changed.\n")); } else if (!must_make && file->cmds != 0 && always_make_flag) { must_make = 1; DBF (DB_VERBOSE, _("Making '%s' due to always-make flag.\n")); } if (!must_make) { if (ISDB (DB_VERBOSE)) { print_spaces (depth); printf (_("No need to remake target '%s'"), file->name); if (!streq (file->name, file->hname)) printf (_("; using VPATH name '%s'"), file->hname); puts ("."); fflush (stdout); } notice_finished_file (file); /* Since we don't need to remake the file, convert it to use the VPATH filename if we found one. hfile will be either the local name if no VPATH or the VPATH name if one was found. */ PROFILE_TIME; while (file) { file->name = file->hname; file = file->prev; } trace_pop_target(p_call_stack); return 0; } DBF (DB_BASIC, _("Must remake target '%s'.\n")); /* It needs to be remade. If it's VPATH and not reset via GPATH, toss the VPATH. */ if (!streq (file->name, file->hname)) { DB (DB_BASIC, (_(" Ignoring VPATH name '%s'.\n"), file->hname)); file->ignore_vpath = 1; } /* Now, take appropriate actions to remake the file. */ remake_file (file, p_call_stack); if (file->command_state != cs_finished) { DBF (DB_VERBOSE, _("Recipe of '%s' is being run.\n")); if ( file->tracing & BRK_AFTER_CMD || i_debugger_stepping ) enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_AFTER_CMD); PROFILE_TIME; trace_pop_target(p_call_stack); return 0; } switch (file->update_status) { case us_failed: DBF (DB_BASIC, _("Failed to remake target file '%s'.\n")); break; case us_success: DBF (DB_BASIC, _("Successfully remade target file '%s'.\n")); break; case us_question: DBF (DB_BASIC, _("Target file '%s' needs to be remade under -q.\n")); break; case us_none: break; } file->updated = 1; if ( file->tracing & BRK_AFTER_CMD || i_debugger_stepping ) enter_debugger(p_call_stack, file, 0, DEBUG_BRKPT_AFTER_CMD); PROFILE_TIME; trace_pop_target(p_call_stack); return file->update_status; } /* Set FILE's 'updated' flag and re-check its mtime and the mtime's of all files listed in its 'also_make' member. Under -t, this function also touches FILE. On return, FILE->update_status will no longer be us_none if it was. */ void notice_finished_file (struct file *file) { struct dep *d; int ran = file->command_state == cs_running; int touched = 0; file->command_state = cs_finished; file->updated = 1; if (touch_flag /* The update status will be: us_success if 0 or more commands (+ or ${MAKE}) were run and won; us_none if this target was not remade; >us_none if some commands were run and lost. We touch the target if it has commands which either were not run or won when they ran (i.e. status is 0). */ && file->update_status == us_success) { if (file->cmds != 0 && file->cmds->any_recurse) { /* If all the command lines were recursive, we don't want to do the touching. */ unsigned int i; for (i = 0; i < file->cmds->ncommand_lines; ++i) if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE)) goto have_nonrecursing; } else { have_nonrecursing: if (file->phony) file->update_status = us_success; /* According to POSIX, -t doesn't affect targets with no cmds. */ else if (file->cmds != 0) { /* Should set file's modification date and do nothing else. */ file->update_status = touch_file (file); /* Pretend we ran a real touch command, to suppress the "'foo' is up to date" message. */ commands_started++; /* Request for the timestamp to be updated (and distributed to the double-colon entries). Simply setting ran=1 would almost have done the trick, but messes up with the also_make updating logic below. */ touched = 1; } } } if (file->mtime_before_update == UNKNOWN_MTIME) file->mtime_before_update = file->last_mtime; if ((ran && !file->phony) || touched) { int i = 0; /* If -n, -t, or -q and all the commands are recursive, we ran them so really check the target's mtime again. Otherwise, assume the target would have been updated. */ if ((question_flag || just_print_flag || touch_flag) && file->cmds) { for (i = file->cmds->ncommand_lines; i > 0; --i) if (! (file->cmds->lines_flags[i-1] & COMMANDS_RECURSE)) break; } /* If there were no commands at all, it's always new. */ else if (file->is_target && file->cmds == 0) i = 1; file->last_mtime = i == 0 ? UNKNOWN_MTIME : NEW_MTIME; } if (file->double_colon) { /* If this is a double colon rule and it is the last one to be updated, propagate the change of modification time to all the double-colon entries for this file. We do it on the last update because it is important to handle individual entries as separate rules with separate timestamps while they are treated as targets and then as one rule with the unified timestamp when they are considered as a prerequisite of some target. */ struct file *f; FILE_TIMESTAMP max_mtime = file->last_mtime; /* Check that all rules were updated and at the same time find the max timestamp. We assume UNKNOWN_MTIME is newer then any other value. */ for (f = file->double_colon; f != 0 && f->updated; f = f->prev) if (max_mtime != UNKNOWN_MTIME && (f->last_mtime == UNKNOWN_MTIME || f->last_mtime > max_mtime)) max_mtime = f->last_mtime; if (f == 0) for (f = file->double_colon; f != 0; f = f->prev) f->last_mtime = max_mtime; } if (ran && file->update_status != us_none) /* We actually tried to update FILE, which has updated its also_make's as well (if it worked). If it didn't work, it wouldn't work again for them. So mark them as updated with the same status. */ for (d = file->also_make; d != 0; d = d->next) { d->file->command_state = cs_finished; d->file->updated = 1; d->file->update_status = file->update_status; if (ran && !d->file->phony) /* Fetch the new modification time. We do this instead of just invalidating the cached time so that a vpath_search can happen. Otherwise, it would never be done because the target is already updated. */ f_mtime (d->file, 0); } else if (file->update_status == us_none) /* Nothing was done for FILE, but it needed nothing done. So mark it now as "succeeded". */ file->update_status = us_success; } /* Check whether another file (whose mtime is THIS_MTIME) needs updating on account of a dependency which is file FILE. If it does, store 1 in *MUST_MAKE_PTR. In the process, update any non-intermediate files that FILE depends on (including FILE itself). Return nonzero if any updating failed. */ static enum update_status check_dep (struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr, target_stack_node_t *p_call_stack) { struct file *ofile; struct dep *d; enum update_status dep_status = us_success; ++depth; start_updating (file); /* We might change file if we find a different one via vpath; remember this one to turn off updating. */ ofile = file; if (file->phony || !file->intermediate) { /* If this is a non-intermediate file, update it and record whether it is newer than THIS_MTIME. */ FILE_TIMESTAMP mtime; dep_status = update_file (file, depth, p_call_stack); check_renamed (file); mtime = file_mtime (file); check_renamed (file); if (mtime == NONEXISTENT_MTIME || mtime > this_mtime) *must_make_ptr = 1; } else { /* FILE is an intermediate file. */ FILE_TIMESTAMP mtime; if (!file->phony && file->cmds == 0 && !file->tried_implicit) { if (try_implicit_rule (file, depth)) DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n")); else DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n")); file->tried_implicit = 1; } if (file->cmds == 0 && !file->is_target && default_file != 0 && default_file->cmds != 0) { DBF (DB_IMPLICIT, _("Using default commands for '%s'.\n")); file->cmds = default_file->cmds; } check_renamed (file); mtime = file_mtime (file); check_renamed (file); if (mtime != NONEXISTENT_MTIME && mtime > this_mtime) /* If the intermediate file actually exists and is newer, then we should remake from it. */ *must_make_ptr = 1; else { /* Otherwise, update all non-intermediate files we depend on, if necessary, and see whether any of them is more recent than the file on whose behalf we are checking. */ struct dep *ld; int deps_running = 0; /* If this target is not running, set it's state so that we check it fresh. It could be it was checked as part of an order-only prerequisite and so wasn't rebuilt then, but should be now. */ if (file->command_state != cs_running) { /* If the target was waiting for a dependency it has to be reconsidered, as that dependency might have finished. */ if (file->command_state == cs_deps_running) file->considered = !considered; set_command_state (file, cs_not_started); } ld = 0; d = file->deps; while (d != 0) { enum update_status new; int maybe_make; if (is_updating (d->file)) { OSS (error, NILF, _("Circular %s <- %s dependency dropped."), file->name, d->file->name); if (ld == 0) { file->deps = d->next; free_dep (d); d = file->deps; } else { ld->next = d->next; free_dep (d); d = ld->next; } continue; } d->file->parent = file; maybe_make = *must_make_ptr; new = check_dep (d->file, depth, this_mtime, &maybe_make, p_call_stack); if (new > dep_status) dep_status = new; if (! d->ignore_mtime) *must_make_ptr = maybe_make; check_renamed (d->file); if (dep_status && !keep_going_flag) break; if (d->file->command_state == cs_running || d->file->command_state == cs_deps_running) deps_running = 1; ld = d; d = d->next; } if (deps_running) /* Record that some of FILE's deps are still being made. This tells the upper levels to wait on processing it until the commands are finished. */ set_command_state (file, cs_deps_running); } } finish_updating (file); finish_updating (ofile); return dep_status; } /* Touch FILE. Return us_success if successful, us_failed if not. */ #define TOUCH_ERROR(call) do{ perror_with_name ((call), file->name); \ return us_failed; }while(0) static enum update_status touch_file (struct file *file) { if (!silent_flag) OS (message, 0, "touch %s", file->name); /* Print-only (-n) takes precedence over touch (-t). */ if (just_print_flag) return us_success; #ifndef NO_ARCHIVES if (ar_name (file->name)) return ar_touch (file->name) ? us_failed : us_success; else #endif { int fd = open (file->name, O_RDWR | O_CREAT, 0666); if (fd < 0) TOUCH_ERROR ("touch: open: "); else { struct stat statbuf; char buf = 'x'; int e; EINTRLOOP (e, fstat (fd, &statbuf)); if (e < 0) TOUCH_ERROR ("touch: fstat: "); /* Rewrite character 0 same as it already is. */ if (read (fd, &buf, 1) < 0) TOUCH_ERROR ("touch: read: "); if (lseek (fd, 0L, 0) < 0L) TOUCH_ERROR ("touch: lseek: "); if (write (fd, &buf, 1) < 0) TOUCH_ERROR ("touch: write: "); /* If file length was 0, we just changed it, so change it back. */ if (statbuf.st_size == 0) { (void) close (fd); fd = open (file->name, O_RDWR | O_TRUNC, 0666); if (fd < 0) TOUCH_ERROR ("touch: open: "); } (void) close (fd); } } return us_success; } /* Having checked and updated the dependencies of FILE, do whatever is appropriate to remake FILE itself. Return the status from executing FILE's commands. */ static void remake_file (file_t *file, target_stack_node_t *p_call_stack) { if (file->cmds == 0) { if (file->phony) /* Phony target. Pretend it succeeded. */ file->update_status = us_success; else if (file->is_target) /* This is a nonexistent target file we cannot make. Pretend it was successfully remade. */ file->update_status = us_success; else { /* This is a dependency file we cannot remake. Fail. */ if (!rebuilding_makefiles || !file->dontcare) complain (file); file->update_status = us_failed; } } else { chop_commands (file->cmds); /* The normal case: start some commands. */ if (!touch_flag || file->cmds->any_recurse) { execute_file_commands (file, p_call_stack); return; } /* This tells notice_finished_file it is ok to touch the file. */ file->update_status = us_success; } /* This does the touching under -t. */ notice_finished_file (file); } /* Return the mtime of a file, given a 'struct file'. Caches the time in the struct file to avoid excess stat calls. If the file is not found, and SEARCH is nonzero, VPATH searching and replacement is done. If that fails, a library (-lLIBNAME) is tried and the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into FILE. */ FILE_TIMESTAMP f_mtime (struct file *file, int search) { FILE_TIMESTAMP mtime; /* File's mtime is not known; must get it from the system. */ #ifndef NO_ARCHIVES if (ar_name (file->name)) { /* This file is an archive-member reference. */ char *arname, *memname; struct file *arfile; int found; time_t member_date; /* Find the archive's name. */ ar_parse_name (file->name, &arname, &memname); /* Find the modification time of the archive itself. Also allow for its name to be changed via VPATH search. */ arfile = lookup_file (arname); if (arfile == 0) arfile = enter_file (strcache_add (arname)); mtime = f_mtime (arfile, search); check_renamed (arfile); if (search && strcmp (arfile->hname, arname)) { /* The archive's name has changed. Change the archive-member reference accordingly. */ char *name; unsigned int arlen, memlen; arlen = strlen (arfile->hname); memlen = strlen (memname); name = alloca (arlen + 1 + memlen + 2); memcpy (name, arfile->hname, arlen); name[arlen] = '('; memcpy (name + arlen + 1, memname, memlen); name[arlen + 1 + memlen] = ')'; name[arlen + 1 + memlen + 1] = '\0'; /* If the archive was found with GPATH, make the change permanent; otherwise defer it until later. */ if (arfile->name == arfile->hname) rename_file (file, strcache_add (name)); else rehash_file (file, strcache_add (name)); check_renamed (file); } free (arname); file->low_resolution_time = 1; if (mtime == NONEXISTENT_MTIME) /* The archive doesn't exist, so its members don't exist either. */ return NONEXISTENT_MTIME; found = ar_member_date (file->hname, &member_date); if (found && member_date == (time_t) 0) { OSS (error, NILF, _("Warning: Archive '%s' seems to have been created in deterministic mode. '%s' will always be updated. Please consider passing the U flag to ar to avoid the problem."), arfile->name, memname); } mtime = found ? file_timestamp_cons (file->hname, member_date, 0) : NONEXISTENT_MTIME; } else #endif { mtime = name_mtime (file->name); if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath) { /* If name_mtime failed, search VPATH. */ const char *name = vpath_search (file->name, &mtime, NULL, NULL); if (name /* Last resort, is it a library (-lxxx)? */ || (file->name[0] == '-' && file->name[1] == 'l' && (name = library_search (file->name, &mtime)) != 0)) { if (mtime != UNKNOWN_MTIME) /* vpath_search and library_search store UNKNOWN_MTIME if they didn't need to do a stat call for their work. */ file->last_mtime = mtime; /* If we found it in VPATH, see if it's in GPATH too; if so, change the name right now; if not, defer until after the dependencies are updated. */ if (gpath_search (name, strlen (name) - strlen (file->name) - 1)) { rename_file (file, name); check_renamed (file); return file_mtime (file); } rehash_file (file, name); check_renamed (file); /* If the result of a vpath search is -o or -W, preserve it. Otherwise, find the mtime of the resulting file. */ if (mtime != OLD_MTIME && mtime != NEW_MTIME) mtime = name_mtime (name); } } } /* Files can have bogus timestamps that nothing newly made will be "newer" than. Updating their dependents could just result in loops. So notify the user of the anomaly with a warning. We only need to do this once, for now. */ if (!clock_skew_detected && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME && !file->updated) { static FILE_TIMESTAMP adjusted_now; FILE_TIMESTAMP adjusted_mtime = mtime; #if defined(WINDOWS32) || defined(__MSDOS__) /* Experimentation has shown that FAT filesystems can set file times up to 3 seconds into the future! Play it safe. */ #define FAT_ADJ_OFFSET (FILE_TIMESTAMP) 3 FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS; if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime) adjusted_mtime -= adjustment; #elif defined(__EMX__) /* FAT filesystems round time to the nearest even second! Allow for any file (NTFS or FAT) to perhaps suffer from this brain damage. */ FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0 && FILE_TIMESTAMP_NS (adjusted_mtime) == 0) ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS : 0); #endif /* If the file's time appears to be in the future, update our concept of the present and try once more. */ if (adjusted_now < adjusted_mtime) { int resolution; FILE_TIMESTAMP now = file_timestamp_now (&resolution); adjusted_now = now + (resolution - 1); if (adjusted_now < adjusted_mtime) { #ifdef NO_FLOAT OS (error, NILF, _("Warning: File '%s' has modification time in the future"), file->name); #else double from_now = (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now) + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now)) / 1e9)); char from_now_string[100]; if (from_now >= 99 && from_now <= ULONG_MAX) sprintf (from_now_string, "%lu", (unsigned long) from_now); else sprintf (from_now_string, "%.2g", from_now); OSS (error, NILF, _("Warning: File '%s' has modification time %s s in the future"), file->name, from_now_string); #endif clock_skew_detected = 1; } } } /* Store the mtime into all the entries for this file. */ if (file->double_colon) file = file->double_colon; do { /* If this file is not implicit but it is intermediate then it was made so by the .INTERMEDIATE target. If this file has never been built by us but was found now, it existed before make started. So, turn off the intermediate bit so make doesn't delete it, since it didn't create it. */ if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started && !file->tried_implicit && file->intermediate) file->intermediate = 0; file->last_mtime = mtime; file = file->prev; } while (file != 0); return mtime; } /* Return the mtime of the file or archive-member reference NAME. */ /* First, we check with stat(). If the file does not exist, then we return NONEXISTENT_MTIME. If it does, and the symlink check flag is set, then examine each indirection of the symlink and find the newest mtime. This causes one duplicate stat() when -L is being used, but the code is much cleaner. */ static FILE_TIMESTAMP name_mtime (const char *name) { FILE_TIMESTAMP mtime; struct stat st; int e; EINTRLOOP (e, stat (name, &st)); if (e == 0) mtime = FILE_TIMESTAMP_STAT_MODTIME (name, st); else if (errno == ENOENT || errno == ENOTDIR) mtime = NONEXISTENT_MTIME; else { perror_with_name ("stat: ", name); return NONEXISTENT_MTIME; } /* If we get here we either found it, or it doesn't exist. If it doesn't exist see if we can use a symlink mtime instead. */ #ifdef MAKE_SYMLINKS #ifndef S_ISLNK # define S_ISLNK(_m) (((_m)&S_IFMT)==S_IFLNK) #endif if (check_symlink_flag) { PATH_VAR (lpath); /* Check each symbolic link segment (if any). Find the latest mtime amongst all of them (and the target file of course). Note that we have already successfully dereferenced all the links above. So, if we run into any error trying to lstat(), or readlink(), or whatever, something bizarre-o happened. Just give up and use whatever mtime we've already computed at that point. */ strcpy (lpath, name); while (1) { FILE_TIMESTAMP ltime; PATH_VAR (lbuf); long llen; char *p; EINTRLOOP (e, lstat (lpath, &st)); if (e) { /* Just take what we have so far. */ if (errno != ENOENT && errno != ENOTDIR) perror_with_name ("lstat: ", lpath); break; } /* If this is not a symlink, we're done (we started with the real file's mtime so we don't need to test it again). */ if (!S_ISLNK (st.st_mode)) break; /* If this mtime is newer than what we had, keep the new one. */ ltime = FILE_TIMESTAMP_STAT_MODTIME (lpath, st); if (ltime > mtime) mtime = ltime; /* Set up to check the file pointed to by this link. */ EINTRLOOP (llen, readlink (lpath, lbuf, GET_PATH_MAX)); if (llen < 0) { /* Eh? Just take what we have. */ perror_with_name ("readlink: ", lpath); break; } lbuf[llen] = '\0'; /* If the target is fully-qualified or the source is just a filename, then the new path is the target. Otherwise it's the source directory plus the target. */ if (lbuf[0] == '/' || (p = strrchr (lpath, '/')) == NULL) strcpy (lpath, lbuf); else if ((p - lpath) + llen + 2 > GET_PATH_MAX) /* Eh? Path too long! Again, just go with what we have. */ break; else /* Create the next step in the symlink chain. */ strcpy (p+1, lbuf); } } #endif return mtime; } /* Search for a library file specified as -lLIBNAME, searching for a suitable library file in the system library directories and the VPATH directories. */ static const char * library_search (const char *lib, FILE_TIMESTAMP *mtime_ptr) { static const char *dirs[] = { #ifndef _AMIGA "/lib", "/usr/lib", #endif #if defined(WINDOWS32) && !defined(LIBDIR) /* * This is completely up to the user at product install time. Just define * a placeholder. */ #define LIBDIR "." #endif LIBDIR, /* Defined by configuration. */ 0 }; const char *file = 0; char *libpatterns; FILE_TIMESTAMP mtime; /* Loop variables for the libpatterns value. */ char *p; const char *p2; unsigned int len; unsigned int liblen; /* Information about the earliest (in the vpath sequence) match. */ unsigned int best_vpath = 0, best_path = 0; const char **dp; libpatterns = xstrdup (variable_expand ("$(.LIBPATTERNS)")); /* Skip the '-l'. */ lib += 2; liblen = strlen (lib); /* Loop through all the patterns in .LIBPATTERNS, and search on each one. To implement the linker-compatible behavior we have to search through all entries in .LIBPATTERNS and choose the "earliest" one. */ p2 = libpatterns; while ((p = find_next_token (&p2, &len)) != 0) { static char *buf = NULL; static unsigned int buflen = 0; static int libdir_maxlen = -1; static unsigned int std_dirs = 0; char *libbuf = variable_expand (""); /* Expand the pattern using LIB as a replacement. */ { char c = p[len]; char *p3, *p4; p[len] = '\0'; p3 = find_percent (p); if (!p3) { /* Give a warning if there is no pattern. */ OS (error, NILF, _(".LIBPATTERNS element '%s' is not a pattern"), p); p[len] = c; continue; } p4 = variable_buffer_output (libbuf, p, p3-p); p4 = variable_buffer_output (p4, lib, liblen); p4 = variable_buffer_output (p4, p3+1, len - (p3-p)); p[len] = c; } /* Look first for 'libNAME.a' in the current directory. */ mtime = name_mtime (libbuf); if (mtime != NONEXISTENT_MTIME) { if (mtime_ptr != 0) *mtime_ptr = mtime; file = strcache_add (libbuf); /* This by definition will have the best index, so stop now. */ break; } /* Now try VPATH search on that. */ { unsigned int vpath_index, path_index; const char* f = vpath_search (libbuf, mtime_ptr ? &mtime : NULL, &vpath_index, &path_index); if (f) { /* If we have a better match, record it. */ if (file == 0 || vpath_index < best_vpath || (vpath_index == best_vpath && path_index < best_path)) { file = f; best_vpath = vpath_index; best_path = path_index; if (mtime_ptr != 0) *mtime_ptr = mtime; } } } /* Now try the standard set of directories. */ if (!buflen) { for (dp = dirs; *dp != 0; ++dp) { int l = strlen (*dp); if (l > libdir_maxlen) libdir_maxlen = l; std_dirs++; } buflen = strlen (libbuf); buf = xmalloc (libdir_maxlen + buflen + 2); } else if (buflen < strlen (libbuf)) { buflen = strlen (libbuf); buf = xrealloc (buf, libdir_maxlen + buflen + 2); } { /* Use the last std_dirs index for standard directories. This was it will always be greater than the VPATH index. */ unsigned int vpath_index = ~((unsigned int)0) - std_dirs; for (dp = dirs; *dp != 0; ++dp) { sprintf (buf, "%s/%s", *dp, libbuf); mtime = name_mtime (buf); if (mtime != NONEXISTENT_MTIME) { if (file == 0 || vpath_index < best_vpath) { file = strcache_add (buf); best_vpath = vpath_index; if (mtime_ptr != 0) *mtime_ptr = mtime; } } vpath_index++; } } } free (libpatterns); return file; } remake-4.1+dbg1.3~dfsg.1/remote-cstms.c000066400000000000000000000205711317072305000175660ustar00rootroot00000000000000/* GNU Make remote job exportation interface to the Customs daemon. THIS CODE IS NOT SUPPORTED BY THE GNU PROJECT. Please do not send bug reports or questions about it to the Make maintainers. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "commands.h" #include "job.h" #include "debug.h" #include #include #include "customs.h" char *remote_description = "Customs"; /* File name of the Customs 'export' client command. A full path name can be used to avoid some path-searching overhead. */ #define EXPORT_COMMAND "/usr/local/bin/export" /* ExportPermit gotten by start_remote_job_p, and used by start_remote_job. */ static ExportPermit permit; /* Normalized path name of the current directory. */ static char *normalized_cwd; /* Call once at startup even if no commands are run. */ void remote_setup (void) { } /* Called before exit. */ void remote_cleanup (void) { } /* Return nonzero if the next job should be done remotely. */ int start_remote_job_p (int first_p) { static int inited = 0; int status; int njobs; if (!inited) { /* Allow the user to turn off job exportation (useful while he is debugging Customs, for example). */ if (getenv ("GNU_MAKE_NO_CUSTOMS") != 0) { inited = -1; return 0; } /* For secure Customs, make is installed setuid root and Customs requires a privileged source port be used. */ make_access (); if (ISDB (DB_JOBS)) Rpc_Debug (1); /* Ping the daemon once to see if it is there. */ inited = Customs_Ping () == RPC_SUCCESS ? 1 : -1; /* Return to normal user access. */ user_access (); if (starting_directory == 0) /* main couldn't figure it out. */ inited = -1; else { /* Normalize the current directory path name to something that should work on all machines exported to. */ normalized_cwd = xmalloc (GET_PATH_MAX); strcpy (normalized_cwd, starting_directory); if (Customs_NormPath (normalized_cwd, GET_PATH_MAX) < 0) /* Path normalization failure means using Customs won't work, but it's not really an error. */ inited = -1; } } if (inited < 0) return 0; njobs = job_slots_used; if (!first_p) njobs -= 1; /* correction for being called from reap_children() */ /* the first job should run locally, or, if the -l flag is given, we use that as clue as to how many local jobs should be scheduled locally */ if (max_load_average < 0 && njobs == 0 || njobs < max_load_average) return 0; status = Customs_Host (EXPORT_SAME, &permit); if (status != RPC_SUCCESS) { DB (DB_JOBS, (_("Customs won't export: %s\n"), Rpc_ErrorMessage (status))); return 0; } return !CUSTOMS_FAIL (&permit.addr); } /* Start a remote job running the command in ARGV, with environment from ENVP. It gets standard input from STDIN_FD. On failure, return nonzero. On success, return zero, and set *USED_STDIN to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to a unique identification, and set *IS_REMOTE to nonzero if the job is remote, zero if it is local (meaning *ID_PTR is a process ID). */ int start_remote_job (char **argv, char **envp, int stdin_fd, int *is_remote, int *id_ptr, int *used_stdin) { char waybill[MAX_DATA_SIZE], msg[128]; struct hostent *host; struct timeval timeout; struct sockaddr_in sin; int len; int retsock, retport, sock; Rpc_Stat status; int pid; /* Create the return socket. */ retsock = Rpc_UdpCreate (True, 0); if (retsock < 0) { O (error, NILF, "exporting: Couldn't create return socket."); return 1; } /* Get the return socket's port number. */ len = sizeof (sin); if (getsockname (retsock, (struct sockaddr *) &sin, &len) < 0) { (void) close (retsock); perror_with_name ("exporting: ", "getsockname"); return 1; } retport = sin.sin_port; /* Create the TCP socket for talking to the remote child. */ sock = Rpc_TcpCreate (False, 0); /* Create a WayBill to give to the server. */ len = Customs_MakeWayBill (&permit, normalized_cwd, argv[0], argv, envp, retport, waybill); /* Modify the waybill as if the remote child had done 'child_access ()'. */ { WayBill *wb = (WayBill *) waybill; wb->ruid = wb->euid; wb->rgid = wb->egid; } /* Send the request to the server, timing out in 20 seconds. */ timeout.tv_usec = 0; timeout.tv_sec = 20; sin.sin_family = AF_INET; sin.sin_port = htons (Customs_Port ()); sin.sin_addr = permit.addr; status = Rpc_Call (sock, &sin, (Rpc_Proc) CUSTOMS_IMPORT, len, (Rpc_Opaque) waybill, sizeof (msg), (Rpc_Opaque) msg, 1, &timeout); host = gethostbyaddr ((char *)&permit.addr, sizeof(permit.addr), AF_INET); { const char *hnm = host ? host->h_name : inet_ntoa (permit.addr); size_t hlen = strlen (hnm); if (status != RPC_SUCCESS) { const char *err = Rpc_ErrorMessage (status); (void) close (retsock); (void) close (sock); error (NILF, hlen + strlen (err), "exporting to %s: %s", hnm, err); return 1; } else if (msg[0] != 'O' || msg[1] != 'k' || msg[2] != '\0') { (void) close (retsock); (void) close (sock); error (NILF, hlen + strlen (msg), "exporting to %s: %s", hnm, msg); return 1; } else { error (NILF, hlen + INTSTR_LENGTH, "*** exported to %s (id %u)", hnm, permit.id); } fflush (stdout); fflush (stderr); } pid = fork (); if (pid < 0) { /* The fork failed! */ perror_with_name ("fork", ""); return 1; } else if (pid == 0) { /* Child side. Run 'export' to handle the connection. */ static char sock_buf[20], retsock_buf[20], id_buf[20]; static char *new_argv[6] = { EXPORT_COMMAND, "-id", sock_buf, retsock_buf, id_buf, 0 }; /* Set up the arguments. */ (void) sprintf (sock_buf, "%d", sock); (void) sprintf (retsock_buf, "%d", retsock); (void) sprintf (id_buf, "%x", permit.id); /* Get the right stdin. */ if (stdin_fd != 0) (void) dup2 (stdin_fd, 0); /* Unblock signals in the child. */ unblock_sigs (); /* Run the command. */ exec_command (new_argv, envp); } /* Parent side. Return the 'export' process's ID. */ (void) close (retsock); (void) close (sock); *is_remote = 0; *id_ptr = pid; *used_stdin = 1; return 0; } /* Get the status of a dead remote child. Block waiting for one to die if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR to the termination signal or zero if it exited normally, and *COREDUMP_PTR nonzero if it dumped core. Return the ID of the child that died, 0 if we would have to block and !BLOCK, or < 0 if there were none. */ int remote_status (int *exit_code_ptr, int *signal_ptr, int *coredump_ptr, int block) { return -1; } /* Block asynchronous notification of remote child death. If this notification is done by raising the child termination signal, do not block that signal. */ void block_remote_children (void) { return; } /* Restore asynchronous notification of remote child death. If this is done by raising the child termination signal, do not unblock that signal. */ void unblock_remote_children (void) { return; } /* Send signal SIG to child ID. Return 0 if successful, -1 if not. */ int remote_kill (int id, int sig) { return -1; } remake-4.1+dbg1.3~dfsg.1/remote-stub.c000066400000000000000000000054221317072305000174100ustar00rootroot00000000000000/* Template for the remote job exportation interface to GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "job.h" #include "commands.h" /* Call once at startup even if no commands are run. */ void remote_setup (void) { } /* Called before exit. */ void remote_cleanup (void) { } /* Return nonzero if the next job should be done remotely. */ int start_remote_job_p (int first_p UNUSED) { return 0; } /* Start a remote job running the command in ARGV, with environment from ENVP. It gets standard input from STDIN_FD. On failure, return nonzero. On success, return zero, and set *USED_STDIN to nonzero if it will actually use STDIN_FD, zero if not, set *ID_PTR to a unique identification, and set *IS_REMOTE to zero if the job is local, nonzero if it is remote (meaning *ID_PTR is a process ID). */ int start_remote_job (char **argv UNUSED, char **envp UNUSED, int stdin_fd UNUSED, int *is_remote UNUSED, int *id_ptr UNUSED, int *used_stdin UNUSED) { return -1; } /* Get the status of a dead remote child. Block waiting for one to die if BLOCK is nonzero. Set *EXIT_CODE_PTR to the exit status, *SIGNAL_PTR to the termination signal or zero if it exited normally, and *COREDUMP_PTR nonzero if it dumped core. Return the ID of the child that died, 0 if we would have to block and !BLOCK, or < 0 if there were none. */ int remote_status (int *exit_code_ptr UNUSED, int *signal_ptr UNUSED, int *coredump_ptr UNUSED, int block UNUSED) { errno = ECHILD; return -1; } /* Block asynchronous notification of remote child death. If this notification is done by raising the child termination signal, do not block that signal. */ void block_remote_children (void) { return; } /* Restore asynchronous notification of remote child death. If this is done by raising the child termination signal, do not unblock that signal. */ void unblock_remote_children (void) { return; } /* Send signal SIG to child ID. Return 0 if successful, -1 if not. */ int remote_kill (int id UNUSED, int sig UNUSED) { return -1; } remake-4.1+dbg1.3~dfsg.1/rpm/000077500000000000000000000000001317072305000155715ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/rpm/README.md000066400000000000000000000005501317072305000170500ustar00rootroot00000000000000How to use ---------- * Copy the approproate tarball to `rmbuild/SOURCES`. * Run `rpmbuild`. `rpmbuild` is in found in package `rpm-build`. For example to build just a binary only on CentOS 7: ``` $ sudo yum -y install rpm-build $ cp remake-3.82+dbg0.9.tar.bz2 ~/rpmbuild/SOURCES $ cp remake-centos6.spec remake.spec $ rpmbuild -bb remake-centos7.spec ``` remake-4.1+dbg1.3~dfsg.1/rpm/remake-centos6.spec000066400000000000000000000031401317072305000212660ustar00rootroot00000000000000# -*- coding: utf-8 -*- Summary: GNU Make with comprehensible tracing and a debugger Name: remake Epoch: 1 Version: 3.82+dbg0.7 Release: 19%{?dist} License: GPLv3 Group: Development/Tools URL: http://bashdb.sf.net/remake/ Source: ftp://ftp.gnu.org/gnu/make/remake-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: readline-devel Requires(preun): /sbin/install-info %description remake is a patched version of GNU Make that adds improved error reporting, the ability to trace execution in a comprehensible way, and a debugger. %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf ${RPM_BUILD_ROOT} make DESTDIR=$RPM_BUILD_ROOT install rm -f ${RPM_BUILD_ROOT}/%{_infodir}/dir %find_lang %name %check echo ============TESTING=============== /usr/bin/env LANG=C make check echo ============END TESTING=========== %clean rm -rf ${RPM_BUILD_ROOT} %post if [ -f %{_infodir}/remake.info.gz ]; then # for --excludedocs /sbin/install-info %{_infodir}/remake.info.gz %{_infodir}/dir --entry="* Make: (remake). The GNU remake utility." || : fi %preun if [ $1 = 0 ]; then if [ -f %{_infodir}/make.info.gz ]; then # for --excludedocs /sbin/install-info --delete %{_infodir}/make.info.gz %{_infodir}/dir --entry="* Make: (remake). The GNU remake utility." || : fi fi %files -f %{name}.lang %defattr(-,root,root) %doc NEWS README README.remake COPYING AUTHORS %{_bindir}/* %{_mandir}/man*/* %{_infodir}/*.info* %changelog * Fri Sep 23 2011 Rocky Bernstein - 1:3.81-19 - First cut via CentOS6 spec remake-4.1+dbg1.3~dfsg.1/rpm/remake-centos7.spec000066400000000000000000000032541317072305000212750ustar00rootroot00000000000000# -*- coding: utf-8 -*- Summary: GNU Make with comprehensible tracing and a debugger Name: remake Epoch: 1 Version: 3.82 Release: 19%{?dist} License: GPLv3 Group: Development/Tools URL: http://bashdb.sf.net/remake/ Source: ftp://ftp.gnu.org/gnu/make/remake-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: readline-devel Requires(preun): /sbin/install-info %description remake is a patched version of GNU Make that adds improved error reporting, the ability to trace execution in a comprehensible way, and a debugger. %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf ${RPM_BUILD_ROOT} make DESTDIR=$RPM_BUILD_ROOT install rm -f ${RPM_BUILD_ROOT}/%{_infodir}/dir %find_lang %name %check echo ============TESTING=============== /usr/bin/env LANG=C make check echo ============END TESTING=========== %clean rm -rf ${RPM_BUILD_ROOT} %post if [ -f %{_infodir}/remake.info.gz ]; then # for --excludedocs /sbin/install-info %{_infodir}/remake.info.gz %{_infodir}/dir --entry="* Make: (remake). The GNU remake utility." || : fi %preun if [ $1 = 0 ]; then if [ -f %{_infodir}/make.info.gz ]; then # for --excludedocs /sbin/install-info --delete %{_infodir}/make.info.gz %{_infodir}/dir --entry="* Make: (remake). The GNU remake utility." || : fi fi %files -f %{name}.lang %defattr(-,root,root) %doc NEWS README README.remake COPYING AUTHORS %{_bindir}/* %{_mandir}/man*/* %{_infodir}/*.info* %changelog * Fri Apr 23 2017 Rocky Bernstein - 1:3.81-19 - revise for CentOS7 * Fri Sep 23 2011 Rocky Bernstein - 1:3.81-19 - First cut via CentOS6 spec remake-4.1+dbg1.3~dfsg.1/rule.c000066400000000000000000000366751317072305000161270ustar00rootroot00000000000000/* Pattern and suffix rule internals for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include "filedef.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" static void freerule (struct rule *rule, struct rule *lastrule); /* Chain of all pattern rules. */ struct rule *pattern_rules; /* Pointer to last rule in the chain, so we can add onto the end. */ struct rule *last_pattern_rule; /* Number of rules in the chain. */ unsigned int num_pattern_rules; /* Maximum number of target patterns of any pattern rule. */ unsigned int max_pattern_targets; /* Maximum number of dependencies of any pattern rule. */ unsigned int max_pattern_deps; /* Maximum length of the name of a dependencies of any pattern rule. */ unsigned int max_pattern_dep_length; /* Pointer to structure for the file .SUFFIXES whose dependencies are the suffixes to be searched. */ struct file *suffix_file; /* Maximum length of a suffix. */ unsigned int maxsuffix; /* Compute the maximum dependency length and maximum number of dependencies of all implicit rules. Also sets the subdir flag for a rule when appropriate, possibly removing the rule completely when appropriate. */ void count_implicit_rule_limits (void) { char *name; int namelen; struct rule *rule; num_pattern_rules = max_pattern_targets = max_pattern_deps = 0; max_pattern_dep_length = 0; name = 0; namelen = 0; rule = pattern_rules; while (rule != 0) { unsigned int ndeps = 0; struct dep *dep; struct rule *next = rule->next; ++num_pattern_rules; if (rule->num > max_pattern_targets) max_pattern_targets = rule->num; for (dep = rule->deps; dep != 0; dep = dep->next) { const char *dname = dep_name (dep); unsigned int len = strlen (dname); #ifdef VMS const char *p = strrchr (dname, ']'); const char *p2; if (p == 0) p = strrchr (dname, ':'); p2 = p != 0 ? strchr (dname, '%') : 0; #else const char *p = strrchr (dname, '/'); const char *p2 = p != 0 ? strchr (dname, '%') : 0; #endif ndeps++; if (len > max_pattern_dep_length) max_pattern_dep_length = len; if (p != 0 && p2 > p) { /* There is a slash before the % in the dep name. Extract the directory name. */ if (p == dname) ++p; if (p - dname > namelen) { namelen = p - dname; name = xrealloc (name, namelen + 1); } memcpy (name, dname, p - dname); name[p - dname] = '\0'; /* In the deps of an implicit rule the 'changed' flag actually indicates that the dependency is in a nonexistent subdirectory. */ dep->changed = !dir_file_exists_p (name, ""); } else /* This dependency does not reside in a subdirectory. */ dep->changed = 0; } if (ndeps > max_pattern_deps) max_pattern_deps = ndeps; rule = next; } free (name); } /* Create a pattern rule from a suffix rule. TARGET is the target suffix; SOURCE is the source suffix. CMDS are the commands. If TARGET is nil, it means the target pattern should be '(%.o)'. If SOURCE is nil, it means there should be no deps. */ static void convert_suffix_rule (const char *target, const char *source, struct commands *cmds) { const char **names, **percents; struct dep *deps; names = xmalloc (sizeof (const char *)); percents = xmalloc (sizeof (const char *)); if (target == 0) { /* Special case: TARGET being nil means we are defining a '.X.a' suffix rule; the target pattern is always '(%.o)'. */ #ifdef VMS *names = strcache_add_len ("(%.obj)", 7); #else *names = strcache_add_len ("(%.o)", 5); #endif *percents = *names + 1; } else { /* Construct the target name. */ unsigned int len = strlen (target); char *p = alloca (1 + len + 1); p[0] = '%'; memcpy (p + 1, target, len + 1); *names = strcache_add_len (p, len + 1); *percents = *names; } if (source == 0) deps = 0; else { /* Construct the dependency name. */ unsigned int len = strlen (source); char *p = alloca (1 + len + 1); p[0] = '%'; memcpy (p + 1, source, len + 1); deps = alloc_dep (); deps->name = strcache_add_len (p, len + 1); } create_pattern_rule (names, percents, 1, 0, deps, cmds, 0); } /* Convert old-style suffix rules to pattern rules. All rules for the suffixes on the .SUFFIXES list are converted and added to the chain of pattern rules. */ void convert_to_pattern (void) { struct dep *d, *d2; char *rulename; /* We will compute every potential suffix rule (.x.y) from the list of suffixes in the .SUFFIXES target's dependencies and see if it exists. First find the longest of the suffixes. */ maxsuffix = 0; for (d = suffix_file->deps; d != 0; d = d->next) { unsigned int l = strlen (dep_name (d)); if (l > maxsuffix) maxsuffix = l; } /* Space to construct the suffix rule target name. */ rulename = alloca ((maxsuffix * 2) + 1); for (d = suffix_file->deps; d != 0; d = d->next) { unsigned int slen; /* Make a rule that is just the suffix, with no deps or commands. This rule exists solely to disqualify match-anything rules. */ convert_suffix_rule (dep_name (d), 0, 0); if (d->file->cmds != 0) /* Record a pattern for this suffix's null-suffix rule. */ convert_suffix_rule ("", dep_name (d), d->file->cmds); /* Add every other suffix to this one and see if it exists as a two-suffix rule. */ slen = strlen (dep_name (d)); memcpy (rulename, dep_name (d), slen); for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next) { struct file *f; unsigned int s2len; s2len = strlen (dep_name (d2)); /* Can't build something from itself. */ if (slen == s2len && streq (dep_name (d), dep_name (d2))) continue; memcpy (rulename + slen, dep_name (d2), s2len + 1); f = lookup_file (rulename); if (f == 0 || f->cmds == 0) continue; if (s2len == 2 && rulename[slen] == '.' && rulename[slen + 1] == 'a') /* A suffix rule '.X.a:' generates the pattern rule '(%.o): %.X'. It also generates a normal '%.a: %.X' rule below. */ convert_suffix_rule (NULL, /* Indicates '(%.o)'. */ dep_name (d), f->cmds); /* The suffix rule '.X.Y:' is converted to the pattern rule '%.Y: %.X'. */ convert_suffix_rule (dep_name (d2), dep_name (d), f->cmds); } } } /* Install the pattern rule RULE (whose fields have been filled in) at the end of the list (so that any rules previously defined will take precedence). If this rule duplicates a previous one (identical target and dependencies), the old one is replaced if OVERRIDE is nonzero, otherwise this new one is thrown out. When an old rule is replaced, the new one is put at the end of the list. Return nonzero if RULE is used; zero if not. */ static int new_pattern_rule (struct rule *rule, int override) { struct rule *r, *lastrule; unsigned int i, j; rule->in_use = 0; rule->terminal = 0; rule->next = 0; /* Search for an identical rule. */ lastrule = 0; for (r = pattern_rules; r != 0; lastrule = r, r = r->next) for (i = 0; i < rule->num; ++i) { for (j = 0; j < r->num; ++j) if (!streq (rule->targets[i], r->targets[j])) break; /* If all the targets matched... */ if (j == r->num) { struct dep *d, *d2; for (d = rule->deps, d2 = r->deps; d != 0 && d2 != 0; d = d->next, d2 = d2->next) if (!streq (dep_name (d), dep_name (d2))) break; if (d == 0 && d2 == 0) { /* All the dependencies matched. */ if (override) { /* Remove the old rule. */ freerule (r, lastrule); /* Install the new one. */ if (pattern_rules == 0) pattern_rules = rule; else last_pattern_rule->next = rule; last_pattern_rule = rule; /* We got one. Stop looking. */ goto matched; } else { /* The old rule stays intact. Destroy the new one. */ freerule (rule, (struct rule *) 0); return 0; } } } } matched:; if (r == 0) { /* There was no rule to replace. */ if (pattern_rules == 0) pattern_rules = rule; else last_pattern_rule->next = rule; last_pattern_rule = rule; } return 1; } /* Install an implicit pattern rule based on the three text strings in the structure P points to. These strings come from one of the arrays of default implicit pattern rules. TERMINAL specifies what the 'terminal' field of the rule should be. */ void install_pattern_rule (struct pspec *p, int terminal) { struct rule *r; const char *ptr; r = xmalloc (sizeof (struct rule)); r->num = 1; r->targets = xmalloc (sizeof (const char *)); r->suffixes = xmalloc (sizeof (const char *)); r->lens = xmalloc (sizeof (unsigned int)); r->lens[0] = strlen (p->target); r->targets[0] = p->target; r->suffixes[0] = find_percent_cached (&r->targets[0]); r->floc.filenm = NULL; r->floc.lineno = 0; assert (r->suffixes[0] != NULL); ++r->suffixes[0]; ptr = p->dep; r->deps = PARSE_SIMPLE_SEQ ((char **)&ptr, struct dep); if (new_pattern_rule (r, 0)) { r->terminal = terminal; r->cmds = xmalloc (sizeof (struct commands)); r->cmds->fileinfo.filenm = 0; r->cmds->fileinfo.lineno = 0; /* These will all be string literals, but we malloc space for them anyway because somebody might want to free them later. */ r->cmds->commands = xstrdup (p->commands); r->cmds->command_lines = 0; r->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT; } } /* Free all the storage used in RULE and take it out of the pattern_rules chain. LASTRULE is the rule whose next pointer points to RULE. */ static void freerule (struct rule *rule, struct rule *lastrule) { struct rule *next = rule->next; free_dep_chain (rule->deps); /* MSVC erroneously warns without a cast here. */ free ((void *)rule->targets); free ((void *)rule->suffixes); free (rule->lens); /* We can't free the storage for the commands because there are ways that they could be in more than one place: * If the commands came from a suffix rule, they could also be in the 'struct file's for other suffix rules or plain targets given on the same makefile line. * If two suffixes that together make a two-suffix rule were each given twice in the .SUFFIXES list, and in the proper order, two identical pattern rules would be created and the second one would be discarded here, but both would contain the same 'struct commands' pointer from the 'struct file' for the suffix rule. */ free (rule); if (pattern_rules == rule) if (lastrule != 0) abort (); else pattern_rules = next; else if (lastrule != 0) lastrule->next = next; if (last_pattern_rule == rule) last_pattern_rule = lastrule; } /* Create a new pattern rule with the targets in the nil-terminated array TARGETS. TARGET_PERCENTS is an array of pointers to the % in each element of TARGETS. N is the number of items in the array (not counting the nil element). The new rule has dependencies DEPS and commands from COMMANDS. It is a terminal rule if TERMINAL is nonzero. This rule overrides identical rules with different commands if OVERRIDE is nonzero. The storage for TARGETS and its elements and TARGET_PERCENTS is used and must not be freed until the rule is destroyed. */ void create_pattern_rule (const char **targets, const char **target_percents, unsigned int n, int terminal, struct dep *deps, struct commands *commands, int override) { unsigned int i; struct rule *r = xmalloc (sizeof (struct rule)); r->num = n; r->cmds = commands; r->deps = deps; r->targets = targets; r->suffixes = target_percents; r->lens = xmalloc (n * sizeof (unsigned int)); r->tracing = BRK_NONE; if (commands) { r->floc.filenm = commands->fileinfo.filenm; r->floc.lineno = commands->fileinfo.lineno - 1; } else { r->floc.filenm = NULL; r->floc.lineno = 0; } for (i = 0; i < n; ++i) { r->lens[i] = strlen (targets[i]); assert (r->suffixes[i] != NULL); ++r->suffixes[i]; } if (new_pattern_rule (r, override)) r->terminal = terminal; } /*! Show information about a given rule. Useful from the debugger or gdb. */ void print_rule (rule_t *r, bool b_verbose) { unsigned int i; for (i = 0; i < r->num; ++i) { fputs (r->targets[i], stdout); putchar ((i + 1 == r->num) ? ':' : ' '); } if (r->terminal) putchar (':'); print_prereqs (r->deps); putchar ('\n'); if (!b_verbose) return; if (r->cmds != 0) print_commands (NULL, r->cmds, false); } /* Print the data base of rules. */ void print_rule_data_base (bool b_verbose) { unsigned int rules, terminal; struct rule *r; puts (_("\n# Implicit Rules")); rules = terminal = 0; for (r = pattern_rules; r != 0; r = r->next) { ++rules; print_rule (r, b_verbose); if (r->terminal) ++terminal; } if (!b_verbose) { printf("\n"); return; } if (rules == 0) puts (_("\n# No implicit rules.")); else { printf (_("\n# %u implicit rules, %u"), rules, terminal); #ifndef NO_FLOAT printf (" (%.1f%%)", (double) terminal / (double) rules * 100.0); #else { int f = (terminal * 1000 + 5) / rules; printf (" (%d.%d%%)", f/10, f%10); } #endif puts (_(" terminal.")); } if (num_pattern_rules != rules) { /* This can happen if a fatal error was detected while reading the makefiles and thus count_implicit_rule_limits wasn't called yet. */ if (num_pattern_rules != 0) ONN (fatal, NILF, _("BUG: num_pattern_rules is wrong! %u != %u"), num_pattern_rules, rules); } } remake-4.1+dbg1.3~dfsg.1/rule.h000066400000000000000000000047711317072305000161240ustar00rootroot00000000000000/* Definitions for using pattern rules in GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* Structure used for pattern (implicit) rules. */ #ifndef _REMAKE_RULE_H #define _REMAKE_RULE_H #include "gnumake.h" #include "types.h" struct rule { struct rule *next; const char **targets; /* Targets of the rule. */ unsigned int *lens; /* Lengths of each target. */ const char **suffixes; /* Suffixes (after '%') of each target. */ struct dep *deps; /* Dependencies of the rule. */ struct commands *cmds; /* Commands to execute. */ unsigned short num; /* Number of targets. */ char terminal; /* If terminal (double-colon). */ char in_use; /* If in use by a parent pattern_search. */ gmk_floc floc; /* Location of rule */ breakpoint_mask_t tracing; /* breakpoint status of target. */ }; /* For calling install_pattern_rule. */ struct pspec { const char *target, *dep, *commands; }; extern struct rule *pattern_rules; extern struct rule *last_pattern_rule; extern unsigned int num_pattern_rules; extern unsigned int max_pattern_deps; extern unsigned int max_pattern_targets; extern unsigned int max_pattern_dep_length; extern struct file *suffix_file; extern unsigned int maxsuffix; void count_implicit_rule_limits (void); void convert_to_pattern (void); void install_pattern_rule (struct pspec *p, int terminal); void create_pattern_rule (const char **targets, const char **target_percents, unsigned int num, int terminal, struct dep *deps, struct commands *commands, int override); /*! Show information about a given rule. Useful from the debugger or gdb. */ extern void print_rule (rule_t *r, bool b_verbose); extern void print_rule_data_base (bool b_verbose); #endif /*REMAKE_RULE_H*/ remake-4.1+dbg1.3~dfsg.1/signame.c000066400000000000000000000153171317072305000165710ustar00rootroot00000000000000/* Convert between signal names and numbers. Copyright (C) 1990-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" /* If the system provides strsignal, we don't need it. */ #if !HAVE_STRSIGNAL /* If the system provides sys_siglist, we'll use that. Otherwise create our own. */ #if !HAVE_DECL_SYS_SIGLIST /* Some systems do not define NSIG in . */ #ifndef NSIG #ifdef _NSIG #define NSIG _NSIG #else #define NSIG 32 #endif #endif /* There is too much variation in Sys V signal numbers and names, so we must initialize them at runtime. */ static const char *undoc; static const char *sys_siglist[NSIG]; /* Table of abbreviations for signals. Note: A given number can appear more than once with different abbreviations. */ #define SIG_TABLE_SIZE (NSIG*2) typedef struct { int number; const char *abbrev; } num_abbrev; static num_abbrev sig_table[SIG_TABLE_SIZE]; /* Number of elements of sig_table used. */ static int sig_table_nelts = 0; /* Enter signal number NUMBER into the tables with ABBREV and NAME. */ static void init_sig (int number, const char *abbrev, const char *name) { /* If this value is ever greater than NSIG it seems like it'd be a bug in the system headers, but... better safe than sorry. We know, for example, that this isn't always true on VMS. */ if (number >= 0 && number < NSIG) sys_siglist[number] = name; if (sig_table_nelts < SIG_TABLE_SIZE) { sig_table[sig_table_nelts].number = number; sig_table[sig_table_nelts++].abbrev = abbrev; } } static int signame_init (void) { int i; undoc = xstrdup (_("unknown signal")); /* Initialize signal names. */ for (i = 0; i < NSIG; i++) sys_siglist[i] = undoc; /* Initialize signal names. */ #if defined (SIGHUP) init_sig (SIGHUP, "HUP", _("Hangup")); #endif #if defined (SIGINT) init_sig (SIGINT, "INT", _("Interrupt")); #endif #if defined (SIGQUIT) init_sig (SIGQUIT, "QUIT", _("Quit")); #endif #if defined (SIGILL) init_sig (SIGILL, "ILL", _("Illegal Instruction")); #endif #if defined (SIGTRAP) init_sig (SIGTRAP, "TRAP", _("Trace/breakpoint trap")); #endif /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */ #if defined (SIGABRT) init_sig (SIGABRT, "ABRT", _("Aborted")); #endif #if defined (SIGIOT) init_sig (SIGIOT, "IOT", _("IOT trap")); #endif #if defined (SIGEMT) init_sig (SIGEMT, "EMT", _("EMT trap")); #endif #if defined (SIGFPE) init_sig (SIGFPE, "FPE", _("Floating point exception")); #endif #if defined (SIGKILL) init_sig (SIGKILL, "KILL", _("Killed")); #endif #if defined (SIGBUS) init_sig (SIGBUS, "BUS", _("Bus error")); #endif #if defined (SIGSEGV) init_sig (SIGSEGV, "SEGV", _("Segmentation fault")); #endif #if defined (SIGSYS) init_sig (SIGSYS, "SYS", _("Bad system call")); #endif #if defined (SIGPIPE) init_sig (SIGPIPE, "PIPE", _("Broken pipe")); #endif #if defined (SIGALRM) init_sig (SIGALRM, "ALRM", _("Alarm clock")); #endif #if defined (SIGTERM) init_sig (SIGTERM, "TERM", _("Terminated")); #endif #if defined (SIGUSR1) init_sig (SIGUSR1, "USR1", _("User defined signal 1")); #endif #if defined (SIGUSR2) init_sig (SIGUSR2, "USR2", _("User defined signal 2")); #endif /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that is what is in POSIX.1. */ #if defined (SIGCHLD) init_sig (SIGCHLD, "CHLD", _("Child exited")); #endif #if defined (SIGCLD) init_sig (SIGCLD, "CLD", _("Child exited")); #endif #if defined (SIGPWR) init_sig (SIGPWR, "PWR", _("Power failure")); #endif #if defined (SIGTSTP) init_sig (SIGTSTP, "TSTP", _("Stopped")); #endif #if defined (SIGTTIN) init_sig (SIGTTIN, "TTIN", _("Stopped (tty input)")); #endif #if defined (SIGTTOU) init_sig (SIGTTOU, "TTOU", _("Stopped (tty output)")); #endif #if defined (SIGSTOP) init_sig (SIGSTOP, "STOP", _("Stopped (signal)")); #endif #if defined (SIGXCPU) init_sig (SIGXCPU, "XCPU", _("CPU time limit exceeded")); #endif #if defined (SIGXFSZ) init_sig (SIGXFSZ, "XFSZ", _("File size limit exceeded")); #endif #if defined (SIGVTALRM) init_sig (SIGVTALRM, "VTALRM", _("Virtual timer expired")); #endif #if defined (SIGPROF) init_sig (SIGPROF, "PROF", _("Profiling timer expired")); #endif #if defined (SIGWINCH) /* "Window size changed" might be more accurate, but even if that is all that it means now, perhaps in the future it will be extended to cover other kinds of window changes. */ init_sig (SIGWINCH, "WINCH", _("Window changed")); #endif #if defined (SIGCONT) init_sig (SIGCONT, "CONT", _("Continued")); #endif #if defined (SIGURG) init_sig (SIGURG, "URG", _("Urgent I/O condition")); #endif #if defined (SIGIO) /* "I/O pending" has also been suggested. A disadvantage is that signal only happens when the process has asked for it, not every time I/O is pending. Another disadvantage is the confusion from giving it a different name than under Unix. */ init_sig (SIGIO, "IO", _("I/O possible")); #endif #if defined (SIGWIND) init_sig (SIGWIND, "WIND", _("SIGWIND")); #endif #if defined (SIGPHONE) init_sig (SIGPHONE, "PHONE", _("SIGPHONE")); #endif #if defined (SIGPOLL) init_sig (SIGPOLL, "POLL", _("I/O possible")); #endif #if defined (SIGLOST) init_sig (SIGLOST, "LOST", _("Resource lost")); #endif #if defined (SIGDANGER) init_sig (SIGDANGER, "DANGER", _("Danger signal")); #endif #if defined (SIGINFO) init_sig (SIGINFO, "INFO", _("Information request")); #endif #if defined (SIGNOFP) init_sig (SIGNOFP, "NOFP", _("Floating point co-processor not available")); #endif return 1; } #endif /* HAVE_DECL_SYS_SIGLIST */ char * strsignal (int sig) { static char buf[] = "Signal 12345678901234567890"; #if ! HAVE_DECL_SYS_SIGLIST # if HAVE_DECL__SYS_SIGLIST # define sys_siglist _sys_siglist # elif HAVE_DECL___SYS_SIGLIST # define sys_siglist __sys_siglist # else static char sig_initted = 0; if (!sig_initted) sig_initted = signame_init (); # endif #endif if (sig > 0 && sig < NSIG) return (char *) sys_siglist[sig]; sprintf (buf, "Signal %d", sig); return buf; } #endif /* HAVE_STRSIGNAL */ remake-4.1+dbg1.3~dfsg.1/strcache.c000066400000000000000000000201441317072305000167340ustar00rootroot00000000000000/* Constant string caching for GNU Make. Copyright (C) 2006-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include #include "hash.h" /* A string cached here will never be freed, so we don't need to worry about reference counting. We just store the string, and then remember it in a hash so it can be looked up again. */ typedef unsigned short int sc_buflen_t; struct strcache { struct strcache *next; /* The next block of strings. Must be first! */ sc_buflen_t end; /* Offset to the beginning of free space. */ sc_buflen_t bytesfree; /* Free space left in this buffer. */ sc_buflen_t count; /* # of strings in this buffer (for stats). */ char buffer[1]; /* The buffer comes after this. */ }; /* The size (in bytes) of each cache buffer. Try to pick something that will map well into the heap. This must be able to be represented by a short int (<=65535). */ #define CACHE_BUFFER_BASE (8192) #define CACHE_BUFFER_ALLOC(_s) ((_s) - (2 * sizeof (size_t))) #define CACHE_BUFFER_OFFSET (offsetof (struct strcache, buffer)) #define CACHE_BUFFER_SIZE(_s) (CACHE_BUFFER_ALLOC(_s) - CACHE_BUFFER_OFFSET) static sc_buflen_t bufsize = CACHE_BUFFER_SIZE (CACHE_BUFFER_BASE); static struct strcache *strcache = NULL; static struct strcache *fullcache = NULL; static unsigned long total_buffers = 0; static unsigned long total_strings = 0; static unsigned long total_size = 0; /* Add a new buffer to the cache. Add it at the front to reduce search time. This can also increase the overhead, since it's less likely that older buffers will be filled in. However, GNU make has so many smaller strings that this doesn't seem to be much of an issue in practice. */ static struct strcache * new_cache () { struct strcache *new; new = xmalloc (bufsize + CACHE_BUFFER_OFFSET); new->end = 0; new->count = 0; new->bytesfree = bufsize; new->next = strcache; strcache = new; ++total_buffers; return new; } static const char * add_string (const char *str, unsigned int len) { char *res; struct strcache *sp; struct strcache **spp = &strcache; /* We need space for the nul char. */ unsigned int sz = len + 1; /* If the string we want is too large to fit into a single buffer, then no existing cache is large enough. Change the maximum size. */ if (sz > bufsize) bufsize = CACHE_BUFFER_SIZE ((((sz + 1) / CACHE_BUFFER_BASE) + 1) * CACHE_BUFFER_BASE); else /* Find the first cache with enough free space. */ for (; *spp != NULL; spp = &(*spp)->next) if ((*spp)->bytesfree > sz) break; /* If nothing is big enough, make a new cache. */ sp = *spp; if (sp == NULL) { sp = new_cache (); spp = &sp; } /* Add the string to this cache. */ res = &sp->buffer[sp->end]; memmove (res, str, len); res[len] = '\0'; sp->end += sz; sp->bytesfree -= sz; ++sp->count; /* If the amount free in this cache is less than the average string size, consider it full and move it to the full list. */ ++total_strings; total_size += sz; if (sp->bytesfree < (total_size / total_strings) + 1) { *spp = (*spp)->next; sp->next = fullcache; fullcache = sp; } return res; } /* Hash table of strings in the cache. */ static unsigned long str_hash_1 (const void *key) { return_ISTRING_HASH_1 ((const char *) key); } static unsigned long str_hash_2 (const void *key) { return_ISTRING_HASH_2 ((const char *) key); } static int str_hash_cmp (const void *x, const void *y) { return_ISTRING_COMPARE ((const char *) x, (const char *) y); } static struct hash_table strings; static unsigned long total_adds = 0; static const char * add_hash (const char *str, int len) { /* Look up the string in the hash. If it's there, return it. */ char *const *slot = (char *const *) hash_find_slot (&strings, str); const char *key = *slot; /* Count the total number of add operations we performed. */ ++total_adds; if (!HASH_VACANT (key)) return key; /* Not there yet so add it to a buffer, then into the hash table. */ key = add_string (str, len); hash_insert_at (&strings, key, slot); return key; } /* Returns true if the string is in the cache; false if not. */ int strcache_iscached (const char *str) { struct strcache *sp; for (sp = strcache; sp != 0; sp = sp->next) if (str >= sp->buffer && str < sp->buffer + sp->end) return 1; for (sp = fullcache; sp != 0; sp = sp->next) if (str >= sp->buffer && str < sp->buffer + sp->end) return 1; return 0; } /* If the string is already in the cache, return a pointer to the cached version. If not, add it then return a pointer to the cached version. Note we do NOT take control of the string passed in. */ const char * strcache_add (const char *str) { return add_hash (str, strlen (str)); } const char * strcache_add_len (const char *str, unsigned int len) { /* If we're not given a nul-terminated string we have to create one, because the hashing functions expect it. */ if (str[len] != '\0') { char *key = alloca (len + 1); memcpy (key, str, len); key[len] = '\0'; str = key; } return add_hash (str, len); } int strcache_setbufsize (unsigned int size) { if (size > bufsize) bufsize = size; return bufsize; } void strcache_init (void) { hash_init (&strings, 8000, str_hash_1, str_hash_2, str_hash_cmp); } /* Generate some stats output. */ void strcache_print_stats (const char *prefix) { const struct strcache *sp; unsigned long numbuffs = 0, fullbuffs = 0; unsigned long totfree = 0, maxfree = 0, minfree = bufsize; if (! strcache) { printf (_("\n%s No strcache buffers\n"), prefix); return; } /* Count the first buffer separately since it's not full. */ for (sp = strcache->next; sp != NULL; sp = sp->next) { sc_buflen_t bf = sp->bytesfree; totfree += bf; maxfree = (bf > maxfree ? bf : maxfree); minfree = (bf < minfree ? bf : minfree); ++numbuffs; } for (sp = fullcache; sp != NULL; sp = sp->next) { sc_buflen_t bf = sp->bytesfree; totfree += bf; maxfree = (bf > maxfree ? bf : maxfree); minfree = (bf < minfree ? bf : minfree); ++numbuffs; ++fullbuffs; } /* Make sure we didn't lose any buffers. */ assert (total_buffers == numbuffs + 1); printf (_("\n%s strcache buffers: %lu (%lu) / strings = %lu / storage = %lu B / avg = %lu B\n"), prefix, numbuffs + 1, fullbuffs, total_strings, total_size, (total_size / total_strings)); printf (_("%s current buf: size = %hu B / used = %hu B / count = %hu / avg = %hu B\n"), prefix, bufsize, strcache->end, strcache->count, (strcache->end / strcache->count)); if (numbuffs) { unsigned long sz = total_size - bufsize; unsigned long cnt = total_strings - strcache->count; sc_buflen_t avgfree = totfree / numbuffs; printf (_("%s other used: total = %lu B / count = %lu / avg = %lu B\n"), prefix, sz, cnt, sz / cnt); printf (_("%s other free: total = %lu B / max = %lu B / min = %lu B / avg = %hu B\n"), prefix, totfree, maxfree, minfree, avgfree); } printf (_("\n%s strcache performance: lookups = %lu / hit rate = %lu%%\n"), prefix, total_adds, (long unsigned)(100.0 * (total_adds - total_strings) / total_adds)); fputs (_("# hash-table stats:\n# "), stdout); hash_print_stats (&strings, stdout); } remake-4.1+dbg1.3~dfsg.1/subproc.bat000066400000000000000000000015631317072305000171450ustar00rootroot00000000000000@echo off rem Copyright (C) 1996-2014 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . cd w32\subproc set MAKE=%2 set MAKEFILE=%1 if x%2 == x set MAKE=nmake %MAKE% /f %MAKEFILE% cd ..\.. remake-4.1+dbg1.3~dfsg.1/tests/000077500000000000000000000000001317072305000161355ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/.cvsignore000066400000000000000000000000051317072305000201300ustar00rootroot00000000000000work remake-4.1+dbg1.3~dfsg.1/tests/.gitignore000066400000000000000000000000561317072305000201260ustar00rootroot00000000000000/*~ /config-flags.pm /test-file /test.* /work remake-4.1+dbg1.3~dfsg.1/tests/COPYING000066400000000000000000001045131317072305000171740ustar00rootroot00000000000000 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 . remake-4.1+dbg1.3~dfsg.1/tests/ChangeLog000066400000000000000000001102261317072305000177110ustar00rootroot000000000000002010-07-28 Paul Smith * scripts/targets/POSIX: Compatibility issues with Solaris (and Tru64?); "false" returns different exit codes, and set -x shows output with extra whitespace. Run the commands by hand first to find out what the real shell would do, then compare what make does. * scripts/variables/SHELL: Ditto. 2010-07-12 Paul Smith * test_driver.pl: Add a new $perl_name containing the path to Perl. * run_make_tests.pl (run_make_test): Replace the special string #PERL# in a makefile etc. with the path the Perl executable so makefiles can use it. * scripts/targets/ONESHELL: Add a new set of regression tests for the .ONESHELL feature. 2010-07-06 Paul Smith * scripts/variables/SHELL: Test the new .SHELLFLAGS variable. * scripts/targets/POSIX: New file. Test the .POSIX special target. Verify that enabling .POSIX changes the shell flags to set -e. 2010-07-01 Paul Smith * scripts/features/recursion: Add a space to separate command-line args. Fixes Savannah bug #29968. 2009-11-12 Boris Kolpackov * scripts/features/vpath3: Test for the new library search behavior. 2009-10-06 Boris Kolpackov * scripts/features/se_explicit: Enable the test for now fixed Savannah bug 25780. 2009-10-06 Boris Kolpackov * scripts/variables/undefine: Tests for the new undefine feature. 2009-10-03 Paul Smith * scripts/features/parallelism: Test for open Savannah bug #26846. * scripts/variables/MAKE: Rewrite for new run_make_test() format. * scripts/variables/MAKEFLAGS: Created. Add test for Savannah bug #2216 (still open). * scripts/features/include: Test for Savannah bug #102 (still open). 2009-09-30 Boris Kolpackov * scripts/features/include: Add diagnostics issuing tests for cases where targets have been updated and failed with the dontcare flag. Savannah bugs #15110, #25493, #12686, #17740. 2009-09-28 Paul Smith * scripts/functions/shell: Add regression test for Savannah bug #20513 (still open). * scripts/features/se_explicit: Add regression tests for Savannah bug #25780 (still open). * run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)? that runs tests we know will fail. This allows us to add regression tests to the test suite for bugs that haven't been fixed yet. 2009-09-28 Boris Kolpackov * scripts/features/patspecific_vars: Add a test for the shortest stem first order. * scripts/features/patternrules: Add a test for the shortest stem first order. 2009-09-24 Paul Smith * scripts/features/se_implicit: Add a test for order-only secondary expansion prerequisites. 2009-09-23 Paul Smith * scripts/features/patternrules: Test that we can remove pattern rules, both single and multiple prerequisites. Savannah bug #18622. * scripts/features/echoing: Rework for run_make_test(). 2009-06-14 Paul Smith * scripts/features/vpath: Verify we don't get bogus circular dependency warnings if we choose a different file via vpath during update. Savannah bug #13529. 2009-06-13 Paul Smith * scripts/variables/MAKEFILES: Verify that MAKEFILES included files (and files included by them) don't set the default goal. Savannah bug #13401. * scripts/functions/wildcard: Test that wildcards with non-existent glob matchers return empty. 2009-06-09 Paul Smith * scripts/options/dash-B: Test the $? works correctly with -B. Savannah bug #17825. * scripts/features/patternrules: Test that dependencies of "also_make" targets are created properly. Savannah bug #19108. * test_driver.pl (compare_output): Create a "run" file for failed tests containing the command that was run. (get_runfile): New function. * run_make_tests.pl (valid_option): Enhanced support for valgrind: allow memcheck and massif tools. * scripts/features/patternrules: Have to comment out a line in the first test due to backing out a change that broke the implicit rule search algorithm. Savannah bug #17752. * scripts/misc/general4: Remove a test that is redundant with patternrules. * scripts/features/parallelism: Add a test for re-exec with jobserver master override. Savannah bug #18124. 2009-06-08 Paul Smith * scripts/features/targetvars: Add a test for continued target vars after a semicolon. Savannah bug #17521. 2009-06-07 Paul Smith * scripts/features/se_explicit: Make sure we catch defining prereqs during snap_deps(). Savannah bug #24622. * scripts/variables/automatic: Check prereq ordering when the target with the recipe has no prereqs. Savannah bug #21198. * scripts/variables/LIBPATTERNS: Add a new set of test for $(.LIBPATTERNS) (previously untested!) 2009-06-04 Paul Smith * scripts/variables/SHELL: The export target-specific SHELL test has an incorrect known-good-value. * scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.) * scripts/features/se_explicit: Add tests for Savannah bug #24588. 2009-05-31 Paul Smith * scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697. * scripts/features/targetvars: Add tests of overrides for Savannah bug #26207. * scripts/features/patspecific_vars: Ditto. * scripts/features/patternrules: Add a test for Savannah bug #26593. 2009-05-30 Paul Smith * scripts/variables/flavors: Update with new variable flavor tests. * scripts/variables/define: Create a new set of tests for define/endef and move those aspects of the flavors suite here. 2009-05-25 Paul Smith * scripts/features/targetvars: Ditto. * scripts/features/export: Test new variable parsing abilities. 2009-02-23 Ramon Garcia * scripts/variables/private: Create a new suite of tests for 'private'. 2007-11-04 Paul Smith * scripts/functions/eval: Update error message for command -> recipe. * test_driver.pl (compare_output): Allow the answer to be a regex, if surrounded by '/'. * scripts/misc/close_stdout: Use a regex for the answer, since sometimes the error will have a description and sometimes it won't. 2007-09-10 Paul Smith * scripts/variables/special: Add tests for .RECIPEPREFIX variable. 2007-08-15 Paul Smith These test cases were contributed by Icarus Sparry and J. David Bryan for Savannah bugs #3330 and #15919. * scripts/targets/SECONDARY: Add tests for Savannah bugs 3330 and 15919. * scripts/features/parallelism: Add tests for wrong answer/hang combining INTERMEDIATE, order-only prereqs, and parallelism. See Savannah bugs 3330 and 15919. 2007-07-13 Paul Smith Install a timeout so tests can never loop infinitely. Original idea and patch for a single-test version provided by Icarus Sparry * test_driver.pl (_run_command): New function: this is called by other functions to actually run a command. Before we run it, install a SIGALRM handler and set up a timer to go off in the future (default is 5s; this can be overridden by individual tests). (run_command): Call it. (run_command_with_output): Call it. * run_make_tests.pl (run_make_with_options): Override the default timeout if the caller requests it. (run_make_test): Pass any timeout override to run_make_with_options. * scripts/features/parallelism: Increase the timeout for long tests. * scripts/options/dash-l: Ditto. 2006-10-01 Paul Smith * run_make_tests.pl (set_more_defaults): Remove setting of LANG in ENV here. This doesn't always work. * test_driver.pl (toplevel): Set LC_ALL to 'C' in the make environment. Fixes Savannah bug #16698. 2006-09-30 Paul Smith * scripts/variables/automatic: Add back the test for bug #8154. 2006-04-01 Paul D. Smith * scripts/functions/realpath: Don't run tests with multiple initial slashes on Windows: those paths mean something different. 2006-03-19 Paul D. Smith * scripts/features/parallelism: Test that the jobserver is properly managed when we have to re-exec the master instance of make. 2006-03-17 Boris Kolpackov * scripts/features/statipattrules: Add tests for bug #16053. 2006-03-09 Paul Smith * scripts/features/escape: Use "pre:" not "p:" to avoid conflicts with DOS drive letters. Fixes Savannah bug #15947. * test_driver.pl (run_each_test): Set the status properly even when a test fails to execute. Fixes Savannah bug #15942. * scripts/functions/foreach: Use a different environment variable other than PATH to avoid differences with Windows platforms. Fixes Savannah bug #15938. 2006-03-05 Paul D. Smith * run_make_tests.pl (set_more_defaults): Add CYGWIN_NT as a port type W32. Fixed Savannah bug #15937. * scripts/features/default_names: Don't call error() when the test fails. Fixes Savannah bug #15941. 2006-02-17 Paul D. Smith * scripts/features/targetvars: Test a complex construction which guarantees that we have to merge variable lists of different sizes. Tests for Savannah bug #15757. 2006-02-15 Paul D. Smith * scripts/functions/error: Make sure filename/lineno information is related to where the error is expanded, not where it's set. * scripts/functions/warning: Ditto. * scripts/functions/foreach: Check for different error conditions. * scripts/functions/word: Ditto. * scripts/variables/negative: Test some variable reference failure conditions. * scripts/options/warn-undefined-variables: Test the --warn-undefined-variables flag. 2006-02-09 Paul D. Smith * run_make_tests.pl (set_more_defaults): Update valgrind support for newer versions. * test_driver.pl (toplevel): Skip all hidden files/directories (ones beginning with "."). * scripts/functions/andor: Tests for $(and ..) and $(or ...) functions. 2006-02-08 Boris Kolpackov * scripts/features/parallelism: Add a test for bug #15641. 2006-02-06 Paul D. Smith * scripts/options/dash-W: Add a test for bug #15341. 2006-01-03 Paul D. Smith * scripts/variables/automatic: Add a test for bug #8154. * README: Update to reflect the current state of the test suite. 2005-12-12 Paul D. Smith * scripts/features/parallelism, scripts/functions/wildcard, scripts/targets/FORCE, scripts/targets/PHONY, scripts/targets/SILENT: Use the default setting for $delete_command. Fixes bug #15085. * run_make_tests.pl (get_this_pwd) [VMS]: Use -no_ask with delete_file. 2005-12-11 Paul D. Smith * scripts/misc/general4: Test implicit rules with '$' in the prereq list & prereq patterns. * scripts/features/se_implicit: Add in .SECONDEXPANSION settings. 2005-12-09 Boris Kolpackov * scripts/features/patternrules: Add a test for bug #13022. 2005-12-07 Boris Kolpackov * scripts/features/double_colon: Add a test for bug #14334. 2005-11-17 Boris Kolpackov * scripts/functions/flavor: Add a test for the flavor function. 2005-11-14 Boris Kolpackov * scripts/variables/INCLUDE_DIRS: Add a test for the .INCLUDE_DIRS special variable. 2005-10-24 Paul D. Smith * scripts/misc/general4: Test '$$' in prerequisites list. * scripts/features/statipattrules: Rewrite to use run_make_test(). Add various static pattern info. * scripts/features/se_statpat: Enable .SECONDEXPANSION target. * scripts/features/se_explicit: Add tests for handling '$$' in prerequisite lists with and without setting .SECONDEXPANSION. * scripts/features/order_only: Convert to run_make_test(). * run_make_tests.pl (set_more_defaults): If we can't get the value of $(MAKE) from make, then fatal immediately. 2005-08-31 Paul D. Smith * run_make_tests.pl (get_this_pwd): Require the POSIX module (in an eval to trap errors) and if it exists, use POSIX::getcwd to find the working directory. If it doesn't exist, go back to the previous methods. This tries to be more accurate on Windows systems. 2005-08-29 Paul D. Smith * scripts/functions/abspath: Add some text to the error messages to get a better idea of what's wrong. Make warnings instead of errors. * scripts/features/patspecific_vars: Don't use "test", which is UNIX specific. Print the values and let the test script match them. 2005-08-25 Paul Smith * scripts/variables/SHELL: Use a /./ prefix instead of //: the former works better with non-UNIX environments. Fixes Savannah bug #14129. 2005-08-13 Boris Kolpackov * scripts/functions/wildcard: Wrap calls to $(wildcard ) with $(sort) so that the resulting order is no longer filesystem- dependant. 2005-08-10 Boris Kolpackov * scripts/features/statipattrules: Add a test for Savannah bug #13881. 2005-08-07 Paul D. Smith * scripts/features/parallelism: Add a test for a bug reported by Michael Matz (matz@suse.de) in which make exits without waiting for all its children in some situations during parallel builds. 2005-07-08 Paul D. Smith * test_driver.pl: Reset the environment to a clean value every time before we invoke make. I'm suspicious that the environment isn't handled the same way in Windows as it is in UNIX, and some variables are leaking out beyond the tests they are intended for. Create an %extraENV hash tests can set to add more env. vars. * tests/scripts/features/export: Change to use %extraENV. * tests/scripts/functions/eval: Ditto. * tests/scripts/functions/origin: Ditto. * tests/scripts/options/dash-e: Ditto. * tests/scripts/variables/SHELL: Ditto. 2005-06-27 Paul D. Smith * scripts/options/dash-W: Use 'echo >>' instead of touch to update files. * scripts/features/reinvoke: Rewrite to be safer on systems with subsecond timestamps. * scripts/features/patternrules: False exits with different error codes on different systems (for example, Linux => 1, Solaris => 255). * scripts/options/dash-W: Set the timestamp to foo.x in the future, to be sure it will be considered updated when it's remade. 2005-06-26 Paul D. Smith * scripts/functions/shell: New test suite for the shell function. 2005-06-25 Paul D. Smith * scripts/features/include: Test include/-include/sinclude with no arguments. Tests fix for Savannah bug #1761. * scripts/misc/general3: Implement comprehensive testing of backslash-newline behavior in command scripts: various types of quoting, fast path / slow path, etc. Tests fix for Savannah bug #1332. * scripts/options/symlinks: Test symlinks to non-existent files. Tests fix for Savannah bug #13280. * scripts/misc/general3: Test semicolons in variable references. Tests fix for Savannah bug #1454. * scripts/variables/MAKE_RESTARTS: New file: test the MAKE_RESTARTS variable. * scripts/options/dash-B: Test re-exec doesn't loop infinitely. Tests fix for Savannah bug #7566. * scripts/options/dash-W: New file: test the -W flag, including re-exec infinite looping. 2005-06-12 Paul D. Smith * scripts/misc/close_stdout: Add a test for Savannah bug #1328. This test only works on systems that have /dev/full (e.g., Linux). 2005-06-09 Paul D. Smith * scripts/functions/foreach: Add a test for Savannah bug #11913. 2005-05-31 Boris Kolpackov * scripts/features/include: Add a test for Savannah bug #13216. * scripts/features/patternrules: Add a test for Savannah bug #13218. 2005-05-13 Paul D. Smith * scripts/features/conditionals: Add tests for the new if... else if... endif syntax. 2005-05-03 Paul D. Smith * scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to DEFAULT_GOAL. 2005-05-02 Paul D. Smith * scripts/features/parallelism: Add a test for exporting recursive variables containing $(shell ) calls. Rewrite this script to use run_make_test() everywhere. 2005-04-07 Paul D. Smith * scripts/targets/SECONDARY: Add a test for Savannah bug #12331. 2005-03-15 Boris Kolpackov * scripts/variables/automatic: Add a test for Savannah bug #12320. 2005-03-10 Boris Kolpackov * scripts/features/patternrules: Add a test for Savannah bug #12267. 2005-03-09 Boris Kolpackov * scripts/variables/DEFAULT_TARGET: Add a test for Savannah bug #12266. 2005-03-04 Boris Kolpackov * scripts/features/patternrules: Add a test for Savannah bug #12202. 2005-03-03 Boris Kolpackov * scripts/features/se_implicit: Add a test for stem termination bug. Add a test for stem triple-expansion bug. * scripts/features/se_statpat: Add a test for stem triple-expansion bug. * scripts/features/statipattrules: Change test #4 to reflect new way empty prerequisite list is handled. 2005-03-01 Boris Kolpackov * scripts/features/statipattrules: Add a test for Savannah bug #12180. 2005-02-28 Paul D. Smith * scripts/options/dash-q: Add a test for Savannah bug # 7144. * scripts/options/symlinks: New file to test checking of symlink timestamps. Can't use filename dash-L because it conflicts with dash-l on case-insensitive filesystems. * scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST: Rename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3 unique filenames. 2005-02-28 Boris Kolpackov * scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET special variable. 2005-02-27 Boris Kolpackov * scripts/features/se_explicit: Test the second expansion in explicit rules. * scripts/features/se_implicit: Test the second expansion in implicit rules. * scripts/features/se_statpat: Test the second expansion in static pattern rules. * scripts/variables/automatic: Fix to work with the second expansion. * scripts/misc/general4: Add a test for bug #12091. 2005-02-27 Paul D. Smith * scripts/functions/eval: Check that eval of targets within command scripts fails. See Savannah bug # 12124. 2005-02-26 Paul D. Smith * test_driver.pl (compare_output): If a basic comparison of the log and answer doesn't match, try harder: change all backslashes to slashes and all CRLF to LF. This helps on DOS/Windows systems. 2005-02-09 Paul D. Smith * scripts/features/recursion: Test command line variable settings: only one instance of a given variable should be provided. 2004-11-30 Boris Kolpackov * tests/scripts/functions/abspath: New file: test `abspath' built-in function. * tests/scripts/functions/realpath: New file: test `realpath' built-in function. 2004-11-28 Paul D. Smith * scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252; this doesn't really test anything useful in UNIX but... * scripts/variables/SHELL: New file: test proper handling of SHELL according to POSIX rules. Fixes bug #1276. 2004-10-21 Boris Kolpackov * scripts/functions/word: Test $(firstword ) and $(lastword ). 2004-10-05 Boris Kolpackov * scripts/features/patspecific_vars: Test simple/recursive variable expansion. 2004-09-28 Boris Kolpackov * scripts/features/include: Test dontcare flag inheritance when rebuilding makefiles. 2004-09-27 Boris Kolpackov * scripts/features/patspecific_vars: Test exported variables. 2004-09-22 Paul D. Smith * run_make_tests.pl (run_make_test): Don't add newlines to the makestring or answer if they are completely empty. * scripts/features/patternrules: Rename from implicit_prereq_eval. * scripts/test_template: Rework the template. 2004-09-21 Boris Kolpackov * run_make_tests.pl: Change `#!/usr/local/bin/perl' to be `#!/usr/bin/env perl'. * scripts/features/implicit_prereq_eval: Test implicit rule prerequisite evaluation code. 2004-09-21 Paul D. Smith * run_make_tests.pl (run_make_test): Enhance to allow the make string to be undef: in that case it reuses the previous make string. Allows multiple tests on the same makefile. * scripts/variables/flavors: Add some tests for prefix characters interacting with define/endef variables. 2004-09-20 Paul D. Smith * scripts/functions/substitution: Rewrite to use run_make_test() interface, and add test for substitution failures reported by Markus Mauhart . 2004-03-22 Paul D. Smith * test_driver.pl (run_each_test, toplevel, compare_output): Change to track both the testing categories _AND_ the number of individual tests, and report both sets of numbers. 2004-02-21 Paul D. Smith * scripts/functions/origin: Set our own environment variable rather than relying on $HOME. 2004-01-21 Paul D. Smith * scripts/features/conditionals: Test arguments to ifn?def which contain whitespace (such as a function that is evaluated). Bug #7257. 2004-01-07 Paul D. Smith * scripts/features/order_only: Test order-only prerequisites in pattern rules (patch #2349). 2003-11-02 Paul D. Smith * scripts/functions/if: Test if on conditionals with trailing whitespace--bug #5798. * scripts/functions/eval: Test eval in a non-file context--bug #6195. 2003-04-19 Paul D. Smith * scripts/features/patspecific_vars: Test multiple patterns matching the same target--Bug #1405. 2003-04-09 Paul D. Smith * run_make_tests.pl (set_more_defaults): A new $port_type of 'OS/2' for (surprise!) OS/2. Also choose a wait time of 2 seconds for OS/2. 2003-03-28 Paul D. Smith * scripts/targets/SECONDARY: Test the "global" .SECONDARY (with not prerequisites)--Bug #2515. 2003-01-30 Paul D. Smith * scripts/features/targetvars: Test very long target-specific variable definition lines (longer than the default make buffer length). Tests patch # 1022. * scripts/functions/eval: Test very recursive $(eval ...) calls with simple variable expansion (bug #2238). * scripts/functions/word: Test error handling for word and wordlist functions (bug #2407). 2003-01-22 Paul D. Smith * scripts/functions/call: Test recursive argument masking (bug #1744). 2002-10-25 Paul D. Smith * scripts/functions/eval: Test using $(eval ...) inside conditionals (Bug #1516). 2002-10-14 Paul D. Smith * scripts/options/dash-t: Add a test for handling -t on targets with no commands (Bug #1418). 2002-10-13 Paul D. Smith * scripts/features/targetvars: Add a test for exporting target-specific vars (Bug #1391). 2002-10-05 Paul D. Smith * scripts/variables/automatic: Add tests for $$(@), $${@}, $${@D}, and $${@F}. 2002-09-23 Paul D. Smith * scripts/features/escape: Test handling of escaped comment characters in targets and prerequisites. 2002-09-18 Paul D. Smith * scripts/features/export: Test export/unexport of multiple variables in a single command. 2002-09-17 Paul D. Smith * scripts/features/targetvars: Tests for Bug #940: test target-specific and pattern-specific variables in conjunction with double-colon targets. 2002-09-10 Paul D. Smith * test_driver.pl (compare_output): Match the new format for time skew error messages. * scripts/features/export: Created. Add tests for export/unexport capabilities, including exporting/unexporting expanded variables. * scripts/features/conditionals: Add a test for expanded variables in ifdef conditionals. 2002-09-04 Paul D. Smith * scripts/features/reinvoke: Change touch/sleep combos to utouch invocations. * scripts/features/vpathgpath: Ditto. * scripts/features/vpathplus: Ditto. * scripts/options/dash-n: Ditto. * scripts/targets/INTERMEDIATE: Ditto. * scripts/targets/SECONDARY: Ditto. * scripts/options/dash-t: Added a test for the -t bug fixed by Henning Makholm. This test was also contributed by Henning. * scripts/misc/general4: Add a test suite for obscure algorithmic features of make. First test: make sure creation subdirectories as prerequisites of targets works properly. * scripts/misc/version: Remove this bogus test. 2002-08-07 Paul D. Smith * scripts/misc/general3: Add a test for makefiles that don't end in newlines. * scripts/variables/special: Create tests for the special variables (.VARIABLES and .TARGETS). Comment out .TARGETS test for now as it's not yet supported. 2002-08-01 Paul D. Smith * scripts/options/dash-B: Add a test for the new -B option. 2002-07-11 Paul D. Smith * run_make_tests.pl (valid_option): Add support for Valgrind. Use -valgrind option to the test suite. (set_more_defaults): Set up the file descriptor to capture Valgrind output. We have to unset its close-on-exec flag; we hardcode the value for F_SETFD (2) rather than load it; hopefully this will help us avoid breaking the Windows/DOS test suite. 2002-07-10 Paul D. Smith * scripts/variables/automatic: Add some tests for $$@, $$(@D), and $$(@F). * test_driver.pl (utouch): Create a new function that creates a file with a specific timestamp offset. Use of this function will let us avoid lots of annoying sleep() invocations in the tests just to get proper timestamping, which will make the tests run a lot faster. So far it's only used in the automatic test suite. 2002-07-09 Paul D. Smith * scripts/variables/automatic: Create a test for automatic variables. 2002-07-08 Paul D. Smith * scripts/features/order_only: Test new order-only prerequisites. 2002-07-07 Paul D. Smith * scripts/functions/eval: Test new function. * scripts/functions/value: Test new function. * scripts/variables/MAKEFILE_LIST: Test new variable. 2002-04-28 Paul D. Smith * scripts/functions/call: New test: transitive closure implementation using $(call ...) to test variable recursion. 2002-04-21 Paul D. Smith * test_driver.pl (compare_dir_tree): Ignore CVS and RCS directories in the script directories. 2001-05-02 Paul D. Smith * scripts/variables/flavors: Test define/endef scripts where only one of the command lines is quiet. 2000-06-22 Paul D. Smith * scripts/options/dash-q: New file; test the -q option. Includes a test for PR/1780. 2000-06-21 Paul D. Smith * scripts/features/targetvars: Added a test for PR/1709: allowing semicolons in target-specific variable values. 2000-06-19 Paul D. Smith * scripts/functions/addsuffix: Test for an empty final argument. Actually this bug might have happened for any function, but this one was handy. 2000-06-17 Eli Zaretskii * scripts/options/general: If parallel jobs are not supported, expect a warning message from Make. 2000-06-15 Eli Zaretskii * scripts/options/general: Don't try -jN with N != 1 if parallel jobs are not supported. 2000-05-24 Paul D. Smith * scripts/options/general: Test general option processing (PR/1716). 2000-04-11 Paul D. Smith * scripts/functions/strip: Test empty value to strip (PR/1689). 2000-04-08 Eli Zaretskii * scripts/features/reinvoke: Sleep before updating the target files in the first test, to ensure its time stamp really gets newer; otherwise Make might re-exec more than once. 2000-04-07 Eli Zaretskii * scripts/features/double_colon: Don't run the parallel tests if parallel jobs aren't supported. 2000-04-04 Paul D. Smith * scripts/functions/word: wordlist doesn't swap arguments anymore. 2000-03-27 Paul D. Smith * scripts/features/statipattrules: Test that static pattern rules whose prerequisite patterns resolve to empty strings throw an error (instead of dumping core). Fixes PR/1670. * scripts/features/reinvoke: Make more robust by touching "b" first, to ensure it's not newer than "a". Reported by Marco Franzen . * scripts/options/dash-n: Ditto. * scripts/functions/call: Whoops. The fix to PR/1527 caused recursive invocations of $(call ...) to break. I can't come up with any way to get both working at the same time, so I backed out the fix to 1527 and added a test case for recursive calls. This also tests the fix for PR/1610. * scripts/features/double_colon: Test that circular dependencies in double-colon rule sets are detected correctly (PR/1671). 2000-03-26 Paul D. Smith * scripts/targets/INTERMEDIATE: Test that make doesn't remove .INTERMEDIATE files when given on the command line (PR/1669). 2000-03-08 Paul D. Smith * scripts/options/dash-k: Add a test for error detection by multiple targets depending on the same prerequisite with -k. For PR/1634. 2000-02-07 Paul D. Smith * scripts/features/escape: Add a test for backslash-escaped spaces in a target name (PR/1586). 2000-02-04 Paul D. Smith * scripts/features/patspecific_vars: Add a test for pattern-specific target variables inherited from the parent target (PR/1407). 2000-02-02 Paul D. Smith * run_make_tests.pl (set_more_defaults): Hard-code the LANG to C to make sure sorting order, etc. is predictable. Reported by Andreas Jaeger . * run_make_tests.pl (set_more_defaults): Set the $wtime variable depending on the OS. Eli Zaretskii reports this seems to need to be *4* on DOS/Windows, not just 2. Keep it 1 for other systems. * scripts/features/vpathplus (touchfiles): Use the $wtime value instead of hardcoding 2. * scripts/targets/SECONDARY: Ditto. * scripts/targets/INTERMEDIATE: Ditto. 2000-01-27 Paul D. Smith * test_driver.pl (toplevel): Don't try to run test scripts which are really directories. 2000-01-23 Paul D. Smith * scripts/features/include: Remove a check; the fix caused more problems than the error, so I removed it and removed the test for it. 2000-01-11 Paul D. Smith * scripts/functions/call: Add a test for PR/1517 and PR/1527: make sure $(call ...) doesn't eval its arguments and that you can invoke foreach from it without looping forever. 1999-12-15 Paul D. Smith * scripts/targets/INTERMEDIATE: Add a test for PR/1423: make sure .INTERMEDIATE settings on files don't disable them as implicit intermediate possibilities. 1999-12-01 Paul D. Smith * scripts/features/double_colon: Add a test for PR/1476: Try double-colon rules as non-goal targets and during parallel builds to make sure they're handled serially. 1999-11-17 Paul D. Smith * scripts/functions/if: Add a test for PR/1429: put some text after an if-statement to make sure it works. * scripts/features/targetvars: Add a test for PR/1380: handling += in target-specific variable definitions correctly. 1999-10-15 Paul D. Smith * scripts/variables/MAKEFILES: This was really broken: it didn't test anything at all, really. Rewrote it, plus added a test for PR/1394. 1999-10-13 Paul D. Smith * scripts/options/dash-n: Add a test for PR/1379: "-n doesn't behave properly when used with recursive targets". 1999-10-08 Paul D. Smith * scripts/features/targetvars: Add a check for PR/1378: "Target-specific vars don't inherit correctly" 1999-09-29 Paul D. Smith * test_driver.pl (get_osname): Change $fancy_file_names to $short_filenames and reverse the logic. (run_each_test): Change test of non-existent $port_host to use $short_filenames--problem reported by Eli Zaretskii. 1999-09-23 Paul D. Smith * scripts/features/parallelism: Add a check to ensure that the jobserver works when we re-invoke. Also cleaned up the tests a little, reducing the number of rules we use so the test won't need as many "sleep" commands. 1999-09-16 Paul D. Smith * scripts/features/reinvoke: Remove invocations of "touch" in makefiles. See the comments on the touch function rewrite below. Note that UNIX touch behaves the same way if the file already exists: it sets the time to the _local_ time. We don't want this. This is probably a good tip for makefile writers in general, actually... where practical. * scripts/options/dash-l: Ditto. * scripts/options/dash-n: Ditto. * test_driver.pl (run_each_test): In retrospect, I don't like the .lN/.bN/.dN postfix required by DOS. So, for non-DOS systems I changed it back to use .log, .base, and .diff. * run_make_tests.pl (set_more_defaults): Move the check for the make pathname to here from set_defaults (that's too early since it happens before the command line processing). Create a new variable $port_type, calculated from $osname, to specify what kind of system we're running on. We should integrate the VOS stuff here, too. (valid_option): Comment out the workdir/-work stuff so people won't be fooled into thinking it works... someone needs to fix this, though! * scripts/functions/origin: Use $port_type instead of $osname. * scripts/functions/foreach: Ditto. * scripts/features/default_names: Ditto. 1999-09-15 Paul D. Smith * test_driver.pl (touch): Rewrite this function. Previously it used to use utime() to hard-set the time based on the current local clock, or, if the file didn't exist, it merely created it. This mirrors exactly what real UNIX touch does, but it fails badly on networked filesystems where the FS server clock is skewed from the local clock: normally modifying a file causes it to get a mod time based on the _server's_ clock. Hard-setting it based on the _local_ clock causes gratuitous errors and makes the tests unreliable except on local filesystems. The new function will simply modify the file, allowing the filesystem to set the mod time as it sees fit. * scripts/features/parallelism: The second test output could change depending on how fast some scripts completed; use "sleep" to force the order we want. * test_driver.pl (toplevel): A bug in Perl 5.000 to Perl 5.004 means that "%ENV = ();" doesn't do the right thing. This worked in Perl 4 and was fixed in Perl 5.004_01, but use a loop to delete the environment rather than require specific versions. * run_make_tests.pl (set_more_defaults): Don't use Perl 5 s/// modifier "s", so the tests will run with Perl 4. (set_more_defaults): Set $pure_log to empty if there's no -logfile option in PURIFYOPTIONS. (setup_for_test): Don't remove any logs unless $pure_log is set. 1999-09-15 Eli Zaretskii * scripts/features/reinvoke: Put the SHELL definition in the right test makefile. 1999-09-15 Paul D. Smith ChangeLog file for the test suite created. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/tests/ChangeLog.1000066400000000000000000001372741317072305000200640ustar00rootroot000000000000002013-10-09 Paul Smith * scripts/features/patspecific_vars: Typo fixes. 2013-10-05 Paul Smith * test_driver.pl (run_all_tests): Rewrite to be more clear. * scripts/features/jobserver: Avoid using $ENV{HOME} as it doesn't exist everywhere. * scripts/features/default_names: End with 1; * scripts/features/loadapi: Use new calling signatures. Verify the NOEXPAND flag works. Test with all valid function name characters. 2013-09-29 Paul Smith * scripts/variables/SHELL: Solaris /bin/sh can't handle options in multiple words; skip that test. * scripts/targets/ONESHELL: Ditto. * scripts/variables/GNUMAKEFLAGS: Verify that GNUMAKEFLAGS is cleared and options are not duplicated. 2013-09-23 Paul Smith * scripts/options/print-directory: Rename dash-w to print-directory to avoid conflicts with dash-W on case-insensitive filesystems. 2013-09-22 Paul Smith * scripts/features/se_implicit: Verify that order-only tokens inside second expansion are parsed correctly. Test for Savannah bug #31155. * run_make_tests.pl (set_more_defaults): If we can't find gnumake.h based on the make program we might be running from a remote build directory. Parse the Makefile for the right path. Fix some test issues on Solaris. * scripts/features/archives: Determine what output ar gives when adding and replacing objects and compare with that. * scripts/features/escape: Solaris /bin/sh doesn't properly handle backslashes inside single quotes, so don't rely on it. * scripts/features/output-sync: false(1) gives different exit codes on different systems; use "exit 1" instead. * scripts/features/parallelism: Increase the timeout for slower systems. 2013-09-21 Paul Smith * scripts/features/archives: Some versions of ar (MacOSX) generate different output when creating archives. Run it and verify the real output. * scripts/features/default_names: MacOSX is, like Windows, case-preserving / case-insensitive. Redo the test to avoid checking for "UNIX". * test_driver.pl (attach_default_output): Don't dup stdout into stderr. Reported by Denis Excoffier * scripts/features/se_explicit: Fix a test that behaves differently with/without archive capability enabled. * scripts/features/output-sync: Don't test output-sync if it's not enabled. We also skip it if parallelism is not enabled, although strictly speaking some of the output-sync tests are valid even without parallelism. * scripts/features/jobserver: Move some tests that require the jobserver from features/parallelism to a separate suite. Only run this if jobserver mode is enabled. * scripts/features/output-sync: Test shell functions writing to stderr in recipes: ensure it's captured via output-sync. Test output generated while reading makefiles and make sure it's captured via output-sync. Make sure that fatal errors dump the output so it's not lost. * scripts/options/dash-w: Add a test for -w flag. 2013-09-15 Paul Smith * scripts/misc/fopen-fail: Check for failure on infinite recursion. * run_make_tests.pl (run_make_test): Allow the answer string to be undef, which means that we shouldn't compare it at all. Only the exit code matters in this case. * test_driver.pl (compare_output): Ditto. Test for Savannah bug #27374. * scripts/features/parallelism: Test broken jobserver on recursion. Test for Savannah bug #39934. * scripts/options/eval: Verify --eval during restart. Test for Savannah bug #39203. 2013-09-14 Paul Smith * scripts/features/output-sync: Verify -Orecurse properly. 2013-09-12 Paul Smith * scripts/features/output-sync: Modify for output sync behavior. * scripts/variables/MAKE_RESTARTS: Ditto. * scripts/variables/MAKEFLAGS: Remove mode for --trace. * scripts/variables/GNUMAKEFLAGS: Ditto. 2013-07-22 Paul Smith * scripts/features/rule_glob: Add tests for wildcards in rules. Test for Savannah bug #39310. 2013-07-09 Paul Smith * scripts/features/se_implicit: Add a test for SE rules depending on other SE rules to be built. 2013-05-26 Paul Smith * scripts/features/archives: Test for Savannah bug #38442. * scripts/misc/bs-nl: Test for Savannah bug #39035. Add a test for Savannah bug #38945. 2013-05-22 Paul Smith * scripts/options/dash-n: Fix results after MAKEFLAGS fixes. * scripts/variables/MAKEFLAGS: Ditto. * scripts/variables/GNUMAKEFLAGS: Ditto. 2013-05-14 Paul Smith * scripts/features/loadapi: Add plugin_is_GPL_compatible symbol. * scripts/features/load: Ditto. 2013-05-13 Paul Smith * scripts/features/output-sync (output_sync_set): Update for new --trace behavior. 2013-05-05 Paul Smith * scripts/features/output-sync (output_sync_set): Remove extraneous enter/leave lines, which are no longer printed. Add tests for syncing command line printing. (output_sync_set): Rename options: "job"->"line"; "make"->"recurse" 2013-05-04 Paul Smith * scripts/features/loadapi: Use the new alloc functions. * scripts/features/output-sync (output_sync_set): New test for ordered recursive output for -Ojob / -Otarget. 2013-05-03 Eli Zaretskii * scripts/features/load: Fix signatures of testload_gmk_setup and explicit_setup, to bring them in line with the documentation. 2013-04-28 Paul Smith * scripts/features/output-sync (output_sync_set): Add tests for the per-job syntax mode. (output_sync_set): Test improved error message location. 2013-04-15 Paul Smith * scripts/features/output-sync (output_sync_set): New arg syntax. 2013-04-14 Paul Smith * scripts/features/output-sync: Rewrite to be more reliable. * test_driver.pl (_run_command): Don't set SIGALRM until after we start the child. Print errors to the top-level output, which will be stderr. (attach_default_output): Use a list of file handles as the stack. (detach_default_output): Ditto. * scripts/features/output-sync: Add a test for output-sync. 2013-02-25 Paul Smith * run_make_tests.pl (valid_option): Support the -srcdir flag. (set_more_defaults): Set up $srcdir if it's not set yet. * scripts/functions/guile: Verify gmk-eval doesn't expand twice. * scripts/features/load: Rework to test just the load capability. * scripts/features/loadapi: New set of tests for the load API. 2013-01-19 Paul Smith * scripts/features/load: Test loaded files with and without "./" prefix. Add tests for automatically rebuilding loaded files if they are out of date or non-existent. 2013-01-13 Paul Smith * scripts/features/archives: Add a check targets that have parens, but are not archives. See Savannah bug #37878. * scripts/options/dash-n: Verify -n is preserved after recursive / re-exec. See Savannah bug #38051. 2013-01-12 Paul Smith * scripts/features/parallelism: Change rule so it doesn't depend on invocation order, etc. 2012-10-29 Paul Smith * scripts/features/load: New test suite for the "load" directive. 2012-09-09 Paul Smith * scripts/functions/file: Get errors in the C locale, not the current locale. Fixes Savannah bug #35764. * scripts/features/escape: Check that backslashes before non-special characters are not removed. * scripts/features/utf8: New test for UTF-8 support. See Savannah bug #36529. * scripts/targets/POSIX: Add tests for default macro values as specified by IEEE Std 1003.1-2008. See Savannah bug #37069. 2012-03-04 Paul Smith * scripts/features/se_explicit: Test $(x:%=%) format in secondary expansion prerequisite lists. See Savannah bug #16545. * scripts/features/escape: Test escaped ":" in prerequisite lists. See Savannah bug #12126. * scripts/variables/private: Test appending private variables in pattern-specific target rules. See Savannah bug #35468. 2012-03-03 Paul Smith * scripts/variables/SHELL: Ensure .SHELLFLAGS works with options separated by whitespace. * scripts/targets/ONESHELL: Try .ONESHELL in combination with whitespace-separated options in .SHELLFLAGS. See Savannah bug #35397. * scripts/functions/filter-out: Add filter tests and test escape operations. See Savannah bug #35410. * guile.supp: Suppress valgrind errors from Guile * run_make_tests.pl: Use the Guile suppression file. * scripts/misc/bs-nl: Check for POSIX and non-POSIX backslash/newline handling. Addresses Savannah bug #16670. 2012-01-29 Paul Smith * scripts/variables/flavors: Add tests for ::= * scripts/variables/define: Ditto * scripts/functions/file: Test the new $(file ...) function. 2012-01-12 Paul Smith * scripts/functions/guile: New regression tests for Guile support. 2011-12-10 Paul Smith * scripts/targets/SECONDARY: Add prereq statements to ensure rules are printed in the right order for test #9 2011-11-14 Paul Smith * scripts/features/double_colon: Check double-colon with escaped filenames. See Savannah bug #33399. 2011-09-18 Paul Smith * scripts/features/parallelism: On re-exec make sure we preserve the value of MAKEFLAGS when necessary. See Savannah bug #33873. * scripts/features/vpath3: Verify handling of -lfoo libraries found via vpath vs. the standard directory search. See Savannah bug #32511. 2011-09-12 Paul Smith * scripts/functions/call: Verify that using export in a $(call ...) context creates a global variable. See Savannah bug #32498. 2011-09-02 Paul Smith * scripts/options/dash-n: Verify that in "-n -t", the -n takes priority. Patch from Michael Witten . 2011-08-29 Paul Smith * scripts/features/varnesting: Test resetting of variables while expanding them. See Savannah patch #7534 2011-06-12 Paul Smith * scripts/features/archives: Check archives with whitespace at the beginning, end, and extra in the middle. Another test for Savannah bug #30612. 2011-05-07 Paul Smith * scripts/variables/private: Ensure we skip private variables when appending. Test for Savannah bug #32872. * scripts/functions/wildcard: Verify wildcard used to test for file existence/non-existence. 2011-05-02 Paul Smith * scripts/functions/sort: Add a test for Savannah bug #33125. 2011-04-17 David A. Wheeler * scripts/features/shell_assignment: Regression for "!=" feature 2010-11-06 Paul Smith * scripts/features/targetvars: Fix known-good output for BS/NL changes. * scripts/functions/call: Ditto. * scripts/variables/special: Ditto. * scripts/misc/bs-nl: New test suite for backslash/newline testing. 2010-08-29 Paul Smith * scripts/features/errors: Add new error message to output text. * scripts/variables/SHELL: Ditto. * scripts/targets/POSIX: Ditto. * scripts/options/dash-k: Ditto. * scripts/features/vpathplus: Ditto. * scripts/features/patternrules: Ditto. * scripts/features/parallelism: Ditto. 2010-08-13 Paul Smith * scripts/features/archives: New regression tests for archive support. Test for fix to Savannah bug #30612. * run_make_tests.pl (set_more_defaults): Set a %FEATURES hash to the features available in $(.FEATURES). 2010-08-10 Paul Smith * scripts/features/reinvoke: Ensure command line variable settings are preserved across make re-exec. Tests Savannah bug #30723. 2010-07-28 Paul Smith * scripts/targets/POSIX: Compatibility issues with Solaris (and Tru64?); "false" returns different exit codes, and set -x shows output with extra whitespace. Run the commands by hand first to find out what the real shell would do, then compare what make does. * scripts/variables/SHELL: Ditto. 2010-07-12 Paul Smith * test_driver.pl: Add a new $perl_name containing the path to Perl. * run_make_tests.pl (run_make_test): Replace the special string #PERL# in a makefile etc. with the path the Perl executable so makefiles can use it. * scripts/targets/ONESHELL: Add a new set of regression tests for the .ONESHELL feature. 2010-07-06 Paul Smith * scripts/variables/SHELL: Test the new .SHELLFLAGS variable. * scripts/targets/POSIX: New file. Test the .POSIX special target. Verify that enabling .POSIX changes the shell flags to set -e. 2010-07-01 Paul Smith * scripts/features/recursion: Add a space to separate command-line args. Fixes Savannah bug #29968. 2009-11-12 Boris Kolpackov * scripts/features/vpath3: Test for the new library search behavior. 2009-10-06 Boris Kolpackov * scripts/features/se_explicit: Enable the test for now fixed Savannah bug 25780. 2009-10-06 Boris Kolpackov * scripts/variables/undefine: Tests for the new undefine feature. 2009-10-03 Paul Smith * scripts/features/parallelism: Test for open Savannah bug #26846. * scripts/variables/MAKE: Rewrite for new run_make_test() format. * scripts/variables/MAKEFLAGS: Created. Add test for Savannah bug #2216 (still open). * scripts/features/include: Test for Savannah bug #102 (still open). 2009-09-30 Boris Kolpackov * scripts/features/include: Add diagnostics issuing tests for cases where targets have been updated and failed with the dontcare flag. Savannah bugs #15110, #25493, #12686, #17740. 2009-09-28 Paul Smith * scripts/functions/shell: Add regression test for Savannah bug #20513 (still open). * scripts/features/se_explicit: Add regression tests for Savannah bug #25780 (still open). * run_make_tests.pl (valid_option): Add a new flag, -all([-_]?tests)? that runs tests we know will fail. This allows us to add regression tests to the test suite for bugs that haven't been fixed yet. 2009-09-28 Boris Kolpackov * scripts/features/patspecific_vars: Add a test for the shortest stem first order. * scripts/features/patternrules: Add a test for the shortest stem first order. 2009-09-24 Paul Smith * scripts/features/se_implicit: Add a test for order-only secondary expansion prerequisites. 2009-09-23 Paul Smith * scripts/features/patternrules: Test that we can remove pattern rules, both single and multiple prerequisites. Savannah bug #18622. * scripts/features/echoing: Rework for run_make_test(). 2009-06-14 Paul Smith * scripts/features/vpath: Verify we don't get bogus circular dependency warnings if we choose a different file via vpath during update. Savannah bug #13529. 2009-06-13 Paul Smith * scripts/variables/MAKEFILES: Verify that MAKEFILES included files (and files included by them) don't set the default goal. Savannah bug #13401. * scripts/functions/wildcard: Test that wildcards with non-existent glob matchers return empty. 2009-06-09 Paul Smith * scripts/options/dash-B: Test the $? works correctly with -B. Savannah bug #17825. * scripts/features/patternrules: Test that dependencies of "also_make" targets are created properly. Savannah bug #19108. * test_driver.pl (compare_output): Create a "run" file for failed tests containing the command that was run. (get_runfile): New function. * run_make_tests.pl (valid_option): Enhanced support for valgrind: allow memcheck and massif tools. * scripts/features/patternrules: Have to comment out a line in the first test due to backing out a change that broke the implicit rule search algorithm. Savannah bug #17752. * scripts/misc/general4: Remove a test that is redundant with patternrules. * scripts/features/parallelism: Add a test for re-exec with jobserver master override. Savannah bug #18124. 2009-06-08 Paul Smith * scripts/features/targetvars: Add a test for continued target vars after a semicolon. Savannah bug #17521. 2009-06-07 Paul Smith * scripts/features/se_explicit: Make sure we catch defining prereqs during snap_deps(). Savannah bug #24622. * scripts/variables/automatic: Check prereq ordering when the target with the recipe has no prereqs. Savannah bug #21198. * scripts/variables/LIBPATTERNS: Add a new set of test for $(.LIBPATTERNS) (previously untested!) 2009-06-04 Paul Smith * scripts/variables/SHELL: The export target-specific SHELL test has an incorrect known-good-value. * scripts/misc/general4: Check for whitespace (ffeed, vtab, etc.) * scripts/features/se_explicit: Add tests for Savannah bug #24588. 2009-05-31 Paul Smith * scripts/variables/DEFAULT_GOAL: Add tests for Savannah bug #25697. * scripts/features/targetvars: Add tests of overrides for Savannah bug #26207. * scripts/features/patspecific_vars: Ditto. * scripts/features/patternrules: Add a test for Savannah bug #26593. 2009-05-30 Paul Smith * scripts/variables/flavors: Update with new variable flavor tests. * scripts/variables/define: Create a new set of tests for define/endef and move those aspects of the flavors suite here. 2009-05-25 Paul Smith * scripts/features/targetvars: Ditto. * scripts/features/export: Test new variable parsing abilities. 2009-02-23 Ramon Garcia * scripts/variables/private: Create a new suite of tests for 'private'. 2007-11-04 Paul Smith * scripts/functions/eval: Update error message for command -> recipe. * test_driver.pl (compare_output): Allow the answer to be a regex, if surrounded by '/'. * scripts/misc/close_stdout: Use a regex for the answer, since sometimes the error will have a description and sometimes it won't. 2007-09-10 Paul Smith * scripts/variables/special: Add tests for .RECIPEPREFIX variable. 2007-08-15 Paul Smith These test cases were contributed by Icarus Sparry and J. David Bryan for Savannah bugs #3330 and #15919. * scripts/targets/SECONDARY: Add tests for Savannah bugs 3330 and 15919. * scripts/features/parallelism: Add tests for wrong answer/hang combining INTERMEDIATE, order-only prereqs, and parallelism. See Savannah bugs 3330 and 15919. 2007-07-13 Paul Smith Install a timeout so tests can never loop infinitely. Original idea and patch for a single-test version provided by Icarus Sparry * test_driver.pl (_run_command): New function: this is called by other functions to actually run a command. Before we run it, install a SIGALRM handler and set up a timer to go off in the future (default is 5s; this can be overridden by individual tests). (run_command): Call it. (run_command_with_output): Call it. * run_make_tests.pl (run_make_with_options): Override the default timeout if the caller requests it. (run_make_test): Pass any timeout override to run_make_with_options. * scripts/features/parallelism: Increase the timeout for long tests. * scripts/options/dash-l: Ditto. 2006-10-01 Paul Smith * run_make_tests.pl (set_more_defaults): Remove setting of LANG in ENV here. This doesn't always work. * test_driver.pl (toplevel): Set LC_ALL to 'C' in the make environment. Fixes Savannah bug #16698. 2006-09-30 Paul Smith * scripts/variables/automatic: Add back the test for bug #8154. 2006-04-01 Paul D. Smith * scripts/functions/realpath: Don't run tests with multiple initial slashes on Windows: those paths mean something different. 2006-03-19 Paul D. Smith * scripts/features/parallelism: Test that the jobserver is properly managed when we have to re-exec the master instance of make. 2006-03-17 Boris Kolpackov * scripts/features/statipattrules: Add tests for bug #16053. 2006-03-09 Paul Smith * scripts/features/escape: Use "pre:" not "p:" to avoid conflicts with DOS drive letters. Fixes Savannah bug #15947. * test_driver.pl (run_each_test): Set the status properly even when a test fails to execute. Fixes Savannah bug #15942. * scripts/functions/foreach: Use a different environment variable other than PATH to avoid differences with Windows platforms. Fixes Savannah bug #15938. 2006-03-05 Paul D. Smith * run_make_tests.pl (set_more_defaults): Add CYGWIN_NT as a port type W32. Fixed Savannah bug #15937. * scripts/features/default_names: Don't call error() when the test fails. Fixes Savannah bug #15941. 2006-02-17 Paul D. Smith * scripts/features/targetvars: Test a complex construction which guarantees that we have to merge variable lists of different sizes. Tests for Savannah bug #15757. 2006-02-15 Paul D. Smith * scripts/functions/error: Make sure filename/lineno information is related to where the error is expanded, not where it's set. * scripts/functions/warning: Ditto. * scripts/functions/foreach: Check for different error conditions. * scripts/functions/word: Ditto. * scripts/variables/negative: Test some variable reference failure conditions. * scripts/options/warn-undefined-variables: Test the --warn-undefined-variables flag. 2006-02-09 Paul D. Smith * run_make_tests.pl (set_more_defaults): Update valgrind support for newer versions. * test_driver.pl (toplevel): Skip all hidden files/directories (ones beginning with "."). * scripts/functions/andor: Tests for $(and ...) and $(or ...) functions. 2006-02-08 Boris Kolpackov * scripts/features/parallelism: Add a test for bug #15641. 2006-02-06 Paul D. Smith * scripts/options/dash-W: Add a test for bug #15341. 2006-01-03 Paul D. Smith * scripts/variables/automatic: Add a test for bug #8154. * README: Update to reflect the current state of the test suite. 2005-12-12 Paul D. Smith * scripts/features/parallelism, scripts/functions/wildcard, scripts/targets/FORCE, scripts/targets/PHONY, scripts/targets/SILENT: Use the default setting for $delete_command. Fixes bug #15085. * run_make_tests.pl (get_this_pwd) [VMS]: Use -no_ask with delete_file. 2005-12-11 Paul D. Smith * scripts/misc/general4: Test implicit rules with '$' in the prereq list & prereq patterns. * scripts/features/se_implicit: Add in .SECONDEXPANSION settings. 2005-12-09 Boris Kolpackov * scripts/features/patternrules: Add a test for bug #13022. 2005-12-07 Boris Kolpackov * scripts/features/double_colon: Add a test for bug #14334. 2005-11-17 Boris Kolpackov * scripts/functions/flavor: Add a test for the flavor function. 2005-11-14 Boris Kolpackov * scripts/variables/INCLUDE_DIRS: Add a test for the .INCLUDE_DIRS special variable. 2005-10-24 Paul D. Smith * scripts/misc/general4: Test '$$' in prerequisites list. * scripts/features/statipattrules: Rewrite to use run_make_test(). Add various static pattern info. * scripts/features/se_statpat: Enable .SECONDEXPANSION target. * scripts/features/se_explicit: Add tests for handling '$$' in prerequisite lists with and without setting .SECONDEXPANSION. * scripts/features/order_only: Convert to run_make_test(). * run_make_tests.pl (set_more_defaults): If we can't get the value of $(MAKE) from make, then fatal immediately. 2005-08-31 Paul D. Smith * run_make_tests.pl (get_this_pwd): Require the POSIX module (in an eval to trap errors) and if it exists, use POSIX::getcwd to find the working directory. If it doesn't exist, go back to the previous methods. This tries to be more accurate on Windows systems. 2005-08-29 Paul D. Smith * scripts/functions/abspath: Add some text to the error messages to get a better idea of what's wrong. Make warnings instead of errors. * scripts/features/patspecific_vars: Don't use "test", which is UNIX specific. Print the values and let the test script match them. 2005-08-25 Paul Smith * scripts/variables/SHELL: Use a /./ prefix instead of //: the former works better with non-UNIX environments. Fixes Savannah bug #14129. 2005-08-13 Boris Kolpackov * scripts/functions/wildcard: Wrap calls to $(wildcard) with $(sort) so that the resulting order is no longer filesystem- dependent. 2005-08-10 Boris Kolpackov * scripts/features/statipattrules: Add a test for Savannah bug #13881. 2005-08-07 Paul D. Smith * scripts/features/parallelism: Add a test for a bug reported by Michael Matz (matz@suse.de) in which make exits without waiting for all its children in some situations during parallel builds. 2005-07-08 Paul D. Smith * test_driver.pl: Reset the environment to a clean value every time before we invoke make. I'm suspicious that the environment isn't handled the same way in Windows as it is in UNIX, and some variables are leaking out beyond the tests they are intended for. Create an %extraENV hash tests can set to add more env. vars. * tests/scripts/features/export: Change to use %extraENV. * tests/scripts/functions/eval: Ditto. * tests/scripts/functions/origin: Ditto. * tests/scripts/options/dash-e: Ditto. * tests/scripts/variables/SHELL: Ditto. 2005-06-27 Paul D. Smith * scripts/options/dash-W: Use 'echo >>' instead of touch to update files. * scripts/features/reinvoke: Rewrite to be safer on systems with subsecond timestamps. * scripts/features/patternrules: False exits with different error codes on different systems (for example, Linux => 1, Solaris => 255). * scripts/options/dash-W: Set the timestamp to foo.x in the future, to be sure it will be considered updated when it's remade. 2005-06-26 Paul D. Smith * scripts/functions/shell: New test suite for the shell function. 2005-06-25 Paul D. Smith * scripts/features/include: Test include/-include/sinclude with no arguments. Tests fix for Savannah bug #1761. * scripts/misc/general3: Implement comprehensive testing of backslash-newline behavior in command scripts: various types of quoting, fast path / slow path, etc. Tests fix for Savannah bug #1332. * scripts/options/symlinks: Test symlinks to non-existent files. Tests fix for Savannah bug #13280. * scripts/misc/general3: Test semicolons in variable references. Tests fix for Savannah bug #1454. * scripts/variables/MAKE_RESTARTS: New file: test the MAKE_RESTARTS variable. * scripts/options/dash-B: Test re-exec doesn't loop infinitely. Tests fix for Savannah bug #7566. * scripts/options/dash-W: New file: test the -W flag, including re-exec infinite looping. 2005-06-12 Paul D. Smith * scripts/misc/close_stdout: Add a test for Savannah bug #1328. This test only works on systems that have /dev/full (e.g., Linux). 2005-06-09 Paul D. Smith * scripts/functions/foreach: Add a test for Savannah bug #11913. 2005-05-31 Boris Kolpackov * scripts/features/include: Add a test for Savannah bug #13216. * scripts/features/patternrules: Add a test for Savannah bug #13218. 2005-05-13 Paul D. Smith * scripts/features/conditionals: Add tests for the new if... else if... endif syntax. 2005-05-03 Paul D. Smith * scripts/variables/DEFAULT_GOAL: Rename DEFAULT_TARGET to DEFAULT_GOAL. 2005-05-02 Paul D. Smith * scripts/features/parallelism: Add a test for exporting recursive variables containing $(shell) calls. Rewrite this script to use run_make_test() everywhere. 2005-04-07 Paul D. Smith * scripts/targets/SECONDARY: Add a test for Savannah bug #12331. 2005-03-15 Boris Kolpackov * scripts/variables/automatic: Add a test for Savannah bug #12320. 2005-03-10 Boris Kolpackov * scripts/features/patternrules: Add a test for Savannah bug #12267. 2005-03-09 Boris Kolpackov * scripts/variables/DEFAULT_TARGET: Add a test for Savannah bug #12266. 2005-03-04 Boris Kolpackov * scripts/features/patternrules: Add a test for Savannah bug #12202. 2005-03-03 Boris Kolpackov * scripts/features/se_implicit: Add a test for stem termination bug. Add a test for stem triple-expansion bug. * scripts/features/se_statpat: Add a test for stem triple-expansion bug. * scripts/features/statipattrules: Change test #4 to reflect new way empty prerequisite list is handled. 2005-03-01 Boris Kolpackov * scripts/features/statipattrules: Add a test for Savannah bug #12180. 2005-02-28 Paul D. Smith * scripts/options/dash-q: Add a test for Savannah bug # 7144. * scripts/options/symlinks: New file to test checking of symlink timestamps. Can't use filename dash-L because it conflicts with dash-l on case-insensitive filesystems. * scripts/variables/MAKEFILE_LIST, scripts/variables/MFILE_LIST: Rename MAKEFILE_LIST test to MFILE_LIST, for systems that need 8.3 unique filenames. 2005-02-28 Boris Kolpackov * scripts/variables/DEFAULT_TARGET: Test the .DEFAULT_TARGET special variable. 2005-02-27 Boris Kolpackov * scripts/features/se_explicit: Test the second expansion in explicit rules. * scripts/features/se_implicit: Test the second expansion in implicit rules. * scripts/features/se_statpat: Test the second expansion in static pattern rules. * scripts/variables/automatic: Fix to work with the second expansion. * scripts/misc/general4: Add a test for bug #12091. 2005-02-27 Paul D. Smith * scripts/functions/eval: Check that eval of targets within command scripts fails. See Savannah bug # 12124. 2005-02-26 Paul D. Smith * test_driver.pl (compare_output): If a basic comparison of the log and answer doesn't match, try harder: change all backslashes to slashes and all CRLF to LF. This helps on DOS/Windows systems. 2005-02-09 Paul D. Smith * scripts/features/recursion: Test command line variable settings: only one instance of a given variable should be provided. 2004-11-30 Boris Kolpackov * tests/scripts/functions/abspath: New file: test `abspath' built-in function. * tests/scripts/functions/realpath: New file: test `realpath' built-in function. 2004-11-28 Paul D. Smith * scripts/options/dash-C [WINDOWS32]: Add a test for bug #10252; this doesn't really test anything useful in UNIX but... * scripts/variables/SHELL: New file: test proper handling of SHELL according to POSIX rules. Fixes bug #1276. 2004-10-21 Boris Kolpackov * scripts/functions/word: Test $(firstword ) and $(lastword ). 2004-10-05 Boris Kolpackov * scripts/features/patspecific_vars: Test simple/recursive variable expansion. 2004-09-28 Boris Kolpackov * scripts/features/include: Test dontcare flag inheritance when rebuilding makefiles. 2004-09-27 Boris Kolpackov * scripts/features/patspecific_vars: Test exported variables. 2004-09-22 Paul D. Smith * run_make_tests.pl (run_make_test): Don't add newlines to the makestring or answer if they are completely empty. * scripts/features/patternrules: Rename from implicit_prereq_eval. * scripts/test_template: Rework the template. 2004-09-21 Boris Kolpackov * run_make_tests.pl: Change `#!/usr/local/bin/perl' to be `#!/usr/bin/env perl'. * scripts/features/implicit_prereq_eval: Test implicit rule prerequisite evaluation code. 2004-09-21 Paul D. Smith * run_make_tests.pl (run_make_test): Enhance to allow the make string to be undef: in that case it reuses the previous make string. Allows multiple tests on the same makefile. * scripts/variables/flavors: Add some tests for prefix characters interacting with define/endef variables. 2004-09-20 Paul D. Smith * scripts/functions/substitution: Rewrite to use run_make_test() interface, and add test for substitution failures reported by Markus Mauhart . 2004-03-22 Paul D. Smith * test_driver.pl (run_each_test, toplevel, compare_output): Change to track both the testing categories _AND_ the number of individual tests, and report both sets of numbers. 2004-02-21 Paul D. Smith * scripts/functions/origin: Set our own environment variable rather than relying on $HOME. 2004-01-21 Paul D. Smith * scripts/features/conditionals: Test arguments to ifn?def which contain whitespace (such as a function that is evaluated). Bug #7257. 2004-01-07 Paul D. Smith * scripts/features/order_only: Test order-only prerequisites in pattern rules (patch #2349). 2003-11-02 Paul D. Smith * scripts/functions/if: Test if on conditionals with trailing whitespace--bug #5798. * scripts/functions/eval: Test eval in a non-file context--bug #6195. 2003-04-19 Paul D. Smith * scripts/features/patspecific_vars: Test multiple patterns matching the same target--Bug #1405. 2003-04-09 Paul D. Smith * run_make_tests.pl (set_more_defaults): A new $port_type of 'OS/2' for (surprise!) OS/2. Also choose a wait time of 2 seconds for OS/2. 2003-03-28 Paul D. Smith * scripts/targets/SECONDARY: Test the "global" .SECONDARY (with not prerequisites)--Bug #2515. 2003-01-30 Paul D. Smith * scripts/features/targetvars: Test very long target-specific variable definition lines (longer than the default make buffer length). Tests patch # 1022. * scripts/functions/eval: Test very recursive $(eval ...) calls with simple variable expansion (bug #2238). * scripts/functions/word: Test error handling for word and wordlist functions (bug #2407). 2003-01-22 Paul D. Smith * scripts/functions/call: Test recursive argument masking (bug #1744). 2002-10-25 Paul D. Smith * scripts/functions/eval: Test using $(eval ...) inside conditionals (Bug #1516). 2002-10-14 Paul D. Smith * scripts/options/dash-t: Add a test for handling -t on targets with no commands (Bug #1418). 2002-10-13 Paul D. Smith * scripts/features/targetvars: Add a test for exporting target-specific vars (Bug #1391). 2002-10-05 Paul D. Smith * scripts/variables/automatic: Add tests for $$(@), $${@}, $${@D}, and $${@F}. 2002-09-23 Paul D. Smith * scripts/features/escape: Test handling of escaped comment characters in targets and prerequisites. 2002-09-18 Paul D. Smith * scripts/features/export: Test export/unexport of multiple variables in a single command. 2002-09-17 Paul D. Smith * scripts/features/targetvars: Tests for Bug #940: test target-specific and pattern-specific variables in conjunction with double-colon targets. 2002-09-10 Paul D. Smith * test_driver.pl (compare_output): Match the new format for time skew error messages. * scripts/features/export: Created. Add tests for export/unexport capabilities, including exporting/unexporting expanded variables. * scripts/features/conditionals: Add a test for expanded variables in ifdef conditionals. 2002-09-04 Paul D. Smith * scripts/features/reinvoke: Change touch/sleep combos to utouch invocations. * scripts/features/vpathgpath: Ditto. * scripts/features/vpathplus: Ditto. * scripts/options/dash-n: Ditto. * scripts/targets/INTERMEDIATE: Ditto. * scripts/targets/SECONDARY: Ditto. * scripts/options/dash-t: Added a test for the -t bug fixed by Henning Makholm. This test was also contributed by Henning. * scripts/misc/general4: Add a test suite for obscure algorithmic features of make. First test: make sure creation subdirectories as prerequisites of targets works properly. * scripts/misc/version: Remove this bogus test. 2002-08-07 Paul D. Smith * scripts/misc/general3: Add a test for makefiles that don't end in newlines. * scripts/variables/special: Create tests for the special variables (.VARIABLES and .TARGETS). Comment out .TARGETS test for now as it's not yet supported. 2002-08-01 Paul D. Smith * scripts/options/dash-B: Add a test for the new -B option. 2002-07-11 Paul D. Smith * run_make_tests.pl (valid_option): Add support for Valgrind. Use -valgrind option to the test suite. (set_more_defaults): Set up the file descriptor to capture Valgrind output. We have to unset its close-on-exec flag; we hardcode the value for F_SETFD (2) rather than load it; hopefully this will help us avoid breaking the Windows/DOS test suite. 2002-07-10 Paul D. Smith * scripts/variables/automatic: Add some tests for $$@, $$(@D), and $$(@F). * test_driver.pl (utouch): Create a new function that creates a file with a specific timestamp offset. Use of this function will let us avoid lots of annoying sleep() invocations in the tests just to get proper timestamping, which will make the tests run a lot faster. So far it's only used in the automatic test suite. 2002-07-09 Paul D. Smith * scripts/variables/automatic: Create a test for automatic variables. 2002-07-08 Paul D. Smith * scripts/features/order_only: Test new order-only prerequisites. 2002-07-07 Paul D. Smith * scripts/functions/eval: Test new function. * scripts/functions/value: Test new function. * scripts/variables/MAKEFILE_LIST: Test new variable. 2002-04-28 Paul D. Smith * scripts/functions/call: New test: transitive closure implementation using $(call ...) to test variable recursion. 2002-04-21 Paul D. Smith * test_driver.pl (compare_dir_tree): Ignore CVS and RCS directories in the script directories. 2001-05-02 Paul D. Smith * scripts/variables/flavors: Test define/endef scripts where only one of the command lines is quiet. 2000-06-22 Paul D. Smith * scripts/options/dash-q: New file; test the -q option. Includes a test for PR/1780. 2000-06-21 Paul D. Smith * scripts/features/targetvars: Added a test for PR/1709: allowing semicolons in target-specific variable values. 2000-06-19 Paul D. Smith * scripts/functions/addsuffix: Test for an empty final argument. Actually this bug might have happened for any function, but this one was handy. 2000-06-17 Eli Zaretskii * scripts/options/general: If parallel jobs are not supported, expect a warning message from Make. 2000-06-15 Eli Zaretskii * scripts/options/general: Don't try -jN with N != 1 if parallel jobs are not supported. 2000-05-24 Paul D. Smith * scripts/options/general: Test general option processing (PR/1716). 2000-04-11 Paul D. Smith * scripts/functions/strip: Test empty value to strip (PR/1689). 2000-04-08 Eli Zaretskii * scripts/features/reinvoke: Sleep before updating the target files in the first test, to ensure its time stamp really gets newer; otherwise Make might re-exec more than once. 2000-04-07 Eli Zaretskii * scripts/features/double_colon: Don't run the parallel tests if parallel jobs aren't supported. 2000-04-04 Paul D. Smith * scripts/functions/word: wordlist doesn't swap arguments anymore. 2000-03-27 Paul D. Smith * scripts/features/statipattrules: Test that static pattern rules whose prerequisite patterns resolve to empty strings throw an error (instead of dumping core). Fixes PR/1670. * scripts/features/reinvoke: Make more robust by touching "b" first, to ensure it's not newer than "a". Reported by Marco Franzen . * scripts/options/dash-n: Ditto. * scripts/functions/call: Whoops. The fix to PR/1527 caused recursive invocations of $(call ...) to break. I can't come up with any way to get both working at the same time, so I backed out the fix to 1527 and added a test case for recursive calls. This also tests the fix for PR/1610. * scripts/features/double_colon: Test that circular dependencies in double-colon rule sets are detected correctly (PR/1671). 2000-03-26 Paul D. Smith * scripts/targets/INTERMEDIATE: Test that make doesn't remove .INTERMEDIATE files when given on the command line (PR/1669). 2000-03-08 Paul D. Smith * scripts/options/dash-k: Add a test for error detection by multiple targets depending on the same prerequisite with -k. For PR/1634. 2000-02-07 Paul D. Smith * scripts/features/escape: Add a test for backslash-escaped spaces in a target name (PR/1586). 2000-02-04 Paul D. Smith * scripts/features/patspecific_vars: Add a test for pattern-specific target variables inherited from the parent target (PR/1407). 2000-02-02 Paul D. Smith * run_make_tests.pl (set_more_defaults): Hard-code the LANG to C to make sure sorting order, etc. is predictable. Reported by Andreas Jaeger . * run_make_tests.pl (set_more_defaults): Set the $wtime variable depending on the OS. Eli Zaretskii reports this seems to need to be *4* on DOS/Windows, not just 2. Keep it 1 for other systems. * scripts/features/vpathplus (touchfiles): Use the $wtime value instead of hardcoding 2. * scripts/targets/SECONDARY: Ditto. * scripts/targets/INTERMEDIATE: Ditto. 2000-01-27 Paul D. Smith * test_driver.pl (toplevel): Don't try to run test scripts which are really directories. 2000-01-23 Paul D. Smith * scripts/features/include: Remove a check; the fix caused more problems than the error, so I removed it and removed the test for it. 2000-01-11 Paul D. Smith * scripts/functions/call: Add a test for PR/1517 and PR/1527: make sure $(call ...) doesn't eval its arguments and that you can invoke foreach from it without looping forever. 1999-12-15 Paul D. Smith * scripts/targets/INTERMEDIATE: Add a test for PR/1423: make sure .INTERMEDIATE settings on files don't disable them as implicit intermediate possibilities. 1999-12-01 Paul D. Smith * scripts/features/double_colon: Add a test for PR/1476: Try double-colon rules as non-goal targets and during parallel builds to make sure they're handled serially. 1999-11-17 Paul D. Smith * scripts/functions/if: Add a test for PR/1429: put some text after an if-statement to make sure it works. * scripts/features/targetvars: Add a test for PR/1380: handling += in target-specific variable definitions correctly. 1999-10-15 Paul D. Smith * scripts/variables/MAKEFILES: This was really broken: it didn't test anything at all, really. Rewrote it, plus added a test for PR/1394. 1999-10-13 Paul D. Smith * scripts/options/dash-n: Add a test for PR/1379: "-n doesn't behave properly when used with recursive targets". 1999-10-08 Paul D. Smith * scripts/features/targetvars: Add a check for PR/1378: "Target-specific vars don't inherit correctly" 1999-09-29 Paul D. Smith * test_driver.pl (get_osname): Change $fancy_file_names to $short_filenames and reverse the logic. (run_each_test): Change test of non-existent $port_host to use $short_filenames--problem reported by Eli Zaretskii. 1999-09-23 Paul D. Smith * scripts/features/parallelism: Add a check to ensure that the jobserver works when we re-invoke. Also cleaned up the tests a little, reducing the number of rules we use so the test won't need as many "sleep" commands. 1999-09-16 Paul D. Smith * scripts/features/reinvoke: Remove invocations of "touch" in makefiles. See the comments on the touch function rewrite below. Note that UNIX touch behaves the same way if the file already exists: it sets the time to the _local_ time. We don't want this. This is probably a good tip for makefile writers in general, actually... where practical. * scripts/options/dash-l: Ditto. * scripts/options/dash-n: Ditto. * test_driver.pl (run_each_test): In retrospect, I don't like the .lN/.bN/.dN postfix required by DOS. So, for non-DOS systems I changed it back to use .log, .base, and .diff. * run_make_tests.pl (set_more_defaults): Move the check for the make pathname to here from set_defaults (that's too early since it happens before the command line processing). Create a new variable $port_type, calculated from $osname, to specify what kind of system we're running on. We should integrate the VOS stuff here, too. (valid_option): Comment out the workdir/-work stuff so people won't be fooled into thinking it works... someone needs to fix this, though! * scripts/functions/origin: Use $port_type instead of $osname. * scripts/functions/foreach: Ditto. * scripts/features/default_names: Ditto. 1999-09-15 Paul D. Smith * test_driver.pl (touch): Rewrite this function. Previously it used to use utime() to hard-set the time based on the current local clock, or, if the file didn't exist, it merely created it. This mirrors exactly what real UNIX touch does, but it fails badly on networked filesystems where the FS server clock is skewed from the local clock: normally modifying a file causes it to get a mod time based on the _server's_ clock. Hard-setting it based on the _local_ clock causes gratuitous errors and makes the tests unreliable except on local filesystems. The new function will simply modify the file, allowing the filesystem to set the mod time as it sees fit. * scripts/features/parallelism: The second test output could change depending on how fast some scripts completed; use "sleep" to force the order we want. * test_driver.pl (toplevel): A bug in Perl 5.000 to Perl 5.004 means that "%ENV = ();" doesn't do the right thing. This worked in Perl 4 and was fixed in Perl 5.004_01, but use a loop to delete the environment rather than require specific versions. * run_make_tests.pl (set_more_defaults): Don't use Perl 5 s/// modifier "s", so the tests will run with Perl 4. (set_more_defaults): Set $pure_log to empty if there's no -logfile option in PURIFYOPTIONS. (setup_for_test): Don't remove any logs unless $pure_log is set. 1999-09-15 Eli Zaretskii * scripts/features/reinvoke: Put the SHELL definition in the right test makefile. 1999-09-15 Paul D. Smith ChangeLog file for the test suite created. Copyright (C) 1992-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/tests/NEWS000066400000000000000000000151551317072305000166430ustar00rootroot00000000000000Changes from 0.4.9 to 3.78 (Sep 6, 1999): Lots of new tests. Renamed to follow the GNU make scheme. Also added some support for using Purify with make. Rob Tulloh contributed some changes to get the test suite running on NT; I tweaked them a bit (hopefully I didn't break anything!) Note that NT doesn't grok the self-exec funkiness that Unix shells use, so instead I broke that out into a separate shell script "run_make_tests" that invokes perl with the (renamed) script run_make_tests.pl. Eli Zaretski contributed changes to get the test suite running on DOS with DJGPP. I also meddled in these somewhat. If you're on DOS or NT you should run "perl.exe run_make_tests.pl ..." If you're on Unix, you can continue to run "./run_make_tests ..." as before. Changes from 0.4.8 to 0.4.9 (May 14, 1998): Release by Paul D. Smith ; I'm the one to blame for problems in this version :). Add some perl to test_driver.pl to strip out GNU make clock skew warning messages from the output before comparing it to the known-good output. A new test for escaped :'s in filenames (someone on VMS found this didn't work anymore in 3.77): scripts/features/escape. Changes from 0.4.7 to 0.4.8 (May 14, 1998): Release by Paul D. Smith ; I'm the one to blame for problems in this version :). New tests for features to be included in GNU make 3.77. Changes from 0.4.6 to 0.4.7 (August 18, 1997): Release by Paul D. Smith ; I'm the one to blame for problems in this version :). Reworked some tests to make sure they all work with both perl4 and perl5. Work around a bug in perl 5.004 which doesn't clean the environment correctly in all cases (fixed in at least 5.004_02). Updated functions/strip to test for newline stripping. Keep a $PURIFYOPTIONS env variable if present. Changes from 0.4.5 to 0.4.6 (April 07, 1997): Release by Paul D. Smith ; I'm the one to blame for problems in this version :). Updated to work with GNU make 3.76 (and pretests). Added new tests and updated existing ones. Note that the new tests weren't tested with perl 4, however I think they should work. Ignore any tests whose filenames end in "~", so that Emacs backup files aren't run. Changes from 0.4.4 to 0.4.5 (April 29, 1995): Updated to be compatible with perl 5.001 as well as 4.036. Note: the test suite still won't work on 14-char filesystems (sorry, Kaveh), but I will get to it. Also, some tests and stuff still haven't made it in because I haven't had time to write the test scripts for them. But they, too, will get in eventually. Contributions of scripts (i.e., tests that I can just drop in) are particularly welcome and will be incorporated immediately. Changes from 0.4.3 to 0.4.4 (March 1995): Updated for changes in make 3.72.12, and to ignore CVS directories (thanks go to Jim Meyering for the patches for this). Fixed uname call to not make a mess on BSD/OS 2.0 (whose uname -a is very verbose). Let me know if this doesn't work correctly on your system. Changed to display test name while it is running, not just when it finishes. Note: the test suite still won't work on 14-char filesystems (sorry, Kaveh), but I will get to it. Also, some tests and stuff still haven't made it in because I haven't had time to write the test scripts for them. But they, too, will get in eventually. Changes from 0.4 to 0.4.3 (October 1994): Fixed bugs (like dependencies on environment variables). Caught up with changes in make. The load_limit test should now silently ignore a failure due to make not being able to read /dev/kmem. Reorganized tests into subdirs and renamed lots of things so that those poor souls who still have to deal with 14-char filename limits won't hate me any more. Thanks very much to Kaveh R. Ghazi for helping me with the implementation and testing of these changes, and for putting up with all my whining about it... Added a $| = 1 so that systems that don't seem to automatically flush their output for some reason will still print all the output. I'd hate for someone to miss out on the smiley that you're supposed to get when all the tests pass... :-) Changes from 0.3 to 0.4 (August 1993): Lost in the mists of time (and my hurry to get it out before I left my job). Changes from 0.2 to 0.3 (9-30-92): Several tests fixed to match the fact that MAKELEVEL > 0 or -C now imply -w. parallel_execution test fixed to not use double colon rules any more since their behavior has changed. errors_in_commands test fixed to handle different error messages and return codes from rm. Several tests fixed to handle -make_path with a relative path and/or a name other than "make" for make. dash-e-option test fixed to use $PATH instead of $USER (since the latter does not exist on some System V systems). This also removes the dependency on getlogin (which fails under certain weird conditions). test_driver_core changed so that you can give a test name like scripts/errors_in_commands and it will be handled correctly (handy if you have a shell with filename completion). Changes from 0.1 to 0.2 (5-4-92): README corrected to require perl 4.019, not 4.010. -make_path replaces -old. errors_in_commands test updated for change in format introduced in make 3.62.6. test_driver_core now uses a better way of figuring what OS it is running on (thanks to meyering@cs.utexas.edu (Jim Meyering) for suggesting this, as well as discovering the hard way that the old way (testing for /mnt) fails on his machine). Some new tests were added. ------------------------------------------------------------------------------- Copyright (C) 1992-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . remake-4.1+dbg1.3~dfsg.1/tests/README000066400000000000000000000111051317072305000170130ustar00rootroot00000000000000The test suite was originally written by Steve McGee and Chris Arthur. It is covered by the GNU General Public License (Version 2), described in the file COPYING. It has been maintained as part of GNU make proper since GNU make 3.78. This entire test suite, including all test files, are copyright and distributed under the following terms: ----------------------------------------------------------------------------- Copyright (C) 1992-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 test suite requires Perl. These days, you should have at least Perl 5.004 (available from ftp.gnu.org, and portable to many machines). It used to work with Perl 4.036 but official support for Perl 4.x was abandoned a long time ago, due to lack of testbeds, as well as interest. The test suite assumes that the first "diff" it finds on your PATH is GNU diff, but that only matters if a test fails. To run the test suite on a UNIX system, use "perl ./run_make_tests" (or just "./run_make_tests" if you have a perl on your PATH). To run the test suite on Windows NT or DOS systems, use "perl.exe ./run_make-tests.pl". By default, the test engine picks up the first executable called "make" that it finds in your path. You may use the -make_path option (i.e., "perl run_make_tests -make_path /usr/local/src/make-3.78/make") if you want to run a particular copy. This now works correctly with relative paths and when make is called something other than "make" (like "gmake"). Tests cannot end with a "~" character, as the test suite will ignore any that do (I was tired of having it run my Emacs backup files as tests :)) Also, sometimes the tests may behave strangely on networked filesystems. You can use mkshadow to create a copy of the test suite in /tmp or similar, and try again. If the error disappears, it's an issue with your network or file server, not GNU make (I believe). This shouldn't happen very often anymore: I've done a lot of work on the tests to reduce the impacts of this situation. The options/dash-l test will not really test anything if the copy of make you are using can't obtain the system load. Some systems require make to be setgid sys or kmem for this; if you don't want to install make just to test it, make it setgid to kmem or whatever group /dev/kmem is (i.e., "chgrp kmem make;chmod g+s make" as root). In any case, the options/dash-l test should no longer *fail* because make can't read /dev/kmem. A directory named "work" will be created when the tests are run which will contain any makefiles and "diff" files of tests that fail so that you may look at them afterward to see the output of make and the expected result. There is a -help option which will give you more information about the other possible options for the test suite. Open Issues ----------- The test suite has a number of problems which should be addressed. One VERY serious one is that there is no real documentation. You just have to see the existing tests. Use the newer tests: many of the tests haven't been updated to use the latest/greatest test methods. See the ChangeLog in the tests directory for pointers. The second serious problem is that it's not parallelizable: it scribbles all over its installation directory and so can only test one make at a time. The third serious problem is that it's not relocatable: the only way it works when you build out of the source tree is to create symlinks, which doesn't work on every system and is bogus to boot. The fourth serious problem is that it doesn't create its own sandbox when running tests, so that if a test forgets to clean up after itself that can impact future tests. Bugs ---- Any complaints/suggestions/bugs/etc. for the test suite itself (as opposed to problems in make that the suite finds) should be handled the same way as normal GNU make bugs/problems (see the README for GNU make). Paul D. Smith Chris Arthur remake-4.1+dbg1.3~dfsg.1/tests/config-flags.pm.in000066400000000000000000000007261317072305000214440ustar00rootroot00000000000000# This is a -*-perl-*- script # # Set variables that were defined by configure, in case we need them # during the tests. %CONFIG_FLAGS = ( AM_LDFLAGS => '@AM_LDFLAGS@', AR => '@AR@', CC => '@CC@', CFLAGS => '@CFLAGS@', CPP => '@CPP@', CPPFLAGS => '@CPPFLAGS@', GUILE_CFLAGS => '@GUILE_CFLAGS@', GUILE_LIBS => '@GUILE_LIBS@', LDFLAGS => '@LDFLAGS@', LIBS => '@LIBS@' ); 1; remake-4.1+dbg1.3~dfsg.1/tests/config_flags_pm.com000077500000000000000000000032441317072305000217600ustar00rootroot00000000000000$! $! config_flags_pm.com - Build config-flags.pm on VMS. $! $! Just good enough to run the self tests for now. $! $! Copyright (C) 2014 Free Software Foundation, Inc. $! This file is part of GNU Make. $! $! GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY $! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS $! FOR A PARTICULAR PURPOSE. See the GNU 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 . $! $! $ open/read cfpm_in config-flags.pm.in $! $ outfile = "sys$disk:[]config-flags.pm" $! $ cflags = "/include=([],[.glob]" $! $ create 'outfile' $ open/append cfpm 'outfile' $! $cfpm_read_loop: $ read cfpm_in/end=cfpm_read_loop_end line_in $ line_in_len = f$length(line_in) $ if f$locate("@", line_in) .lt. line_in_len $ then $ part1 = f$element(0, "@", line_in) $ key = f$element(1, "@", line_in) $ part2 = f$element(2, "@", line_in) $ value = "" $ if key .eqs. "CC" then value = "CC" $ if key .eqs. "CPP" then value = "CPP" $ if key .eqs. "CFLAGS" then value = cflags $ if key .eqs. "GUILE_CFLAGS" then value = cflags $ write cfpm part1, value, part2 $ goto cfpm_read_loop $ endif $ write cfpm line_in $ goto cfpm_read_loop $cfpm_read_loop_end: $ close cfpm_in $ close cfpm $! remake-4.1+dbg1.3~dfsg.1/tests/guile.supp000066400000000000000000000005471317072305000201610ustar00rootroot00000000000000# Guile valgrind suppression file # Created with Guile 1.8.7 # --- Garbage collection { guilegc Memcheck:Cond ... fun:scm_gc_for_newcell } { guilegc Memcheck:Value4 ... fun:scm_gc_for_newcell } { guilegc Memcheck:Value8 ... fun:scm_gc_for_newcell } # -- scm_alloc_struct { guileheap Memcheck:Leak ... fun:scm_alloc_struct } remake-4.1+dbg1.3~dfsg.1/tests/mkshadow000077500000000000000000000026201317072305000177000ustar00rootroot00000000000000#!/bin/sh # # Simple script to make a "shadow" test directory, using symbolic links. # Typically you'd put the shadow in /tmp or another local disk # # Copyright (C) 1992-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . case "$1" in "") echo 'Usage: mkshadow '; exit 1 ;; esac dest="$1" if [ ! -d "$dest" ]; then echo "Destination directory '$dest' must exist!" exit 1 fi if [ ! -f run_make_tests ]; then echo "The current directory doesn't appear to contain the test suite!" exit 1 fi suite=`pwd | sed 's%^/tmp_mnt%%'` name=`basename "$suite"` files=`echo *` set -e mkdir "$dest/$name" cd "$dest/$name" ln -s "$suite" .testdir for f in $files; do ln -s .testdir/$f . done rm -rf work echo "Shadow test suite created in '$dest/$name'." exit 0 remake-4.1+dbg1.3~dfsg.1/tests/run_make_tests000077500000000000000000000001451317072305000211060ustar00rootroot00000000000000#!/bin/sh # No exec perl so we allow Environment variables to be passed through perl $0.pl ${1+"$@"} remake-4.1+dbg1.3~dfsg.1/tests/run_make_tests.com000077500000000000000000000201621317072305000216640ustar00rootroot00000000000000$! Test_make.com $! $! This is a wrapper for the GNU make perl test programs on VMS. $! $! Parameter "-help" for description on how to use described below. $! $! Copyright (C) 2014 Free Software Foundation, Inc. $! This file is part of GNU Make. $! $! GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY $! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS $! FOR A PARTICULAR PURPOSE. See the GNU 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 . $! $! $! Allow more than 8 paramters with using commas as a delimiter. $! $ params = "''p1',''p2',''p3',''p4',''p5',''p6',''p7',''p8'" $! $ test_flags = ",verbose,detail,keep,usage,help,debug," $ test_flags_len = f$length(test_flags) $ verbose_flag = "" $ detail_flag = "" $ keep_flag = "" $ usage_flag = "" $ help_flag = "" $ debug_flag = "" $! $ ignored_options = "profile,make,srcdir,valgrind,memcheck,massif," $ ignored_option_len = f$length(ignored_options) $! $ testname = "" $ make :== $bin:make.exe" $! $ i = 0 $param_loop: $ param = f$element(i, ",", params) $ i = i + 1 $ if param .eqs. "" then goto param_loop $ if param .eqs. "," then goto param_loop_end $ param_len = f$length(param) $ if f$locate("/", param) .lt. param_len $ then $ if testname .nes. "" $ then $ write sys$output "Only the last test name specified will be run!" $ endif $ testname = param $ goto param_loop $ endif $ lc_param = f$edit(param,"LOWERCASE") - "-" $ if f$locate(",''lc_param',", ignored_options) .lt. ignored_option_len $ then $ write sys$output "parameter ''param' is ignored on VMS for now." $ goto param_loop $ endif $ if f$locate(",''lc_param',", test_flags) .lt. test_flags_len $ then $ 'lc_param'_flag = "-" + lc_param $ goto param_loop $ endif $ write sys$output "parameter ''param' is not known to VMS." $ goto param_loop $! $param_loop_end: $! $no_gnv = 1 $no_perl = 1 $! $! Find GNV 2.1.3 + manditory updates $! If properly updated, the GNV$GNU logical name is present. $! Updated GNV utilities have a gnv$ prefix on them. $ gnv_root = f$trnlnm("GNV$GNU", "LNM$SYSTEM_TABLE") $ if gnv_root .nes. "" $ then $ no_gnv = 0 $ ! Check for update ar utility. $ new_ar = "gnv$gnu:[usr.bin]gnv$ar.exe" $ if f$search(new_ar) .nes. "" $ then $ ! See if a new port of ar exists. $ ar :== $'new_ar' $ else $ ! Fall back to legacy GNV AR wrapper. $ old_ar = "gnv$gnu:[bin]ar.exe" $ if f$search(old_ar) .nes. "" $ then $ ar :== $'old_ar' $ else $ no_gnv = 1 $ endif $ endif $ ! Check for updated bash $ if no_gnv .eq. 0 $ then $ new_bash = "gnv$gnu:[bin]gnv$bash.exe" $ if f$search(new_bash) .nes. "" $ then $ bash :== $'new_bash' $ sh :== $'new_bash' $ else $ no_gnv = 1 $ endif $ endif $ ! Check for updated coreutils $ if no_gnv .eq. 0 $ then $ new_cat = "gnv$gnu:[bin]gnv$cat.exe" $ if f$search(new_cat) .nes. "" $ then $ cat :== $'new_cat' $ cp :== $gnv$gnu:[bin]gnv$cp.exe $ echo :== $gnv$gnu:[bin]gnv$echo.exe $ false :== $gnv$gnu:[bin]gnv$false.exe $ true :== $gnv$gnu:[bin]gnv$true.exe $ touch :== $gnv$gnu:[bin]gnv$touch.exe $ mkdir :== $gnv$gnu:[bin]gnv$mkdir.exe $ rm :== $gnv$gnu:[bin]gnv$rm.exe $ sleep :== $gnv$gnu:[bin]gnv$sleep.exe $ else $ no_gnv = 1 $ endif $ endif $ ! Check for updated diff utility. $ if no_gnv .eq. 0 $ then $ new_diff = "gnv$gnu:[usr.bin]gnv$diff.exe" $ if f$search(new_diff) .nes. "" $ then $ ! See if a new port of diff exists. $ diff :== $'new_diff' $ else $ ! Fall back to legacy GNV diff $ old_diff = "gnv$gnu:[bin]diff.exe" $ if f$search(old_diff) .nes. "" $ then $ diff :== $'old_diff' $ else $ no_gnv = 1 $ endif $ endif $ endif $ endif $! $if no_gnv $then $ write sys$output "Could not find an up to date GNV installed!" $ help_flag = 1 $endif $! $! Find perl 5.18.1 or later. $! $! look in perl_root:[000000]perl_setup.com $ perl_root = f$trnlnm("perl_root") $ ! This works with known perl installed from PCSI kits. $ if perl_root .nes. "" $ then $ perl_ver = f$element(1, ".", perl_root) $ if f$locate("-", perl_ver) .lt. f$length(perl_ver) $ then $ no_perl = 0 $ endif $ endif $ if no_perl $ then $! look for sys$common:[perl-*]perl_setup.com $ perl_setup = f$search("sys$common:[perl-*]perl_setup.com") $ if perl_setup .eqs. "" $ then $ if gnv_root .nes. "" $ then $ gnv_device = f$parse(gnv_root,,,"DEVICE") $ perl_templ = "[vms$common.perl-*]perl_setup.com" $ perl_search = f$parse(perl_templ, gnv_device) $ perl_setup = f$search(perl_search) $ endif $ endif $ if perl_setup .nes. "" $ then $ @'perl_setup' $ no_perl = 0 $ endif $ endif $! $ if no_perl $ then $ write sys$output "Could not find an up to date Perl installed!" $ help_flag = "-help" $ endif $! $! $ if help_flag .nes. "" $ then $ type sys$input $DECK This is a test script wrapper for the run_make_tests.pl script. This wrapper makes sure that the DCL symbols and logical names needed to run the perl script are in place. The test wrapper currently requires that the DCL symbols be global symbols. Those symbols will be left behind after the procedure is run. The PERL_ROOT will be set to a compatible perl if such a perl is found and is not the default PERL_ROOT:. This setting will persist after the test. This wrapper should be run with the default set to the base directory of the make source. The HELP parameter will bring up this text and then run the help script for the Perl wrapper. Not all options for the perl script have been implemented, such as valgrind or specifying the make path or source path. Running the wrapper script requires: Perl 5.18 or later. PCSI kits available from http://sourceforge.net/projects/vmsperlkit/files/ GNV 2.1.3 or later. GNV 3.0.1 has not tested with this script. Bash 4.2.47 or later. Coreutils 8.21 or later. http://sourceforge.net/projects/gnv/files/ Read before installing: http://sourceforge.net/p/gnv/wiki/InstallingGNVPackages/ As updates for other GNV components get posted, those updates should be used. $EOD $ endif $! $ if no_gnv .or. no_perl then exit 44 $! $! $ make := $bin:make.exe $ default = f$environment("DEFAULT") $ this = f$environment("PROCEDURE") $ on error then goto all_error $ set default 'f$parse(this,,,"DEVICE")''f$parse(this,,,"DIRECTORY")' $! $! Need to make sure that the config-flags.pm exists. $ if f$search("config-flags.pm") .eqs. "" $ then $ @config_flags_pm.com $ endif $ define/user bin 'default',gnv$gnu:[bin] $ define/user decc$filename_unix_noversion enable $ define/user decc$filename_unix_report enable $ define/user decc$readdir_dropdotnotype enable $ flags = "" $ if verbose_flag .nes. "" then flags = verbose_flag $ if detail_flag .nes. "" then flags = flags + " " + detail_flag $ if keep_flag .nes. "" then flags = flags + " " + keep_flag $ if usage_flag .nes. "" then flags = flags + " " + usage_flag $ if help_flag .nes. "" then flags = flags + " " + help_flag $ if debug_flag .nes. "" then flags = flags + " " + debug_flag $ flags = f$edit(flags, "TRIM, COMPRESS") $ if testname .nes. "" $ then $ perl run_make_tests.pl "''testname'" 'flags' $ else $ perl run_make_tests.pl 'flags' $ endif $all_error: $ set default 'default' $! remake-4.1+dbg1.3~dfsg.1/tests/run_make_tests.pl000066400000000000000000000326351317072305000215260ustar00rootroot00000000000000#!/usr/bin/env perl # -*-perl-*- # Test driver for the Make test suite # Usage: run_make_tests [testname] # [-debug] # [-help] # [-verbose] # [-keep] # [-make ] # (and others) # Copyright (C) 1992-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . %FEATURES = (); $valgrind = 0; # invoke make with valgrind $valgrind_args = ''; $memcheck_args = '--num-callers=15 --tool=memcheck --leak-check=full --suppressions=guile.supp'; $massif_args = '--num-callers=15 --tool=massif --alloc-fn=xmalloc --alloc-fn=xcalloc --alloc-fn=xrealloc --alloc-fn=xstrdup --alloc-fn=xstrndup'; $pure_log = undef; # The location of the GNU make source directory $srcdir = ''; $command_string = ''; $all_tests = 0; # rmdir broken in some Perls on VMS. if ($^O eq 'VMS') { require VMS::Filespec; VMS::Filespec->import(); sub vms_rmdir { my $vms_file = vmspath($_[0]); $vms_file = fileify($vms_file); my $ret = unlink(vmsify($vms_file)); return $ret }; *CORE::GLOBAL::rmdir = \&vms_rmdir; } require "test_driver.pl"; require "config-flags.pm"; # Some target systems might not have the POSIX module... $has_POSIX = eval { require "POSIX.pm" }; #$SIG{INT} = sub { print STDERR "Caught a signal!\n"; die @_; }; sub valid_option { local($option) = @_; if ($option =~ /^-make([-_]?path)?$/i) { $make_path = shift @argv; if (!-f $make_path) { print "$option $make_path: Not found.\n"; exit 0; } return 1; } if ($option =~ /^-srcdir$/i) { $srcdir = shift @argv; if (! -f "$srcdir/gnumake.h") { print "$option $srcdir: Not a valid GNU make source directory.\n"; exit 0; } return 1; } if ($option =~ /^-all([-_]?tests)?$/i) { $all_tests = 1; return 1; } if ($option =~ /^-(valgrind|memcheck)$/i) { $valgrind = 1; $valgrind_args = $memcheck_args; return 1; } if ($option =~ /^-massif$/i) { $valgrind = 1; $valgrind_args = $massif_args; return 1; } # This doesn't work--it _should_! Someone badly needs to fix this. # # elsif ($option =~ /^-work([-_]?dir)?$/) # { # $workdir = shift @argv; # return 1; # } return 0; } # This is an "all-in-one" function. Arguments are as follows: # # [0] (string): The makefile to be tested. undef means use the last one. # [1] (string): Arguments to pass to make. # [2] (string): Answer we should get back. # [3] (integer): Exit code we expect. A missing code means 0 (success) $old_makefile = undef; sub subst_make_string { local $_ = shift; $makefile and s/#MAKEFILE#/$makefile/g; s/#MAKEPATH#/$mkpath/g; s/#MAKE#/$make_name/g; s/#PERL#/$perl_name/g; s/#PWD#/$pwd/g; return $_; } sub run_make_test { local ($makestring, $options, $answer, $err_code, $timeout) = @_; # If the user specified a makefile string, create a new makefile to contain # it. If the first value is not defined, use the last one (if there is # one). if (! defined $makestring) { defined $old_makefile || die "run_make_test(undef) invoked before run_make_test('...')\n"; $makefile = $old_makefile; } else { if (! defined($makefile)) { $makefile = &get_tmpfile(); } # Make sure it ends in a newline and substitute any special tokens. $makestring && $makestring !~ /\n$/s and $makestring .= "\n"; $makestring = subst_make_string($makestring); # Populate the makefile! open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n"; print MAKEFILE $makestring; close(MAKEFILE) || die "Failed to write $makefile: $!\n"; } # Do the same processing on $answer as we did on $makestring. if (defined $answer) { $answer && $answer !~ /\n$/s and $answer .= "\n"; $answer = subst_make_string($answer); } run_make_with_options($makefile, $options, &get_logfile(0), $err_code, $timeout); &compare_output($answer, &get_logfile(1)); $old_makefile = $makefile; $makefile = undef; } # The old-fashioned way... sub run_make_with_options { local ($filename,$options,$logname,$expected_code,$timeout) = @_; local($code); local($command) = $make_path; $expected_code = 0 unless defined($expected_code); # Reset to reflect this one test. $test_passed = 1; if ($filename) { $command .= " -f $filename"; } if ($options) { if ($^O eq 'VMS') { # Try to make sure arguments are properly quoted. # This does not handle all cases. # VMS uses double quotes instead of single quotes. $options =~ s/\'/\"/g; # If the leading quote is inside non-whitespace, then the # quote must be doubled, because it will be enclosed in another # set of quotes. $options =~ s/(\S)(\".*\")/$1\"$2\"/g; # Options must be quoted to preserve case if not already quoted. $options =~ s/(\S+)/\"$1\"/g; # Special fixup for embedded quotes. $options =~ s/(\"\".+)\"(\s+)\"(.+\"\")/$1$2$3/g; $options =~ s/(\A)(?:\"\")(.+)(?:\"\")/$1\"$2\"/g; # Special fixup for misc/general4 test. $options =~ s/""\@echo" "cc""/\@echo cc"/; $options =~ s/"\@echo link"""/\@echo link"/; # Remove shell escapes expected to be removed by bash if ($options !~ /path=pre/) { $options =~ s/\\//g; } # special fixup for options/eval $options =~ s/"--eval=\$\(info" "eval/"--eval=\$\(info eval/; print ("Options fixup = -$options-\n") if $debug; } $command .= " $options"; } $command_string = "$command\n"; if ($valgrind) { print VALGRIND "\n\nExecuting: $command\n"; } { my $old_timeout = $test_timeout; $timeout and $test_timeout = $timeout; # If valgrind is enabled, turn off the timeout check $valgrind and $test_timeout = 0; $code = &run_command_with_output($logname,$command); $test_timeout = $old_timeout; } # Check to see if we have Purify errors. If so, keep the logfile. # For this to work you need to build with the Purify flag -exit-status=yes if ($pure_log && -f $pure_log) { if ($code & 0x7000) { $code &= ~0x7000; # If we have a purify log, save it $tn = $pure_testname . ($num_of_logfiles ? ".$num_of_logfiles" : ""); print("Renaming purify log file to $tn\n") if $debug; rename($pure_log, "$tn") || die "Can't rename $log to $tn: $!\n"; ++$purify_errors; } else { unlink($pure_log); } } if ($code != $expected_code) { print "Error running $make_path (expected $expected_code; got $code): $command\n"; $test_passed = 0; $runf = &get_runfile; &create_file (&get_runfile, $command_string); # If it's a SIGINT, stop here if ($code & 127) { print STDERR "\nCaught signal ".($code & 127)."!\n"; ($code & 127) == 2 and exit($code); } return 0; } if ($profile & $vos) { system "add_profile $make_path"; } return 1; } sub print_usage { &print_standard_usage ("run_make_tests", "[-make MAKE_PATHNAME] [-srcdir SRCDIR] [-memcheck] [-massif]",); } sub print_help { &print_standard_help ( "-make", "\tYou may specify the pathname of the copy of make to run.", "-srcdir", "\tSpecify the make source directory.", "-valgrind", "-memcheck", "\tRun the test suite under valgrind's memcheck tool.", "\tChange the default valgrind args with the VALGRIND_ARGS env var.", "-massif", "\tRun the test suite under valgrind's massif toool.", "\tChange the default valgrind args with the VALGRIND_ARGS env var." ); } sub get_this_pwd { $delete_command = 'rm -f'; if ($has_POSIX) { $__pwd = POSIX::getcwd(); } elsif ($vos) { $delete_command = "delete_file -no_ask"; $__pwd = `++(current_dir)`; } else { # No idea... just try using pwd as a last resort. chop ($__pwd = `pwd`); } return $__pwd; } sub set_defaults { # $profile = 1; $testee = "GNU make"; $make_path = "make"; $tmpfilesuffix = "mk"; $pwd = &get_this_pwd; } sub set_more_defaults { local($string); local($index); # find the type of the port. We do this up front to have a single # point of change if it needs to be tweaked. # # This is probably not specific enough. # if ($osname =~ /Windows/i || $osname =~ /MINGW32/i || $osname =~ /CYGWIN_NT/i) { $port_type = 'W32'; } # Bleah, the osname is so variable on DOS. This kind of bites. # Well, as far as I can tell if we check for some text at the # beginning of the line with either no spaces or a single space, then # a D, then either "OS", "os", or "ev" and a space. That should # match and be pretty specific. elsif ($osname =~ /^([^ ]*|[^ ]* [^ ]*)D(OS|os|ev) /) { $port_type = 'DOS'; } # Check for OS/2 elsif ($osname =~ m%OS/2%) { $port_type = 'OS/2'; } # Everything else, right now, is UNIX. Note that we should integrate # the VOS support into this as well and get rid of $vos; we'll do # that next time. else { $port_type = 'UNIX'; } # On DOS/Windows system the filesystem apparently can't track # timestamps with second granularity (!!). Change the sleep time # needed to force a file to be considered "old". $wtime = $port_type eq 'UNIX' ? 1 : $port_type eq 'OS/2' ? 2 : 4; print "Port type: $port_type\n" if $debug; print "Make path: $make_path\n" if $debug; # Find the full pathname of Make. For DOS systems this is more # complicated, so we ask make itself. if ($osname eq 'VMS') { # On VMS pre-setup make to be found with simply 'make'. $make_path = 'make'; } else { my $mk = `sh -c 'echo "all:;\@echo \\\$(MAKE)" | $make_path -f-'`; chop $mk; $mk or die "FATAL ERROR: Cannot determine the value of \$(MAKE):\n 'echo \"all:;\@echo \\\$(MAKE)\" | $make_path -f-' failed!\n"; $make_path = $mk; } print "Make\t= '$make_path'\n" if $debug; my $redir2 = '2> /dev/null'; $redir2 = '' if os_name eq 'VMS'; $string = `$make_path -v -f /dev/null $redir2`; $string =~ /^(GNU Make [^,\n]*)/; $testee_version = "$1\n"; my $redir = '2>&1'; $redir = '' if os_name eq 'VMS'; $string = `sh -c "$make_path -f /dev/null $redir"`; if ($string =~ /(.*): \*\*\* No targets\. Stop\./) { $make_name = $1; } else { $make_path =~ /^(?:.*$pathsep)?(.+)$/; $make_name = $1; } # prepend pwd if this is a relative path (ie, does not # start with a slash, but contains one). Thanks for the # clue, Roland. if (index ($make_path, ":") != 1 && index ($make_path, "/") > 0) { $mkpath = "$pwd$pathsep$make_path"; } else { $mkpath = $make_path; } # If srcdir wasn't provided on the command line, see if the # location of the make program gives us a clue. Don't fail if not; # we'll assume it's been installed into /usr/include or wherever. if (! $srcdir) { $make_path =~ /^(.*$pathsep)?/; my $d = $1 || '../'; -f "${d}gnumake.h" and $srcdir = $d; } # Not with the make program, so see if we can get it out of the makefile if (! $srcdir && open(MF, "< ../Makefile")) { local $/ = undef; $_ = ; close(MF); /^abs_srcdir\s*=\s*(.*?)\s*$/m; -f "$1/gnumake.h" and $srcdir = $1; } # Get Purify log info--if any. if (exists $ENV{PURIFYOPTIONS} && $ENV{PURIFYOPTIONS} =~ /.*-logfile=([^ ]+)/) { $pure_log = $1 || ''; $pure_log =~ s/%v/$make_name/; $purify_errors = 0; } $string = `sh -c "$make_path -j 2 -f /dev/null $redir"`; if ($string =~ /not supported/) { $parallel_jobs = 0; } else { $parallel_jobs = 1; } %FEATURES = map { $_ => 1 } split /\s+/, `sh -c "echo '\\\$(info \\\$(.FEATURES))' | $make_path -f- 2>/dev/null"`; # Set up for valgrind, if requested. if ($valgrind) { my $args = $valgrind_args; open(VALGRIND, "> valgrind.out") || die "Cannot open valgrind.out: $!\n"; # -q --leak-check=yes exists $ENV{VALGRIND_ARGS} and $args = $ENV{VALGRIND_ARGS}; $make_path = "valgrind --log-fd=".fileno(VALGRIND)." $args $make_path"; # F_SETFD is 2 fcntl(VALGRIND, 2, 0) or die "fcntl(setfd) failed: $!\n"; system("echo Starting on `date` 1>&".fileno(VALGRIND)); print "Enabled valgrind support.\n"; } } sub setup_for_test { $makefile = &get_tmpfile; if (-f $makefile) { unlink $makefile; } # Get rid of any Purify logs. if ($pure_log) { ($pure_testname = $testname) =~ tr,/,_,; $pure_testname = "$pure_log.$pure_testname"; system("rm -f $pure_testname*"); print("Purify testfiles are: $pure_testname*\n") if $debug; } } exit !&toplevel; remake-4.1+dbg1.3~dfsg.1/tests/scripts/000077500000000000000000000000001317072305000176245ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/000077500000000000000000000000001317072305000214425ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/archives000066400000000000000000000053101317072305000231700ustar00rootroot00000000000000# -*-mode: perl-*- $description = "Test GNU make's archive management features."; # Rocky: skip for now $details = "\ FIXME: reinstate. Determinism in Linux kernels changes this."; return -1; $details = "\ This only works on systems that support it."; # If this instance of make doesn't support archives, skip it exists $FEATURES{archives} or return -1; # Create some .o files to work with utouch(-60, qw(a1.o a2.o a3.o)); my $ar = $CONFIG_FLAGS{AR}; # Some versions of ar print different things on creation. Find out. my $created = `$ar rv libxx.a a1.o 2>&1`; # Some versions of ar print different things on add. Find out. my $add = `$ar rv libxx.a a2.o 2>&1`; $add =~ s/a2\.o/#OBJECT#/g; # Some versions of ar print different things on replacement. Find out. my $repl = `$ar rv libxx.a a2.o 2>&1`; $repl =~ s/a2\.o/#OBJECT#/g; unlink('libxx.a'); # Very simple run_make_test('all: libxx.a(a1.o)', '', "$ar rvU libxx.a a1.o\n$created"); # Multiple .o's. Add a new one to the existing library ($_ = $add) =~ s/#OBJECT#/a2.o/g; run_make_test('all: libxx.a(a1.o a2.o)', '', "$ar rvU libxx.a a2.o\n$_"); # Touch one of the .o's so it's rebuilt utouch(-40, 'a1.o'); ($_ = $repl) =~ s/#OBJECT#/a1.o/g; run_make_test(undef, '', "$ar rvU libxx.a a1.o\n$_"); # Use wildcards run_make_test('all: libxx.a(*.o)', '', "#MAKE#: Nothing to be done for 'all'.\n"); # Touch one of the .o's so it's rebuilt utouch(-30, 'a1.o'); ($_ = $repl) =~ s/#OBJECT#/a1.o/g; run_make_test(undef, '', "$ar rvU libxx.a a1.o\n$_"); # Use both wildcards and simple names utouch(-50, 'a2.o'); ($_ = $add) =~ s/#OBJECT#/a3.o/g; $_ .= "$ar rvU libxx.a a2.o\n"; ($_ .= $repl) =~ s/#OBJECT#/a2.o/g; run_make_test('all: libxx.a(a3.o *.o)', '', "$ar rvU libxx.a a3.o\n$_"); # Check whitespace handling utouch(-40, 'a2.o'); ($_ = $repl) =~ s/#OBJECT#/a2.o/g; run_make_test('all: libxx.a( a3.o *.o )', '', "$ar rvU libxx.a a2.o\n$_"); rmfiles(qw(a1.o a2.o a3.o libxx.a)); # Check non-archive targets # See Savannah bug #37878 run_make_test(q! all: foo(bar).baz foo(bar).baz: ; @echo '$@' !, '', "foo(bar).baz\n"); # Check renaming of archive targets. # See Savannah bug #38442 mkdir('artest', 0777); touch('foo.vhd'); run_make_test(q! DIR = artest vpath % $(DIR) default: lib(foo) (%): %.vhd ; @cd $(DIR) && touch $(*F) && $(AR) $(ARFLAGS) $@ $(*F) >/dev/null 2>&1 && rm $(*F) .PHONY: default !, '', ""); run_make_test(undef, '', "#MAKE#: Nothing to be done for 'default'.\n"); unlink('foo.vhd'); remove_directory_tree('artest'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/comments000066400000000000000000000023431317072305000232140ustar00rootroot00000000000000$description = "The following test creates a makefile to test comments\n" ."and comment continuation to the next line using a \n" ."backslash within makefiles."; $details = "To test comments within a makefile, a semi-colon was placed \n" ."after a comment was started. This should not be reported as\n" ."an error since it is within a comment. We then continue the \n" ."comment to the next line using a backslash. To test whether\n" ."the comment really continued, we place an echo command with some\n" ."text on the line which should never execute since it should be \n" ."within a comment\n"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<\EOF; # Test comment vs semicolon parsing and line continuation target: # this ; is just a comment \ @echo This is within a comment. @echo There should be no errors for this makefile. EOF # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile); # Create the answer to what should be produced by this Makefile $answer = "There should be no errors for this makefile.\n"; # COMPARE RESULTS &compare_output($answer,&get_logfile(1)) remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/conditionals000066400000000000000000000044151317072305000240570ustar00rootroot00000000000000# -*-perl-*- $description = "Check GNU make conditionals."; $details = "Attempt various different flavors of GNU make conditionals."; run_make_test(' arg1 = first arg2 = second arg3 = third arg4 = cc arg5 = second all: ifeq ($(arg1),$(arg2)) @echo arg1 equals arg2 else @echo arg1 NOT equal arg2 endif ifeq \'$(arg2)\' "$(arg5)" @echo arg2 equals arg5 else @echo arg2 NOT equal arg5 endif ifneq \'$(arg3)\' \'$(arg4)\' @echo arg3 NOT equal arg4 else @echo arg3 equal arg4 endif ifndef undefined @echo variable is undefined else @echo variable undefined is defined endif ifdef arg4 @echo arg4 is defined else @echo arg4 is NOT defined endif', '', 'arg1 NOT equal arg2 arg2 equals arg5 arg3 NOT equal arg4 variable is undefined arg4 is defined'); # Test expansion of variables inside ifdef. run_make_test(' foo = 1 FOO = foo F = f DEF = no DEF2 = no ifdef $(FOO) DEF = yes endif ifdef $(F)oo DEF2 = yes endif DEF3 = no FUNC = $1 ifdef $(call FUNC,DEF)3 DEF3 = yes endif all:; @echo DEF=$(DEF) DEF2=$(DEF2) DEF3=$(DEF3)', '', 'DEF=yes DEF2=yes DEF3=yes'); # Test all the different "else if..." constructs run_make_test(' arg1 = first arg2 = second arg3 = third arg4 = cc arg5 = fifth result = ifeq ($(arg1),$(arg2)) result += arg1 equals arg2 else ifeq \'$(arg2)\' "$(arg5)" result += arg2 equals arg5 else ifneq \'$(arg3)\' \'$(arg3)\' result += arg3 NOT equal arg4 else ifndef arg5 result += variable is undefined else ifdef undefined result += arg4 is defined else result += success endif all: ; @echo $(result)', '', 'success'); # Test some random "else if..." construct nesting run_make_test(' arg1 = first arg2 = second arg3 = third arg4 = cc arg5 = second ifeq ($(arg1),$(arg2)) $(info failed 1) else ifeq \'$(arg2)\' "$(arg2)" ifdef undefined $(info failed 2) else $(info success) endif else ifneq \'$(arg3)\' \'$(arg3)\' $(info failed 3) else ifdef arg5 $(info failed 4) else ifdef undefined $(info failed 5) else $(info failed 6) endif .PHONY: all all: ; @:', '', 'success'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/default_names000066400000000000000000000024471317072305000242030ustar00rootroot00000000000000# -*-perl-*- $description = "This script tests to make sure that Make looks for default makefiles in the correct order (GNUmakefile,makefile,Makefile)"; # Create a makefile called "GNUmakefile" $makefile = "GNUmakefile"; open(MAKEFILE,"> $makefile"); print MAKEFILE "FIRST: ; \@echo It chose GNUmakefile\n"; close(MAKEFILE); # Create another makefile called "makefile" open(MAKEFILE,"> makefile"); print MAKEFILE "SECOND: ; \@echo It chose makefile\n"; close(MAKEFILE); # DOS/WIN32/MacOSX platforms are case-insensitive / case-preserving, so # Makefile is the same file as makefile. Just test what we can here. my $case_sensitive = 0; if (! -f 'Makefile') { # Create another makefile called "Makefile" $case_sensitive = 1; open(MAKEFILE,"> Makefile"); print MAKEFILE "THIRD: ; \@echo It chose Makefile\n"; close(MAKEFILE); } run_make_with_options("","",&get_logfile); compare_output("It chose GNUmakefile\n",&get_logfile(1)); unlink($makefile); run_make_with_options("","",&get_logfile); compare_output("It chose makefile\n",&get_logfile(1)); unlink("makefile"); if ($case_sensitive) { run_make_with_options("","",&get_logfile); compare_output("It chose Makefile\n",&get_logfile(1)); unlink("Makefile"); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/double_colon000066400000000000000000000071541317072305000240400ustar00rootroot00000000000000# -*-perl-*- $description = "Test handling of double-colon rules."; $details = "\ We test these features: - Multiple commands for the same (double-colon) target - Different prerequisites for targets: only out-of-date ones are rebuilt. - Double-colon targets that aren't the goal target. Then we do the same thing for parallel builds: double-colon targets should always be built serially."; # The Contents of the MAKEFILE ... open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; all: baz foo:: f1.h ; @echo foo FIRST foo:: f2.h ; @echo foo SECOND bar:: ; @echo aaa; sleep 1; echo aaa done bar:: ; @echo bbb baz:: ; @echo aaa baz:: ; @echo bbb biz:: ; @echo aaa biz:: two ; @echo bbb two: ; @echo two f1.h f2.h: ; @echo $@ d :: ; @echo ok d :: d ; @echo oops EOF close(MAKEFILE); # TEST 0: A simple double-colon rule that isn't the goal target. &run_make_with_options($makefile, "all", &get_logfile, 0); $answer = "aaa\nbbb\n"; &compare_output($answer, &get_logfile(1)); # TEST 1: As above, in parallel if ($parallel_jobs) { &run_make_with_options($makefile, "-j10 all", &get_logfile, 0); $answer = "aaa\nbbb\n"; &compare_output($answer, &get_logfile(1)); } # TEST 2: A simple double-colon rule that is the goal target &run_make_with_options($makefile, "bar", &get_logfile, 0); $answer = "aaa\naaa done\nbbb\n"; &compare_output($answer, &get_logfile(1)); # TEST 3: As above, in parallel if ($parallel_jobs) { &run_make_with_options($makefile, "-j10 bar", &get_logfile, 0); $answer = "aaa\naaa done\nbbb\n"; &compare_output($answer, &get_logfile(1)); } # TEST 4: Each double-colon rule is supposed to be run individually &utouch(-5, 'f2.h'); &touch('foo'); &run_make_with_options($makefile, "foo", &get_logfile, 0); $answer = "f1.h\nfoo FIRST\n"; &compare_output($answer, &get_logfile(1)); # TEST 5: Again, in parallel. if ($parallel_jobs) { &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0); $answer = "f1.h\nfoo FIRST\n"; &compare_output($answer, &get_logfile(1)); } # TEST 6: Each double-colon rule is supposed to be run individually &utouch(-5, 'f1.h'); unlink('f2.h'); &touch('foo'); &run_make_with_options($makefile, "foo", &get_logfile, 0); $answer = "f2.h\nfoo SECOND\n"; &compare_output($answer, &get_logfile(1)); # TEST 7: Again, in parallel. if ($parallel_jobs) { &run_make_with_options($makefile, "-j10 foo", &get_logfile, 0); $answer = "f2.h\nfoo SECOND\n"; &compare_output($answer, &get_logfile(1)); } # TEST 8: Test circular dependency check; PR/1671 &run_make_with_options($makefile, "d", &get_logfile, 0); $answer = "ok\n$make_name: Circular d <- d dependency dropped.\noops\n"; &compare_output($answer, &get_logfile(1)); # TEST 8: I don't grok why this is different than the above, but it is... # # Hmm... further testing indicates this might be timing-dependent? # #if ($parallel_jobs) { # &run_make_with_options($makefile, "-j10 biz", &get_logfile, 0); # $answer = "aaa\ntwo\nbbb\n"; # &compare_output($answer, &get_logfile(1)); #} unlink('foo','f1.h','f2.h'); # TEST 9: make sure all rules in s double colon family get executed # (Savannah bug #14334). # &touch('one'); &touch('two'); run_make_test(' .PHONY: all all: result result:: one @echo $^ >>$@ @echo $^ result:: two @echo $^ >>$@ @echo $^ ', '', 'one two'); unlink('result','one','two'); # TEST 10: check for proper backslash handling # Savannah bug #33399 run_make_test(' a\ xb :: ; @echo one a\ xb :: ; @echo two ', '', "one\ntwo\n"); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/echoing000066400000000000000000000040571317072305000230070ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test command echoing. It tests that when a command line starts with a '\@', the echoing of that line is suppressed. It also tests the -n option which tells make to ONLY echo the commands and no execution happens. In this case, even the commands with '\@' are printed. Lastly, it tests the -s flag which tells make to prevent all echoing, as if all commands started with a '\@'."; $details = "This test is similar to the 'clean' test except that a '\@' has been placed in front of the delete command line. Four tests are run here. First, make is run normally and the first echo command should be executed. In this case there is no '\@' so we should expect make to display the command AND display the echoed message. Secondly, make is run with the clean target, but since there is a '\@' at the beginning of the command, we expect no output; just the deletion of a file which we check for. Third, we give the clean target again except this time we give make the -n option. We now expect the command to be displayed but not to be executed. In this case we need only to check the output since an error message would be displayed if it actually tried to run the delete command again and the file didn't exist. Lastly, we run the first test again with the -s option and check that make did not echo the echo command before printing the message.\n"; $example = "EXAMPLE_FILE"; touch($example); # TEST #1 # ------- run_make_test(" all: \techo This makefile did not clean the dir... good clean: \t\@$delete_command $example\n", '', 'echo This makefile did not clean the dir... good This makefile did not clean the dir... good'); # TEST #2 # ------- run_make_test(undef, 'clean', ''); if (-f $example) { $test_passed = 0; unlink($example); } # TEST #3 # ------- run_make_test(undef, '-n clean', "$delete_command $example\n"); # TEST #4 # ------- run_make_test(undef, '-s', "This makefile did not clean the dir... good\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/errors000066400000000000000000000057061317072305000227110ustar00rootroot00000000000000# -*-perl-*- $description = "The following tests the -i option and the '-' in front of \n" ."commands to test that make ignores errors in these commands\n" ."and continues processing."; $details = "This test runs two makes. The first runs on a target with a \n" ."command that has a '-' in front of it (and a command that is \n" ."intended to fail) and then a delete command after that is \n" ."intended to succeed. If make ignores the failure of the first\n" ."command as it is supposed to, then the second command should \n" ."delete a file and this is what we check for. The second make\n" ."that is run in this test is identical except that the make \n" ."command is given with the -i option instead of the '-' in \n" ."front of the command. They should run the same. "; if ($vos) { $rm_command = "delete_file"; } else { $rm_command = "rm"; } open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "clean:\n" ."\t-$rm_command cleanit\n" ."\t$rm_command foo\n" ."clean2: \n" ."\t$rm_command cleanit\n" ."\t$rm_command foo\n"; # END of Contents of MAKEFILE close(MAKEFILE); &touch("foo"); unlink("cleanit"); $cleanit_error = `sh -c "$rm_command cleanit 2>&1"`; chomp $cleanit_error; $delete_error_code = $? >> 8; # TEST #1 # ------- my $answer = qq{$rm_command cleanit $cleanit_error work/features/errors.mk:2: recipe for target 'clean' failed work/features/errors.mk:1: [clean] Error 1 (ignored) #0 clean at errors.mk:1 $rm_command foo }; $logfile = &get_logfile; &run_make_with_options($makefile,"",$logfile); # If make acted as planned, it should ignore the error from the first # command in the target and execute the second which deletes the file "foo" # This file, therefore, should not exist if the test PASSES. if (-f "foo") { $test_passed = 0; } # The output for this on VOS is too hard to replicate, so we only check it # on unix. if (!$vos) { $slurp = &read_file_into_string ($logfile); $slurp =~ s:^#0 clean at .*work/features/errors:#0 clean at errors:gm; $slurp =~ s:^.*work/features/errors:work/features/errors:gm; &compare_output_string($answer, $slurp, $logfile); } &touch("foo"); # TEST #2 # ------- $answer = qq{$rm_command cleanit $cleanit_error work/features/errors.mk:5: recipe for target 'clean2' failed work/features/errors.mk:4: [clean2] Error 1 (ignored) #0 clean2 at errors.mk:4 $rm_command foo }; $logfile = &get_logfile; &run_make_with_options($makefile,"clean2 -i",$logfile); if (-f "foo") { $test_passed = 0; } if (!$vos) { $slurp = &read_file_into_string ($logfile); $slurp =~ s:^#0 clean2 at .*work/features/errors:#0 clean2 at errors:gm; $slurp =~ s:^.*work/features/errors:work/features/errors:gm; &compare_output_string($answer, $slurp, $logfile); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/escape000066400000000000000000000036231317072305000226310ustar00rootroot00000000000000# -*-perl-*- $description = "Test various types of escaping in makefiles."; $details = "\ Make sure that escaping of ':' works in target names. Make sure escaping of whitespace works in target names. Make sure that escaping of '#' works. Make sure that backslash before non-special characters are kept."; # TEST 1 run_make_test(' $(path)foo : ; @echo "touch ($@)" foo\ bar: ; @echo "touch ($@)" sharp: foo\#bar.ext foo\#bar.ext: ; @echo "foo#bar.ext = ($@)"', '', 'touch (foo)'); # TEST 2: This one should fail, since the ":" is unquoted. run_make_test(undef, 'path=pre:', "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.", 512); # TEST 3: This one should work, since we escape the ":". run_make_test(undef, "'path=pre\\:'", 'touch (pre:foo)'); # TEST 4: This one should fail, since the escape char is escaped. run_make_test(undef, "'path=pre\\\\:'", "#MAKEFILE#:2: *** target pattern contains no '%'. Stop.", 512); # TEST 5: This one should work run_make_test(undef, "'foo bar'", 'touch (foo bar)'); # TEST 6: Test escaped comments run_make_test(undef, 'sharp', 'foo#bar.ext = (foo#bar.ext)'); # Test escaped colons in prerequisites # Quoting of backslashes in q!! is kind of messy. # Solaris sh does not properly handle backslashes even in '' so just # check the output make prints, not what the shell interprets. run_make_test(q! foo: foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar foo foo\\:bar foo\\\\\\:bar foo\\\\\\\\\\:bar: ; : '$@' !, '', ": 'foo:bar'\n: 'foo\\:bar'\n: 'foo\\\\:bar'\n: 'foo'\n"); # Test backslash before non-special chars: should be kept as-is run_make_test(q! all: ..\foo .DEFAULT: ; : '$@' !, '', ": '..\\foo'\n"); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/export000066400000000000000000000070601317072305000227110ustar00rootroot00000000000000# -*-perl-*- $description = "Check GNU make export/unexport commands."; $details = ""; # The test driver cleans out our environment for us so we don't have to worry # about that here. &run_make_test(' FOO = foo BAR = bar BOZ = boz export BAZ = baz export BOZ BITZ = bitz BOTZ = botz export BITZ BOTZ unexport BOTZ ifdef EXPORT_ALL export endif ifdef UNEXPORT_ALL unexport endif ifdef EXPORT_ALL_PSEUDO .EXPORT_ALL_VARIABLES: endif all: @echo "FOO=$(FOO) BAR=$(BAR) BAZ=$(BAZ) BOZ=$(BOZ) BITZ=$(BITZ) BOTZ=$(BOTZ)" @echo "FOO=$$FOO BAR=$$BAR BAZ=$$BAZ BOZ=$$BOZ BITZ=$$BITZ BOTZ=$$BOTZ" ', '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 1: make sure vars inherited from the parent are exported $extraENV{FOO} = 1; &run_make_test(undef, '', "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO=foo BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 2: global export. Explicit unexport takes precedence. run_make_test(undef, "EXPORT_ALL=1" , "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 3: global unexport. Explicit export takes precedence. &run_make_test(undef, "UNEXPORT_ALL=1", "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 4: both: in the above makefile the unexport comes last so that rules. &run_make_test(undef, "EXPORT_ALL=1 UNEXPORT_ALL=1", "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO= BAR= BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 5: test the pseudo target. &run_make_test(undef, "EXPORT_ALL_PSEUDO=1", "FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=botz FOO=foo BAR=bar BAZ=baz BOZ=boz BITZ=bitz BOTZ=\n"); # TEST 6: Test the expansion of variables inside export &run_make_test(' foo = f-ok bar = b-ok FOO = foo F = f BAR = bar B = b export $(FOO) export $(B)ar all: @echo foo=$(foo) bar=$(bar) @echo foo=$$foo bar=$$bar ', "", "foo=f-ok bar=b-ok\nfoo=f-ok bar=b-ok\n"); # TEST 7: Test the expansion of variables inside unexport &run_make_test(' foo = f-ok bar = b-ok FOO = foo F = f BAR = bar B = b export foo bar unexport $(FOO) unexport $(B)ar all: @echo foo=$(foo) bar=$(bar) @echo foo=$$foo bar=$$bar ', '', "foo=f-ok bar=b-ok\nfoo= bar=\n"); # TEST 7: Test exporting multiple variables on the same line &run_make_test(' A = a B = b C = c D = d E = e F = f G = g H = h I = i J = j SOME = A B C export F G H I J export D E $(SOME) all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J ', '', "A=a B=b C=c D=d E=e F=f G=g H=h I=i J=j\n"); # TEST 8: Test unexporting multiple variables on the same line @extraENV{qw(A B C D E F G H I J)} = qw(1 2 3 4 5 6 7 8 9 10); &run_make_test(' A = a B = b C = c D = d E = e F = f G = g H = h I = i J = j SOME = A B C unexport F G H I J unexport D E $(SOME) all: ; @echo A=$$A B=$$B C=$$C D=$$D E=$$E F=$$F G=$$G H=$$H I=$$I J=$$J ', '', "A= B= C= D= E= F= G= H= I= J=\n"); # TEST 9: Check setting a variable named "export" &run_make_test(' export = 123 export export export export = 456 a: ; @echo "\$$(export)=$(export) / \$$export=$$export" ', '', "\$(export)=456 / \$export=456\n"); # TEST 9: Check "export" as a target &run_make_test(' a: export export: ; @echo "$@" ', '', "export\n"); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/include000066400000000000000000000071741317072305000230210ustar00rootroot00000000000000# -*-mode: perl; rm-trailing-spaces: nil-*- $description = "Test various forms of the GNU make 'include' command."; $details = "\ Test include, -include, sinclude and various regressions involving them. Test extra whitespace at the end of the include, multiple -includes and sincludes (should not give an error) and make sure that errors are reported for targets that were also -included."; $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The contents of the Makefile ... print MAKEFILE < $makefile2"); print MAKEFILE "ANOTHER: ; \@echo This is another included makefile\n"; close(MAKEFILE); # Create the answer to what should be produced by this Makefile &run_make_with_options($makefile, "all", &get_logfile); $answer = "There should be no errors for this makefile.\n"; &compare_output($answer, &get_logfile(1)); &run_make_with_options($makefile, "ANOTHER", &get_logfile); $answer = "This is another included makefile\n"; &compare_output($answer, &get_logfile(1)); $makefile = undef; # Try to build the "error" target; this will fail since we don't know # how to create makeit.mk, but we should also get a message (even though # the -include suppressed it during the makefile read phase, we should # see one during the makefile run phase). run_make_test (' -include foo.mk error: foo.mk ; @echo $@ ', '', "#MAKE#: *** No rule to make target 'foo.mk', needed by 'error'. Stop.\n", 512 ); # Make sure that target-specific variables don't impact things. This could # happen because a file record is created when a target-specific variable is # set. run_make_test (' bar.mk: foo := baz -include bar.mk hello: ; @echo hello ', '', "hello\n" ); # Test inheritance of dontcare flag when rebuilding makefiles. # run_make_test(' .PHONY: all all: ; @: -include foo foo: bar; @: ', '', ''); # Make sure that we don't die when the command fails but we dontcare. # (Savannah bug #13216). # run_make_test(' .PHONY: all all:; @: -include foo foo: bar; @: bar:; @exit 1 ', '', ''); # Check include, sinclude, -include with no filenames. # (Savannah bug #1761). run_make_test(' .PHONY: all all:; @: include -include sinclude', '', ''); # Test that the diagnostics is issued even if the target has been # tried before with the dontcare flag (direct dependency case). # run_make_test(' -include foo all: bar foo: baz bar: baz ', '', "#MAKE#: *** No rule to make target 'baz', needed by 'bar'. Stop.\n", 512); # Test that the diagnostics is issued even if the target has been # tried before with the dontcare flag (indirect dependency case). # run_make_test(' -include foo all: bar foo: baz bar: baz baz: end ', '', "#MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n", 512); # Test that the diagnostics is issued even if the target has been # tried before with the dontcare flag (include/-include case). # run_make_test(' include bar -include foo all: foo: baz bar: baz baz: end ', '', "#MAKEFILE#:2: bar: No such file or directory #MAKE#: *** No rule to make target 'end', needed by 'baz'. Stop.\n", 512); if ($all_tests) { # Test that include of a rebuild-able file doesn't show a warning # Savannah bug #102 run_make_test(q! include foo foo: ; @echo foo = bar > $@ !, '', "#MAKE#: 'foo' is up to date.\n"); rmfiles('foo'); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/jobserver000066400000000000000000000032141317072305000233660ustar00rootroot00000000000000# -*-perl-*- $description = "Test jobserver."; $details = "These tests are ones that specifically are different when the jobserver feature is available. Most -j tests are the same whether or not jobserver is available, and those appear in the 'parallelism' test suite."; exists $FEATURES{'jobserver'} or return -1; if (!$parallel_jobs) { return -1; } # Don't put --jobserver-fds into a re-exec'd MAKEFLAGS. # We can't test this directly because there's no way a makefile can # show the value of MAKEFLAGS we were re-exec'd with. We can intuit it # by looking for "disabling jobserver mode" warnings; we should only # get one from the original invocation and none from the re-exec. # See Savannah bug #18124 unlink('inc.mk'); run_make_test(q! -include inc.mk recur: # @echo 'MAKEFLAGS = $(MAKEFLAGS)' @rm -f inc.mk @$(MAKE) -j2 -f #MAKEFILE# all all: # @echo 'MAKEFLAGS = $(MAKEFLAGS)' @echo $@ inc.mk: # @echo 'MAKEFLAGS = $(MAKEFLAGS)' @echo 'FOO = bar' > $@ !, '--no-print-directory -j2', "#MAKE#[1]: warning: -jN forced in submake: disabling jobserver mode.\nall\n"); unlink('inc.mk'); # Test recursion when make doesn't think it exists. # See Savannah bug #39934 # Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474 open(MAKEFILE,"> Makefile2"); print MAKEFILE ' vpath %.c ../ foo: '; close(MAKEFILE); run_make_test(q! default: ; @ #MAKEPATH# -f Makefile2 !, '-j2 --no-print-directory', "#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule. #MAKE#[1]: Nothing to be done for 'foo'."); rmfiles('Makefile2'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/load000066400000000000000000000053211317072305000223050ustar00rootroot00000000000000# -*-perl-*- $description = "Test the load operator."; $details = "Test dynamic loading of modules."; # Don't do anything if this system doesn't support "load" exists $FEATURES{load} or return -1; # First build a shared object # Provide both a default and non-default load symbol unlink(qw(testload.c testload.so)); open(my $F, '> testload.c') or die "open: testload.c: $!\n"; print $F <<'EOF' ; #include #include #include "gnumake.h" int plugin_is_GPL_compatible; int testload_gmk_setup (gmk_floc *pos) { (void)pos; gmk_eval ("TESTLOAD = implicit", 0); return 1; } int explicit_setup (gmk_floc *pos) { (void)pos; gmk_eval ("TESTLOAD = explicit", 0); return 1; } EOF close($F) or die "close: testload.c: $!\n"; # Make sure we can compile # CONFIG_FLAGS are loaded from config-flags.pm and set by configure my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testload.so testload.c"; my $clog = `$sobuild 2>&1`; if ($? != 0) { $verbose and print "Failed to build testload.so:\n$sobuild\n$_"; return -1; } # TEST 1 run_make_test(q! PRE := $(.LOADED) load testload.so POST := $(.LOADED) all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) !, '', "pre= post=testload.so implicit\n"); # TEST 2 # Load using an explicit function run_make_test(q! PRE := $(.LOADED) load ./testload.so(explicit_setup) POST := $(.LOADED) all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) !, '', "pre= post=testload.so explicit\n"); # TEST 4 # Check multiple loads run_make_test(q! PRE := $(.LOADED) load ./testload.so load testload.so(explicit_setup) POST := $(.LOADED) all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) !, '', "pre= post=testload.so implicit\n"); # TEST 5 # Check auto-rebuild of loaded file that's out of date utouch(-10, 'testload.so'); touch('testload.c'); run_make_test(q! PRE := $(.LOADED) load ./testload.so POST := $(.LOADED) all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) testload.so: testload.c ; @echo "rebuilding $@"; !.$sobuild, '', "rebuilding testload.so\npre= post=testload.so implicit\n"); # TEST 5 # Check auto-rebuild of loaded file when it doesn't exist unlink('testload.so'); run_make_test(q! PRE := $(.LOADED) -load ./testload.so(explicit_setup) POST := $(.LOADED) all: ; @echo pre=$(PRE) post=$(POST) $(TESTLOAD) %.so: %.c ; @echo "rebuilding $@"; !.$sobuild, '', "rebuilding testload.so\npre= post=testload.so explicit\n"); unlink(qw(testload.c testload.so)) unless $keep; # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/loadapi000066400000000000000000000053371317072305000230060ustar00rootroot00000000000000# -*-perl-*- $description = "Test the shared object load API."; $details = "Verify the different aspects of the shared object API."; # Don't do anything if this system doesn't support "load" exists $FEATURES{load} or return -1; # First build a shared object # Provide both a default and non-default load symbol unlink(qw(testapi.c testapi.so)); open(my $F, '> testapi.c') or die "open: testapi.c: $!\n"; print $F <<'EOF' ; #include #include #include "gnumake.h" int plugin_is_GPL_compatible; static char * test_eval (const char *buf) { gmk_eval (buf, 0); return NULL; } static char * test_expand (const char *val) { return gmk_expand (val); } static char * test_noexpand (const char *val) { char *str = gmk_alloc (strlen (val) + 1); strcpy (str, val); return str; } static char * func_test (const char *funcname, unsigned int argc, char **argv) { char *mem; if (strcmp (funcname, "test-expand") == 0) return test_expand (argv[0]); if (strcmp (funcname, "test-eval") == 0) return test_eval (argv[0]); if (strcmp (funcname, "test-noexpand") == 0) return test_noexpand (argv[0]); mem = gmk_alloc (sizeof ("unknown")); strcpy (mem, "unknown"); return mem; } int testapi_gmk_setup () { gmk_add_function ("test-expand", func_test, 1, 1, GMK_FUNC_DEFAULT); gmk_add_function ("test-noexpand", func_test, 1, 1, GMK_FUNC_NOEXPAND); gmk_add_function ("test-eval", func_test, 1, 1, GMK_FUNC_DEFAULT); gmk_add_function ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.", func_test, 0, 0, 0); return 1; } EOF close($F) or die "close: testapi.c: $!\n"; my $sobuild = "$CONFIG_FLAGS{CC} ".($srcdir? "-I$srcdir":'')." $CONFIG_FLAGS{CPPFLAGS} $CONFIG_FLAGS{CFLAGS} -shared -fPIC $CONFIG_FLAGS{LDFLAGS} -o testapi.so testapi.c"; my $clog = `$sobuild 2>&1`; if ($? != 0) { $verbose and print "Failed to build testapi.so:\n$sobuild\n$_"; return -1; } # TEST 1 # Check the gmk_expand() function run_make_test(q! EXPAND = expansion all: ; @echo $(test-expand $$(EXPAND)) load testapi.so !, '', "expansion\n"); # TEST 2 # Check the eval operation. Prove that the argument is expanded only once run_make_test(q! load testapi.so TEST = bye ASSIGN = VAR = $(TEST) $(shell echo there) $(test-eval $(value ASSIGN)) TEST = hi all:;@echo '$(VAR)' !, '', "hi there\n"); # TEST 2 # Check the no-expand capability run_make_test(q! load testapi.so TEST = hi all:;@echo '$(test-noexpand $(TEST))' !, '', "\$(TEST)\n"); unlink(qw(testapi.c testapi.so)) unless $keep; # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/mult_rules000066400000000000000000000033531317072305000235640ustar00rootroot00000000000000$description = "\ The following test creates a makefile to test the presence of multiple rules for one target. One file can be the target of several rules if at most one rule has commands; the other rules can only have dependencies."; $details = "\ The makefile created in this test contains two hardcoded rules for foo.o and bar.o. It then gives another multiple target rule with the same names as above but adding more dependencies. Additionally, another variable extradeps is listed as a dependency but is defined to be null. It can however be defined on the make command line as extradeps=extra.h which adds yet another dependency to the targets."; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE < $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "bigoutput littleoutput: test.h\n"; print MAKEFILE "\t\@echo I am \$(subst output,,\$@)\n"; # END of Contents of MAKEFILE close(MAKEFILE); &touch("test.h"); &run_make_with_options($makefile,"bigoutput",&get_logfile); # Create the answer to what should be produced by this Makefile $answer = "I am big\n"; &compare_output($answer,&get_logfile(1)); &run_make_with_options($makefile,"littleoutput",&get_logfile); $answer = "I am little\n"; &compare_output($answer,&get_logfile(1)); unlink "test.h"; 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/order_only000066400000000000000000000043351317072305000235460ustar00rootroot00000000000000# -*-perl-*- $description = "Test order-only prerequisites."; $details = "\ Create makefiles with various combinations of normal and order-only prerequisites and ensure they behave properly. Test the \$| variable."; # TEST #0 -- Basics run_make_test(' %r: | baz ; @echo $< $^ $| bar: foo foo:;@: baz:;@:', '', "foo foo baz\n"); # TEST #1 -- First try: the order-only prereqs need to be built. run_make_test(q! foo: bar | baz @echo '$$^ = $^' @echo '$$| = $|' touch $@ .PHONY: baz bar baz: touch $@!, '', "touch bar\ntouch baz\n\$^ = bar\n\$| = baz\ntouch foo\n"); # TEST #2 -- now we do it again: baz is PHONY but foo should _NOT_ be updated run_make_test(undef, '', "touch baz\n"); unlink(qw(foo bar baz)); # TEST #3 -- Make sure the order-only prereq was promoted to normal. run_make_test(q! foo: bar | baz @echo '$$^ = $^' @echo '$$| = $|' touch $@ foo: baz .PHONY: baz bar baz: touch $@!, '', "touch bar\ntouch baz\n\$^ = bar baz\n\$| = \ntouch foo\n"); # TEST #4 -- now we do it again run_make_test(undef, '', "touch baz\n\$^ = bar baz\n\$| = \ntouch foo\n"); unlink(qw(foo bar baz)); # Test empty normal prereqs # TEST #5 -- make sure the parser was correct. run_make_test(q! foo:| baz @echo '$$^ = $^' @echo '$$| = $|' touch $@ .PHONY: baz baz: touch $@!, '', "touch baz\n\$^ = \n\$| = baz\ntouch foo\n"); # TEST #6 -- now we do it again: this time foo won't be built run_make_test(undef, '', "touch baz\n"); unlink(qw(foo baz)); # Test order-only in pattern rules # TEST #7 -- make sure the parser was correct. run_make_test(q! %.w : %.x | baz @echo '$$^ = $^' @echo '$$| = $|' touch $@ all: foo.w .PHONY: baz foo.x baz: touch $@!, '', "touch foo.x\ntouch baz\n\$^ = foo.x\n\$| = baz\ntouch foo.w\n"); # TEST #8 -- now we do it again: this time foo.w won't be built run_make_test(undef, '', "touch baz\n"); unlink(qw(foo.w foo.x baz)); # TEST #9 -- make sure that $< is set correctly in the face of order-only # prerequisites in pattern rules. run_make_test(' %r: | baz ; @echo $< $^ $| bar: foo foo:;@: baz:;@:', '', "foo foo baz\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/output-sync000066400000000000000000000214271317072305000237050ustar00rootroot00000000000000# -*-perl-*- $description = "Test --output-sync (-O) option."; $details = "Test the synchronization of output from parallel jobs."; # If we don't have output sync support, never mind. exists $FEATURES{'output-sync'} or return -1; # Output sync can't be tested without parallelization $parallel_jobs or return -1; if ($vos) { $sleep_command = "sleep -seconds"; } else { $sleep_command = "sleep"; } # The following subdirectories with Makefiles are used in several # of the following tests. The model is: # foo/Makefile - has a "foo" target that waits for the bar target # bar/Makefile - has a "bar" target that runs immediately # - has a "baz" target that waits for the foo target # # So, you start the two sub-makes in parallel and first the "bar" target is # built, followed by "foo", followed by "baz". The trick is that first each # target prints a "start" statement, then waits (if appropriate), then prints # an end statement. Thus we can tell if the -O flag is working, since # otherwise these statements would be mixed together. @syncfiles = (); sub output_sync_clean { rmfiles('foo/Makefile', 'bar/Makefile', @syncfiles); rmdir('foo'); rmdir('bar'); } # We synchronize the different jobs by having them wait for a sentinel file to # be created, instead of relying on a certain amount of time passing. # Unfortunately in this test we have to sleep after we see the sync file, # since we also want to make the obtaining of the write synchronization lock # reliable. If things are too fast, then sometimes a different job will steal # the output sync lock and the output is mis-ordered from what we expect. sub output_sync_wait { return "while [ ! -f ../mksync.$_[0] ]; do :; done; rm -f ../mksync.$_[0].wait; $sleep_command 1"; } sub output_sync_set { return "date > ../mksync.$_[0]"; } @syncfiles = qw(mksync.foo mksync.foo_start mksync.bar mksync.bar_start); output_sync_clean(); mkdir('foo', 0777); mkdir('bar', 0777); $set_foo = output_sync_set('foo'); $set_bar = output_sync_set('bar'); $set_foo_start = output_sync_set('foo_start'); $set_bar_start = output_sync_set('bar_start'); $wait_foo = output_sync_wait('foo'); $wait_bar = output_sync_wait('bar'); $wait_foo_start = output_sync_set('foo_start'); $wait_bar_start = output_sync_set('bar_start'); open(MAKEFILE,"> foo/Makefile"); print MAKEFILE < bar/Makefile"); print MAKEFILE <&2) !, '-w -Oline', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n"); # Ensure that output generated while parsing makefiles is synced # when appropriate. run_make_test(q! $(shell echo foo 1>&2) all: ; echo bar !, '-s -w -Otarget', "#MAKE#: Entering directory '#PWD#'\nfoo\n#MAKE#: Leaving directory '#PWD#'\n#MAKE#: Entering directory '#PWD#'\nbar\n#MAKE#: Leaving directory '#PWD#'\n"); # Test recursion $m1 = get_tmpfile(); $m2 = get_tmpfile(); open(M1, "> $m1"); print M1 <<'EOF'; $(shell echo d1 stderr 1>&2) $(info d1 stdout) all:; @: EOF close(M1); open(M2, "> $m2"); print M2 <<'EOF'; $(shell echo d2 stderr 1>&2) $(info d2 stdout) all:; @: # Force an ordering on the output $(shell sleep 1) EOF close(M2); run_make_test(qq! all: t1 t2 t1: ; \@\$(MAKE) -f $m1 t2: ; \@\$(MAKE) -f $m2 !, "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKE#[1]: Entering directory '#PWD#'\nd2 stderr\nd2 stdout\n#MAKE#[1]: Leaving directory '#PWD#'\n"); rmfiles($m1, $m2); # Ensure that output generated while parsing makefiles is synced # when appropriate. $m1 = get_tmpfile(); open(M1, "> $m1"); print M1 <<'EOF'; $(shell echo d1 stderr 1>&2) $(info d1 stdout) $(error d1 failed) all:; @: EOF close(M1); run_make_test(qq! all: t1 t1: ; -\@\$(MAKE) -f $m1 !, "-j -Oline", "#MAKE#[1]: Entering directory '#PWD#'\nd1 stderr\nd1 stdout\n$m1:3: *** d1 failed. Stop.\n#MAKE#[1]: Leaving directory '#PWD#'\n#MAKEFILE#:3: recipe for target 't1' failed\n#MAKE#: directory '#PWD#'\n#MAKE#: [t1] Error 2 (ignored)\n"); rmfiles($m1); # Test $(error ...) functions in recipes run_make_test(q! foo: $(OBJS) ; echo $(or $(filter %.o,$^),$(error fail)) !, '-O', "#MAKEFILE#:2: *** fail. Stop.\n", 512); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/override000066400000000000000000000015511317072305000232060ustar00rootroot00000000000000# -*-perl-*- $description = "Test the override directive on variable assignments."; $details = ""; # TEST 0: Basic override run_make_test(' X = start override recur = $(X) override simple := $(X) X = end all: ; @echo "$(recur) $(simple)" ', 'recur=I simple=J', "end start\n"); # TEST 1: Override with append run_make_test(' X += X1 override X += X2 override Y += Y1 Y += Y2 all: ; @echo "$(X) $(Y)" ', '', "X1 X2 Y1\n"); # TEST 2: Override with append to the command line run_make_test(undef, 'X=C Y=C', "C X2 C Y1\n"); # Test override of define/endef run_make_test(' override define foo @echo First comes the definition. @echo Then comes the override. endef all: ; $(foo) ', 'foo=Hello', "First comes the definition.\nThen comes the override.\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/parallelism000066400000000000000000000136741317072305000237050ustar00rootroot00000000000000# -*-perl-*- $description = "Test parallelism (-j) option."; $details = "This test creates a makefile with two double-colon default rules. The first rule has a series of sleep and echo commands intended to run in series. The second and third have just an echo statement. When make is called in this test, it is given the -j option with a value of 4. This tells make that it may start up to four jobs simultaneously. In this case, since the first command is a sleep command, the output of the second and third commands will appear before the first if indeed make is running all of these commands in parallel."; if (!$parallel_jobs) { return -1; } if ($vos) { $sleep_command = "sleep -seconds"; } else { $sleep_command = "sleep"; } run_make_test(" all : def_1 def_2 def_3 def_1 : ; \@echo ONE; $sleep_command 3 ; echo TWO def_2 : ; \@$sleep_command 2 ; echo THREE def_3 : ; \@$sleep_command 1 ; echo FOUR", '-j4', "ONE\nFOUR\nTHREE\nTWO"); # Test parallelism with included files. Here we sleep/echo while # building the included files, to test that they are being built in # parallel. run_make_test(" all: 1 2; \@echo success -include 1.inc 2.inc 1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@ 2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@", "-j4", "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7); rmfiles(qw(1.inc 2.inc)); # Test parallelism with included files--this time recurse first and make # sure the jobserver works. run_make_test(" recurse: ; \@\$(MAKE) --no-print-directory -f #MAKEFILE# INC=yes all all: 1 2; \@echo success INC = no ifeq (\$(INC),yes) -include 1.inc 2.inc endif 1.inc: ; \@echo ONE.inc; $sleep_command 2; echo TWO.inc; echo '1: ; \@echo ONE; $sleep_command 2; echo TWO' > \$\@ 2.inc: ; \@$sleep_command 1; echo THREE.inc; echo '2: ; \@$sleep_command 1; echo THREE' > \$\@", "-j4", "ONE.inc\nTHREE.inc\nTWO.inc\nONE\nTHREE\nTWO\nsuccess\n", 0, 7); rmfiles(qw(1.inc 2.inc)); # Grant Taylor reports a problem where tokens can be lost (not written back # to the pipe when they should be): this happened when there is a $(shell ...) # function in an exported recursive variable. I added some code to check # for this situation and print a message if it occurred. This test used # to trigger this code when I added it but no longer does after the fix. # We have to increase the timeout from the default (5s) on this test. run_make_test(" export HI = \$(shell \$(\$\@.CMD)) first.CMD = echo hi second.CMD = $sleep_command 4; echo hi .PHONY: all first second all: first second first second: ; \@echo \$\@; $sleep_command 1; echo \$\@", '-j2', "first\nfirst\nsecond\nsecond", 0, 7); # Michael Matz reported a bug where if make is running in # parallel without -k and two jobs die in a row, but not too close to each # other, then make will quit without waiting for the rest of the jobs to die. run_make_test(" .PHONY: all fail.1 fail.2 fail.3 ok all: fail.1 ok fail.2 fail.3 fail.1 fail.2 fail.3: \@$sleep_command \$(patsubst fail.%,%,\$\@) \@echo Fail \@exit 1 ok: \@$sleep_command 4 \@echo Ok done", '-rR -j5', "Fail #MAKEFILE#:6: recipe for target 'fail.1' failed #MAKE#: directory '#PWD#' #MAKE#: *** [fail.1] Error 1 #MAKE#: *** Waiting for unfinished jobs.... Fail #MAKEFILE#:6: recipe for target 'fail.2' failed #MAKE#: directory '#PWD#' #MAKE#: *** [fail.2] Error 1 Fail #MAKEFILE#:6: recipe for target 'fail.3' failed #MAKE#: directory '#PWD#' #MAKE#: *** [fail.3] Error 1 Ok done", 512); # Test for Savannah bug #15641. # run_make_test(' .PHONY: all all:; @: -include foo.d foo.d: comp @echo building $@ comp: mod_a.o mod_b.o; @: mod_a.o mod_b.o: @exit 1 ', '-j2', ''); # TEST #9 -- Savannah bugs 3330 and 15919 # In earlier versions of make this will either give the wrong answer, or hang. utouch(-10, 'target'); run_make_test('target: intermed ; touch $@ .INTERMEDIATE: intermed intermed: | phony ; touch $@ .PHONY: phony phony: ; : phony', '-rR -j', ': phony'); rmfiles('target'); # TEST #11: Make sure -jN from MAKEFLAGS is processed even when we re-exec # See Savannah bug #33873 $extraENV{MAKEFLAGS} = '-j4'; run_make_test(q! things = thing1 thing2 all: $(things) thing1:; @sleep 1; echo '$@ start'; sleep 2; echo '$@ end' thing2:; @echo '$@ start'; sleep 2; echo '$@ end' -include inc.mk inc.mk: ; @touch $@ !, '', "thing2 start\nthing1 start\nthing2 end\nthing1 end\n"); delete $extraENV{MAKEFLAGS}; rmfiles('inc.mk'); # Ensure intermediate/secondary files are not pruned incorrectly. # See Savannah bug #30653 utouch(-15, 'file2'); utouch(-10, 'file4'); utouch(-5, 'file1'); run_make_test(q! .INTERMEDIATE: file3 file4: file3 ; @mv -f $< $@ file3: file2 ; touch $@ file2: file1 ; @touch $@ !, '--no-print-directory -j2', "touch file3"); rmfiles('file1', 'file2', 'file3', 'file4'); # Make sure that all jobserver FDs are closed if we need to re-exec the # master copy. # # First, find the "default" file descriptors we normally use # Then make sure they're still used. # # Right now we don't have a way to run a makefile and capture the output # without checking it, so we can't really write this test. # run_make_test(' # submake: ; @$(MAKE) --no-print-directory -f #MAKEFILE# fdprint 5>output # dependfile: ; @echo FOO=bar > $@ # INCL := true # FOO=foo # ifeq ($(INCL),true) # -include dependfile # endif # fdprint: ; @echo $(filter --jobserver%,$(MAKEFLAGS)) # recurse: ; @$(MAKE) --no-print-directory -f #MAKEFILE# submake INCL=true', # '-j2 INCL=false fdprint', # 'bar'); # rmfiles(qw(dependfile output)); # # Do it again, this time where the include is done by the non-master make. # run_make_test(undef, '-j2 recurse INCL=false', 'bar'); # rmfiles(qw(dependfile output)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/patspecific_vars000066400000000000000000000061711317072305000247170ustar00rootroot00000000000000# -*-perl-*- $description = "Test pattern-specific variable settings."; $details = "\ Create a makefile containing various flavors of pattern-specific variable settings, override and non-override, and using various variable expansion rules, semicolon interference, etc."; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; all: one.x two.x three.x FOO = foo BAR = bar BAZ = baz one.x: override FOO = one %.x: BAR = two t%.x: BAR = four thr% : override BAZ = three one.x two.x three.x: ; @echo $@: $(FOO) $(BAR) $(BAZ) four.x: baz ; @echo $@: $(FOO) $(BAR) $(BAZ) baz: ; @echo $@: $(FOO) $(BAR) $(BAZ) # test matching multiple patterns a%: AAA = aaa %b: BBB = ccc a%: BBB += ddd %b: AAA ?= xxx %b: AAA += bbb .PHONY: ab ab: ; @echo $(AAA); echo $(BBB) EOF close(MAKEFILE); # TEST #1 -- basics &run_make_with_options($makefile, "", &get_logfile); $answer = "one.x: one two baz\ntwo.x: foo four baz\nthree.x: foo four three\n"; &compare_output($answer,&get_logfile(1)); # TEST #2 -- try the override feature &run_make_with_options($makefile, "BAZ=five", &get_logfile); $answer = "one.x: one two five\ntwo.x: foo four five\nthree.x: foo four three\n"; &compare_output($answer,&get_logfile(1)); # TEST #3 -- make sure patterns are inherited properly &run_make_with_options($makefile, "four.x", &get_logfile); $answer = "baz: foo two baz\nfour.x: foo two baz\n"; &compare_output($answer,&get_logfile(1)); # TEST #4 -- test multiple patterns matching the same target &run_make_with_options($makefile, "ab", &get_logfile); $answer = "aaa bbb\nccc ddd\n"; &compare_output($answer,&get_logfile(1)); # TEST #5 -- test pattern-specific exported variables # run_make_test(' /%: export foo := foo /bar: @echo $(foo) $$foo ', '', 'foo foo'); # TEST #6 -- test expansion of pattern-specific simple variables # run_make_test(' .PHONY: all all: inherit := good $$t all: bar baz b%: pattern := good $$t global := original $$t # normal target # ifdef rec bar: a = global: $(global) pattern: $(pattern) inherit: $(inherit) else bar: a := global: $(global) pattern: $(pattern) inherit: $(inherit) endif bar: ; @echo \'normal: $a;\' # pattern target # ifdef rec %z: a = global: $(global) pattern: $(pattern) inherit: $(inherit) else %z: a := global: $(global) pattern: $(pattern) inherit: $(inherit) endif %z: ; @echo \'pattern: $a;\' global := new $$t ', '', 'normal: global: original $t pattern: inherit: ; pattern: global: original $t pattern: inherit: ;'); # TEST #7 -- test expansion of pattern-specific recursive variables # run_make_test(undef, # reuse previous makefile 'rec=1', 'normal: global: new $t pattern: good $t inherit: good $t; pattern: global: new $t pattern: good $t inherit: good $t;'); # TEST #8: override in pattern-specific variables run_make_test(' a%: override FOO += f1 a%: FOO += f2 ab: ; @echo "$(FOO)" ', '', "f1\n"); run_make_test(undef, 'FOO=C', "C f1\n"); # TEST #9: Test shortest stem selection in pattern-specific variables. run_make_test(' %-mt.x: x := two %.x: x := one all: foo.x foo-mt.x foo.x: ;@echo $x foo-mt.x: ;@echo $x ', '', "one\ntwo"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/patternrules000066400000000000000000000077421317072305000241270ustar00rootroot00000000000000# -*-perl-*- $description = "Test pattern rules."; $details = ""; use Cwd; $dir = cwd; $dir =~ s,.*/([^/]+)$,../$1,; # TEST #0: Make sure that multiple patterns where the same target # can be built are searched even if the first one fails # to match properly. # run_make_test(q! .PHONY: all all: case.1 case.2 case.3 # We can't have this, due to "Implicit Rule Search Algorithm" step 5c #xxx: void # 1 - existing file %.1: void @exit 1 %.1: #MAKEFILE# @exit 0 # 2 - phony %.2: void @exit 1 %.2: 2.phony @exit 0 .PHONY: 2.phony # 3 - implicit-phony %.3: void @exit 1 %.3: 3.implicit-phony @exit 0 3.implicit-phony: !, '', ''); # TEST #1: make sure files that are built via implicit rules are marked # as targets (Savannah bug #12202). # run_make_test(' TARGETS := foo foo.out .PHONY: all foo.in all: $(TARGETS) %: %.in @echo $@ %.out: % @echo $@ foo.in: ; @: ', '', 'foo foo.out'); # TEST #2: make sure intermediate files that also happened to be # prerequisites are not removed (Savannah bug #12267). # run_make_test(' $(dir)/foo.o: $(dir)/foo.y: @echo $@ %.c: %.y touch $@ %.o: %.c @echo $@ .PHONY: install install: $(dir)/foo.c ', "dir=$dir", "$dir/foo.y touch $dir/foo.c $dir/foo.o"); unlink("$dir/foo.c"); # TEST #3: make sure precious flag is set properly for targets # that are built via implicit rules (Savannah bug #13218). # setup_for_test(); open(MAKEFILE,"> $makefile"); print MAKEFILE ' .DELETE_ON_ERROR: .PRECIOUS: %.bar %.bar:; @touch $@ && exit 1 $(dir)/foo.bar: '; my $answer = qq{$makefile:6: recipe for target '$dir/foo.bar' failed $makefile:8: *** [../tests/foo.bar] Error 1 #0 ../tests/foo.bar at $makefile:8 }; close(MAKEFILE); my $logfile = &get_logfile; &run_make_with_options($makefile, "dir=$dir", $logfile, 512); my $slurp = &read_file_into_string ($logfile); $slurp =~ s: at .*work/features/: at work/features/:gm; &compare_output_string($answer, $slurp, $logfile); unlink("$dir/foo.bar"); # TEST #4: make sure targets of a matched implicit pattern rule are # never considered intermediate (Savannah bug #13022). # run_make_test(' .PHONY: all all: foo.c foo.o %.h %.c: %.in touch $*.h touch $*.c %.o: %.c %.h echo $+ >$@ %.o: %.c @echo wrong rule foo.in: touch $@ ', '', 'touch foo.in touch foo.h touch foo.c echo foo.c foo.h >foo.o'); unlink('foo.in', 'foo.h', 'foo.c', 'foo.o'); # TEST #5: make sure both prefix and suffix patterns work with multiple # target patterns (Savannah bug #26593). # run_make_test(' all: foo.s1 foo.s2 p1.foo p2.foo p1.% p2.%: %.orig @echo $@ %.s1 %.s2: %.orig @echo $@ .PHONY: foo.orig ', '', "foo.s1\np1.foo\n"); # TEST 6: Make sure that non-target files are still eligible to be created # as part of implicit rule chaining. Savannah bug #17752. run_make_test(q! BIN = xyz COPY = $(BIN).cp SRC = $(BIN).c allbroken: $(COPY) $(BIN) ; @echo ok $(SRC): ; @echo 'main(){}' > $@ %.cp: % ; @cp $< $@ % : %.c ; @cp $< $@ clean: ; @rm -rf $(SRC) $(COPY) $(BIN) !, '', "ok\n"); unlink(qw(xyz xyz.cp xyz.c)); # TEST 7: Make sure that all prereqs of all "also_make" targets get created # before any of the things that depend on any of them. Savannah bug #19108. run_make_test(q! final: x ; @echo $@ x: x.t1 x.t2 ; @echo $@ x.t2: dep dep: ; @echo $@ %.t1 %.t2: ; @echo $*.t1 ; echo $*.t2 !, '', "dep\nx.t1\nx.t2\nx\nfinal\n"); # TEST 8: Verify we can remove pattern rules. Savannah bug #18622. my @f = (qw(foo.w foo.ch)); touch(@f); run_make_test(q! CWEAVE := : # Disable builtin rules %.tex : %.w %.tex : %.w %.ch !, 'foo.tex', "#MAKE#: *** No rule to make target 'foo.tex'. Stop.", 512); unlink(@f); # TEST #9: Test shortest stem selection in pattern rules. run_make_test(' %.x: ;@echo one %-mt.x: ;@echo two all: foo.x foo-mt.x ', '', "one\ntwo"); 1; # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/quoting000066400000000000000000000013121317072305000230500ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test using \n" . "quotes within makefiles."; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<'EOM'; SHELL = /bin/sh TEXFONTS = NICEFONT DEFINES = -DDEFAULT_TFM_PATH=\".:$(TEXFONTS)\" test: ; @"echo" 'DEFINES = $(DEFINES)' EOM # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile); # Create the answer to what should be produced by this Makefile $answer = 'DEFINES = -DDEFAULT_TFM_PATH=\".:NICEFONT\"' . "\n"; # COMPARE RESULTS &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/recursion000066400000000000000000000024101317072305000233730ustar00rootroot00000000000000# -*-perl-*- $description = "Test recursion."; $details = "DETAILS"; # Test some basic recursion. run_make_test(' all: $(MAKE) -f #MAKEFILE# foo foo: @echo $(MAKE) @echo MAKELEVEL = $(MAKELEVEL) $(MAKE) -f #MAKEFILE# last last: @echo $(MAKE) @echo MAKELEVEL = $(MAKELEVEL) @echo THE END ', ('CFLAGS=-O -w' . ($parallel_jobs ? ' -j 2' : '')), ($vos ? "#MAKE#: Entering directory '#PWD#' make 'CFLAGS=-O' -f #MAKEFILE# foo make CFLAGS=-O MAKELEVEL = 0 make 'CFLAGS=-O' -f #MAKEFILE# last make CFLAGS=-O MAKELEVEL = 0 THE END #MAKE#: Leaving directory '#PWD#'" : "#MAKE#: Entering directory '#PWD#' #MAKEPATH# -f #MAKEFILE# foo #MAKE#[1]: Entering directory '#PWD#' #MAKEPATH# MAKELEVEL = 1 #MAKEPATH# -f #MAKEFILE# last #MAKE#[2]: Entering directory '#PWD#' #MAKEPATH# MAKELEVEL = 2 THE END #MAKE#[2]: Leaving directory '#PWD#' #MAKE#[1]: Leaving directory '#PWD#' #MAKE#: Leaving directory '#PWD#'")); # Test command line overrides. run_make_test(' recur: all ; @$(MAKE) --no-print-directory -f #MAKEFILE# a=AA all all: ; @echo "MAKEOVERRIDES = $(MAKEOVERRIDES)" ', 'a=ZZ', 'MAKEOVERRIDES = a=ZZ MAKEOVERRIDES = a=AA '); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/reinvoke000066400000000000000000000036641317072305000232200ustar00rootroot00000000000000# -*-mode: perl-*- $description = "Test GNU make's auto-reinvocation feature."; $details = "\ If the makefile or one it includes can be rebuilt then it is, and make is reinvoked. We create a rule to rebuild the makefile from a temp file, then touch the temp file to make it newer than the makefile."; $omkfile = $makefile; &utouch(-600, 'incl.mk'); # For some reason if we don't do this then the test fails for systems # with sub-second timestamps, maybe + NFS? Not sure. &utouch(-1, 'incl-1.mk'); run_make_test(' all: ; @echo running rules. #MAKEFILE# incl.mk: incl-1.mk @echo rebuilding $@ @echo >> $@ include incl.mk', '', "rebuilding incl.mk\nrunning rules.\n"); # Make sure updating the makefile itself also works &utouch(-600, $omkfile); run_make_test(undef, '', "rebuilding #MAKEFILE#\nrunning rules.\n"); &rmfiles('incl.mk', 'incl-1.mk'); # In this test we create an included file that's out-of-date, but then # the rule doesn't update it. Make shouldn't re-exec. &utouch(-600, 'b','a'); #&utouch(-10, 'a'); &touch('c'); run_make_test(' SHELL = /bin/sh all: ; @echo hello a : b ; echo >> $@ b : c ; [ -f $@ ] || echo >> $@ c: ; echo >> $@ include $(F)', 'F=a', "[ -f b ] || echo >> b\nhello\n"); # Now try with the file we're not updating being the actual file we're # including: this and the previous one test different parts of the code. run_make_test(undef, 'F=b', "[ -f b ] || echo >> b\nhello\n") &rmfiles('a','b','c'); # Ensure command line variables are preserved properly across re-exec # Tests for Savannah bug #30723 run_make_test(' ifdef RECURSE -include foo30723 endif recurse: ; @$(MAKE) -f $(MAKEFILE_LIST) RECURSE=1 test test: ; @echo F.O=$(F.O) foo30723: ; @touch $@ ', '--no-print-directory F.O=bar', "F.O=bar\n"); unlink('foo30723'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/rule_glob000066400000000000000000000016241317072305000233420ustar00rootroot00000000000000# -*-perl-*- $description = "Test globbing in targets and prerequisites."; $details = ""; touch(qw(a.one a.two a.three)); # Test wildcards in regular targets and prerequisites run_make_test(q{ .PHONY: all a.one a.two a.three all: a.one* a.t[a-z0-9]o a.th[!q]ee a.o[Nn][Ee] a.t*: ; @echo $@ }, '', "a.one\na.two\na.three"); # Test wildcards in pattern targets and prerequisites run_make_test(q{ .PHONY: all all: a.four %.four : %.t* ; @echo $@: $(sort $^) }, '', "a.four: a.three a.two"); # Test wildcards in second expansion targets and prerequisites run_make_test(q{ .PHONY: all all: a.four .SECONDEXPANSION: %.four : $$(sort %.t*) ; @echo $@: $(sort $^) }, '', "a.four: a.three a.two"); unlink(qw(a.one a.two a.three)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/se_explicit000066400000000000000000000052111317072305000236740ustar00rootroot00000000000000# -*-perl-*- $description = "Test second expansion in ordinary rules."; $details = ""; # TEST #0: Test handing of '$' in prerequisites with and without second # expansion. # If we don't support archives then the prerequisite is different my $prereq = exists $FEATURES{'archives'} ? '$' : '$(PRE)'; run_make_test(q! ifdef SE .SECONDEXPANSION: endif foo$$bar: bar$$baz bar$$biz ; @echo '$@ : $^' PRE = one two bar$$baz: $$(PRE) baraz: $$(PRE) PRE = three four .DEFAULT: ; @echo '$@' !, '', "$prereq\nbar\$biz\nfoo\$bar : bar\$baz bar\$biz"); run_make_test(undef, 'SE=1', "three\nfour\nbariz\nfoo\$bar : baraz bariz"); # TEST #1: automatic variables. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' foo: bar baz foo: biz | buz foo: $$@.1 \ $$<.2 \ $$(addsuffix .3,$$^) \ $$(addsuffix .4,$$+) \ $$|.5 \ $$*.6 !, '', 'bar baz biz buz foo.1 bar.2 bar.3 baz.3 biz.3 bar.4 baz.4 biz.4 buz.5 .6 '); # Test #2: target/pattern -specific variables. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' foo.x: $$a $$b foo.x: a := bar %.x: b := baz !, '', 'bar baz '); # Test #3: order of prerequisites. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' all: foo bar baz # Subtest #1 foo: foo.1; @: foo: foo.2 foo: foo.3 # Subtest #2 bar: bar.2 bar: bar.1; @: bar: bar.3 # Subtest #3 baz: baz.1 baz: baz.2 baz: ; @: !, '', 'foo.1 foo.2 foo.3 bar.1 bar.2 bar.3 baz.1 baz.2 '); # TEST #4: eval in a context where there is no reading_file run_make_test(q! .SECONDEXPANSION: all : $$(eval $$(info test)) !, '', "test\n#MAKE#: Nothing to be done for 'all'.\n"); # TEST #5: (NEGATIVE) catch eval in a prereq list trying to create new # target/prereq relationships. run_make_test(q! .SECONDEXPANSION: proj1.exe : proj1.o $$(eval $$(test)) define test proj1.o : proj1.c proj1.c: proj1.h endef !, '', "#MAKE#: *** prerequisites cannot be defined in recipes. Stop.\n", 512); # Automatic $$+ variable expansion issue. Savannah bug #25780 run_make_test(q! all : foo foo .SECONDEXPANSION: all : $$+ ; @echo '$+' foo : ; !, '', "foo foo foo foo\n"); # Automatic $$+ variable expansion issue. Savannah bug #25780 run_make_test(q! all : bar bar bar : ; q%x : ; .SECONDEXPANSION: a%l: q1x $$+ q2x ; @echo '$+' !, '', "q1x bar bar q2x bar bar\n"); # Allow patsubst shorthand in second expansion context. # Requires the colon to be quoted. Savannah bug #16545 run_make_test(q! .PHONY: foo.bar .SECONDEXPANSION: foo: $$(@\\:%=%.bar); @echo '$^' !, '', "foo.bar\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/se_implicit000066400000000000000000000072051317072305000236720ustar00rootroot00000000000000# -*-perl-*- $description = "Test second expansion in ordinary rules."; $details = ""; use Cwd; $dir = cwd; $dir =~ s,.*/([^/]+)$,../$1,; # Test #1: automatic variables. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' foo.a: bar baz foo.a: biz | buz foo.%: 1.$$@ \ 2.$$< \ $$(addprefix 3.,$$^) \ $$(addprefix 4.,$$+) \ 5.$$| \ 6.$$* @: 1.foo.a \ 2.bar \ 3.bar \ 3.baz \ 3.biz \ 4.bar \ 4.baz \ 4.biz \ 5.buz \ 6.a: @echo '$@' !, '', '1.foo.a 2.bar 3.bar 3.baz 3.biz 4.bar 4.baz 4.biz 5.buz 6.a bar baz biz buz '); # Test #2: target/pattern -specific variables. # run_make_test(q! .SECONDEXPANSION: foo.x: foo.%: $$(%_a) $$(%_b) bar @: foo.x: x_a := bar %.x: x_b := baz bar baz: ; @echo '$@' !, '', "bar\nbaz\n"); # Test #3: order of prerequisites. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' all: foo bar baz # Subtest #1 # %oo: %oo.1; @: foo: foo.2 foo: foo.3 foo.1: ; @echo '$@' # Subtest #2 # bar: bar.2 %ar: %ar.1; @: bar: bar.3 bar.1: ; @echo '$@' # Subtest #3 # baz: baz.1 baz: baz.2 %az: ; @: !, '', 'foo.1 foo.2 foo.3 bar.1 bar.2 bar.3 baz.1 baz.2 '); # Test #4: stem splitting logic. # run_make_test(q! .SECONDEXPANSION: $(dir)/tmp/bar.o: $(dir)/tmp/foo/bar.c: ; @echo '$@' $(dir)/tmp/bar/bar.c: ; @echo '$@' foo.h: ; @echo '$@' %.o: $$(addsuffix /%.c,foo bar) foo.h @echo '$@: {$<} $^' !, "dir=$dir", "$dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h $dir/tmp/bar.o: {$dir/tmp/foo/bar.c} $dir/tmp/foo/bar.c $dir/tmp/bar/bar.c foo.h "); # Test #5: stem splitting logic and order-only prerequisites. # run_make_test(q! .SECONDEXPANSION: $(dir)/tmp/foo.o: $(dir)/tmp/foo.c $(dir)/tmp/foo.c: ; @echo '$@' bar.h: ; @echo '$@' %.o: %.c|bar.h @echo '$@: {$<} {$|} $^' !, "dir=$dir", "$dir/tmp/foo.c bar.h $dir/tmp/foo.o: {$dir/tmp/foo.c} {bar.h} $dir/tmp/foo.c "); # Test #6: lack of implicit prerequisites. # run_make_test(q! .SECONDEXPANSION: foo.o: foo.c foo.c: ; @echo '$@' %.o: @echo '$@: {$<} $^' !, '', "foo.c\nfoo.o: {foo.c} foo.c\n"); # Test #7: Test stem from the middle of the name. # run_make_test(q! .SECONDEXPANSION: foobarbaz: foo%baz: % $$*.1 @echo '$*' bar bar.1: @echo '$@' !, '', "bar\nbar.1\nbar\n"); # Test #8: Make sure stem triple-expansion does not happen. # run_make_test(q! .SECONDEXPANSION: foo$$bar: f%r: % $$*.1 @echo '$*' oo$$ba oo$$ba.1: @echo '$@' !, '', 'oo$ba oo$ba.1 oo$ba '); # Test #9: Check the value of $^ run_make_test(q! .SECONDEXPANSION: %.so: | $$(extra) ; @echo $^ foo.so: extra := foo.o foo.so: foo.o: !, '', "\n"); # Test #10: Test second expansion with second expansion prerequisites # Ensures pattern_search() recurses with SE prereqs. touch('a'); run_make_test(q! .SECONDEXPANSION: sim_base_rgg := just_a_name sim_base_src := a sim_base_f := a a a sim_%.f: $${sim_$$*_f} echo $@ sim_%.src: $${sim_$$*_src} echo $@ sim_%: \ $$(if $$(sim_$$*_src),sim_%.src) \ $$(if $$(sim_$$*_f),sim_%.f) \ $$(if $$(sim_$$*_rgg),$$(sim_$$*_rgg).s) echo $@ !, '-s sim_base', "#MAKE#: *** No rule to make target 'sim_base'. Stop.", 512); unlink('a'); # Ensure that order-only tokens embedded in second expansions are parsed run_make_test(q! .SECONDEXPANSION: PREREQS=p1|p2 P2=p2 all : foo bar f%o: $$(PREREQS) ; @echo '$@' from '$^' and '$|' b%r: p1|$$(P2) ; @echo '$@' from '$^' and '$|' p% : ; : $@ !, "", ": p1\n: p2\nfoo from p1 and p2\nbar from p1 and p2\n"); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/se_statpat000066400000000000000000000031711317072305000235360ustar00rootroot00000000000000# -*-perl-*- $description = "Test second expansion in static pattern rules."; $details = ""; # Test #1: automatic variables. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' foo.a foo.b: foo.%: bar.% baz.% foo.a foo.b: foo.%: biz.% | buz.% foo.a foo.b: foo.%: $$@.1 \ $$<.2 \ $$(addsuffix .3,$$^) \ $$(addsuffix .4,$$+) \ $$|.5 \ $$*.6 !, '', 'bar.a baz.a biz.a buz.a foo.a.1 bar.a.2 bar.a.3 baz.a.3 biz.a.3 bar.a.4 baz.a.4 biz.a.4 buz.a.5 a.6 '); # Test #2: target/pattern -specific variables. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' foo.x foo.y: foo.%: $$(%_a) $$($$*_b) foo.x: x_a := bar %.x: x_b := baz !, '', "bar\nbaz\n"); # Test #3: order of prerequisites. # run_make_test(q! .SECONDEXPANSION: .DEFAULT: ; @echo '$@' all: foo.a bar.a baz.a # Subtest #1 foo.a foo.b: foo.%: foo.%.1; @: foo.a foo.b: foo.%: foo.%.2 foo.a foo.b: foo.%: foo.%.3 # Subtest #2 bar.a bar.b: bar.%: bar.%.2 bar.a bar.b: bar.%: bar.%.1; @: bar.a bar.b: bar.%: bar.%.3 # Subtest #3 baz.a baz.b: baz.%: baz.%.1 baz.a baz.b: baz.%: baz.%.2 baz.a baz.b: ; @: !, '', 'foo.a.1 foo.a.2 foo.a.3 bar.a.1 bar.a.2 bar.a.3 baz.a.1 baz.a.2 '); # Test #4: Make sure stem triple-expansion does not happen. # run_make_test(q! .SECONDEXPANSION: foo$$bar: f%r: % $$*.1 @echo '$*' oo$$ba oo$$ba.1: @echo '$@' !, '', 'oo$ba oo$ba.1 oo$ba '); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/shell_assignment000066400000000000000000000034101317072305000247220ustar00rootroot00000000000000# -*-perl-*- $description = "Test BSD-style shell assignments (VAR != VAL) for variables."; $details = ""; # TEST 0: Basic shell assignment (!=). run_make_test(' .POSIX: demo1!=printf \' 1 2 3\n4\n\n5 \n \n 6\n\n\n\n\' demo2 != printf \'7 8\n \' demo3 != printf \'$$(demo2)\' demo4 != printf \' 2 3 \n\' demo5 != printf \' 2 3 \n\n\' all: ; @echo "<$(demo1)> <$(demo2)> <$(demo3)> <$(demo4)> <${demo5}>" ', '', "< 1 2 3 4 5 6 > <7 8 > <7 8 > < 2 3 > < 2 3 >\n"); # TEST 1: Handle '#' the same way as BSD make run_make_test(' foo1!=echo bar#baz hash != printf \'\043\' foo2!= echo "bar$(hash)baz" all: ; @echo "<$(foo1)> <$(hash)> <$(foo2)>" ', '', " <#> \n"); # TEST 2: shell assignment variables (from !=) should be recursive. # Note that variables are re-evaluated later, so the shell can output # a value like $(XYZZY) as part of !=. The $(XYZZY) will be EVALUATED # when the value containing it is evaluated. On the negative side, this # means if you don't want this, you need to escape dollar signs as $$. # On the positive side, it means that shell programs can output macros # that are then evaluated as they are traditionally evaluated.. and that # you can use traditional macro evaluation semantics to implement !=. run_make_test(' XYZZY = fiddle-dee-dee dollar = $$ VAR3 != printf \'%s\' \'$(dollar)(XYZZY)\' all: ; @echo "<$(VAR3)>" ', '', "\n"); # TEST 3: Overrides invoke shell anyway; they just don't store the result # in a way that is visible. run_make_test(' override != echo abc > ,abc ; cat ,abc all: ; @echo "<$(override)>" ; cat ,abc ', 'override=xyz', "\nabc\n"); unlink(',abc'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/statipattrules000066400000000000000000000043241317072305000244600ustar00rootroot00000000000000# -*-perl-*- $description = "Test handling of static pattern rules."; $details = "\ The makefile created in this test has three targets. The filter command is used to get those target names ending in .o and statically creates a compile command with the target name and the target name with .c. It also does the same thing for another target filtered with .elc and creates a command to emacs a .el file"; &touch('bar.c', 'lose.c'); # TEST #0 # ------- run_make_test(' files = foo.elc bar.o lose.o $(filter %.o,$(files)): %.o: %.c ; @echo CC -c $(CFLAGS) $< -o $@ $(filter %.elc,$(files)): %.elc: %.el ; @echo emacs $< ', '', 'CC -c bar.c -o bar.o'); # TEST #1 # ------- run_make_test(undef, 'lose.o', 'CC -c lose.c -o lose.o'); # TEST #2 # ------- &touch("foo.el"); run_make_test(undef, 'foo.elc', 'emacs foo.el'); # Clean up after the first tests. unlink('foo.el', 'bar.c', 'lose.c'); # TEST #3 -- PR/1670: don't core dump on invalid static pattern rules # ------- run_make_test(' .DEFAULT: ; @echo $@ foo: foo%: % %.x % % % y.% % ; @echo $@ ', '', ".x\ny.\nfoo"); # TEST #4 -- bug #12180: core dump on a stat pattern rule with an empty # prerequisite list. run_make_test(' foo.x bar.x: %.x : ; @echo $@ ', '', 'foo.x'); # TEST #5 -- bug #13881: double colon static pattern rule does not # substitute %. run_make_test(' foo.bar:: %.bar: %.baz foo.baz: ;@: ', '', ''); # TEST #6: make sure the second stem does not overwrite the first # perprerequisite's stem (Savannah bug #16053). # run_make_test(' all.foo.bar: %.foo.bar: %.one all.foo.bar: %.bar: %.two all.foo.bar: @echo $* @echo $^ .DEFAULT:;@: ', '', 'all.foo all.one all.foo.two'); # TEST #7: make sure the second stem does not overwrite the first # perprerequisite's stem when second expansion is enabled # (Savannah bug #16053). # run_make_test(' .SECONDEXPANSION: all.foo.bar: %.foo.bar: %.one $$*-one all.foo.bar: %.bar: %.two $$*-two all.foo.bar: @echo $* @echo $^ .DEFAULT:;@: ', '', 'all.foo all.one all-one all.foo.two all.foo-two'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/targetvars000066400000000000000000000133101317072305000235450ustar00rootroot00000000000000# -*-perl-*- $description = "Test target-specific variable settings."; $details = "\ Create a makefile containing various flavors of target-specific variable values, override and non-override, and using various variable expansion rules, semicolon interference, etc."; run_make_test(' SHELL = /bin/sh export FOO = foo export BAR = bar one: override FOO = one one two: ; @echo $(FOO) $(BAR) two: BAR = two three: ; BAR=1000 @echo $(FOO) $(BAR) # Some things that shouldn not be target vars funk : override funk : override adelic adelic override : ; echo $@ # Test per-target recursive variables four:FOO=x four:VAR$(FOO)=ok four: ; @echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx)" five:FOO=x five six : VAR$(FOO)=good five six: ;@echo "$(FOO) $(VAR$(FOO)) $(VAR) $(VARx) $(VARfoo)" # Test per-target variable inheritance seven: eight seven eight: ; @echo $@: $(FOO) $(BAR) seven: BAR = seven seven: FOO = seven eight: BAR = eight # Test the export keyword with per-target variables nine: ; @echo $(FOO) $(BAR) $$FOO $$BAR nine: FOO = wallace nine-a: export BAZ = baz nine-a: ; @echo $$BAZ # Test = escaping EQ = = ten: one$(EQ)two ten: one $(EQ) two ten one$(EQ)two $(EQ):;@echo $@ .PHONY: one two three four five six seven eight nine ten $(EQ) one$(EQ)two # Test target-specific vars with pattern/suffix rules QVAR = qvar RVAR = = %.q : ; @echo $(QVAR) $(RVAR) foo.q : RVAR += rvar # Target-specific vars with multiple LHS pattern rules %.r %.s %.t: ; @echo $(QVAR) $(RVAR) $(SVAR) $(TVAR) foo.r : RVAR += rvar foo.t : TVAR := $(QVAR) ', "one two three", "one bar\nfoo two\nBAR=1000\nfoo bar\n"); # TEST #2 run_make_test(undef, "one two FOO=1 BAR=2", "one 2\n1 2\n"); # TEST #3 run_make_test(undef, "four", "x ok ok\n"); # TEST #4 run_make_test(undef, "seven", "eight: seven eight\nseven: seven seven\n"); # TEST #5 run_make_test(undef, "nine", "wallace bar wallace bar\n"); # TEST #5-a run_make_test(undef, "nine-a", "baz\n"); # TEST #6 run_make_test(undef, "ten", "one=two\none bar\n=\nfoo two\nten\n"); # TEST #6 run_make_test(undef, "foo.q bar.q", "qvar = rvar\nqvar =\n"); # TEST #7 run_make_test(undef, "foo.t bar.s", "qvar = qvar\nqvar =\n"); # TEST #8 # For PR/1378: Target-specific vars don't inherit correctly run_make_test(' foo: FOO = foo bar: BAR = bar foo: bar bar: baz baz: ; @echo $(FOO) $(BAR) ', "", "foo bar\n"); # TEST #9 # For PR/1380: Using += assignment in target-specific variables sometimes fails # Also PR/1831 run_make_test(' .PHONY: all one all: FOO += baz all: one; @echo $(FOO) FOO = bar one: FOO += biz one: FOO += boz one: ; @echo $(FOO) ', '', "bar baz biz boz\nbar baz\n"); # Test #10 run_make_test(undef, 'one', "bar biz boz\n"); # Test #11 # PR/1709: Test semicolons in target-specific variable values run_make_test(' foo : FOO = ; ok foo : ; @echo "$(FOO)" ', '', "; ok\n"); # Test #12 # PR/2020: More hassles with += target-specific vars. I _really_ think # I nailed it this time :-/. run_make_test(' .PHONY: a BLAH := foo COMMAND = echo $(BLAH) a: ; @$(COMMAND) a: BLAH := bar a: COMMAND += snafu $(BLAH) ', '', "bar snafu bar\n"); # Test #13 # Test double-colon rules with target-specific variable values run_make_test(' W = bad X = bad foo: W = ok foo:: ; @echo $(W) $(X) $(Y) $(Z) foo:: ; @echo $(W) $(X) $(Y) $(Z) foo: X = ok Y = foo bar: foo bar: Y = bar Z = nopat ifdef PATTERN fo% : Z = pat endif ', 'foo', "ok ok foo nopat\nok ok foo nopat\n"); # Test #14 # Test double-colon rules with target-specific variable values and # inheritance run_make_test(undef, 'bar', "ok ok bar nopat\nok ok bar nopat\n"); # Test #15 # Test double-colon rules with pattern-specific variable values run_make_test(undef, 'foo PATTERN=yes', "ok ok foo pat\nok ok foo pat\n"); # Test #16 # Test target-specific variables with very long command line # (> make default buffer length) run_make_test(' base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi ) deals_changed_since: ; @echo $(BUILD_OBJ) ', '', "no build information\n"); # TEST #17 # Test a merge of set_lists for files, where one list is much longer # than the other. See Savannah bug #15757. mkdir('t1', 0777); touch('t1/rules.mk'); run_make_test(' VPATH = t1 include rules.mk .PHONY: all all: foo.x foo.x : rules.mk ; @echo MYVAR=$(MYVAR) FOOVAR=$(FOOVAR) ALLVAR=$(ALLVAR) all: ALLVAR = xxx foo.x: FOOVAR = bar rules.mk : MYVAR = foo .INTERMEDIATE: foo.x rules.mk ', '-I t1', 'MYVAR= FOOVAR=bar ALLVAR=xxx'); rmfiles('t1/rules.mk'); rmdir('t1'); # TEST #18 # Test appending to a simple variable containing a "$": avoid a # double-expansion. See Savannah bug #15913. run_make_test(' VAR := $$FOO foo: VAR += BAR foo: ; @echo '."'".'$(VAR)'."'".' ', '', '$FOO BAR'); # TEST #19: Override with append variables run_make_test(' a: override FOO += f1 a: FOO += f2 a: ; @echo "$(FOO)" ', '', "f1\n"); run_make_test(undef, 'FOO=C', "C f1\n"); # TEST #19: Conditional variables with command-line settings run_make_test(' a: FOO ?= f1 a: ; @echo "$(FOO)" ', '', "f1\n"); run_make_test(undef, 'FOO=C', "C\n"); # TEST #20: Check for continuation after semicolons run_make_test(q! a: A = 'hello;\ world' a: ; @echo $(A) !, '', "hello; world\n"); # TEST #19: Test define/endef variables as target-specific vars # run_make_test(' # define b # @echo global # endef # a: define b # @echo local # endef # a: ; $(b) # ', # '', "local\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/utf8000066400000000000000000000005001317072305000222460ustar00rootroot00000000000000# -*-perl-*- $description = "Test support for UTF-8."; $details = ""; # Verify that the UTF-8 BOM is ignored. run_make_test("\xEF\xBB\xBFall: ; \@echo \$\@\n", '', "all"); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/varnesting000066400000000000000000000011651317072305000235500ustar00rootroot00000000000000# -*-perl-*- $description = "Test recursive variables"; $details = ""; run_make_test(' x = variable1 variable2 := Hello y = $(subst 1,2,$(x)) z = y a := $($($(z))) all: @echo $(a) ', '', "Hello\n"); # This tests resetting the value of a variable while expanding it. # You may only see problems with this if you're using valgrind or # some other memory checker that poisons freed memory. # See Savannah patch #7534 run_make_test(' VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE) wololo: @$(VARIABLE) ', '', "hi\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/vpath000066400000000000000000000056301317072305000225130ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test the \n" ."vpath directive which allows you to specify a search \n" ."path for a particular class of filenames, those that\n" ."match a particular pattern."; $details = "This tests the vpath directive by specifying search directories\n" ."for one class of filenames with the form: vpath pattern directories" ."\nIn this test, we specify the working directory for all files\n" ."that end in c or h. We also test the variables $@ (which gives\n" ."target name) and $^ (which is a list of all dependencies \n" ."including the directories in which they were found). It also\n" ."uses the function firstword used to extract just the first\n" ."dependency from the entire list."; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "vpath %.c foo\n"; print MAKEFILE "vpath %.c $workdir\n"; print MAKEFILE "vpath %.h $workdir\n"; print MAKEFILE "objects = main.o kbd.o commands.o display.o insert.o\n"; print MAKEFILE "edit: \$(objects)\n"; print MAKEFILE "\t\@echo cc -o \$@ \$^\n"; print MAKEFILE "main.o : main.c defs.h\n"; print MAKEFILE "\t\@echo cc -c \$(firstword \$^)\n"; print MAKEFILE "kbd.o : kbd.c defs.h command.h\n"; print MAKEFILE "\t\@echo cc -c kbd.c\n"; print MAKEFILE "commands.o : command.c defs.h command.h\n"; print MAKEFILE "\t\@echo cc -c commands.c\n"; print MAKEFILE "display.o : display.c defs.h buffer.h\n"; print MAKEFILE "\t\@echo cc -c display.c\n"; print MAKEFILE "insert.o : insert.c defs.h buffer.h\n"; print MAKEFILE "\t\@echo cc -c insert.c\n"; # END of Contents of MAKEFILE close(MAKEFILE); @files_to_touch = ("$workdir${pathsep}main.c","$workdir${pathsep}defs.h", "$workdir${pathsep}kbd.c","$workdir${pathsep}command.h", "$workdir${pathsep}commands.c","$workdir${pathsep}display.c", "$workdir${pathsep}buffer.h","$workdir${pathsep}insert.c", "$workdir${pathsep}command.c"); &touch(@files_to_touch); &run_make_with_options($makefile,"",&get_logfile); # Create the answer to what should be produced by this Makefile $answer = "cc -c $workdir${pathsep}main.c\ncc -c kbd.c\ncc -c commands.c\n" ."cc -c display.c\n" ."cc -c insert.c\ncc -o edit main.o kbd.o commands.o display.o " ."insert.o\n"; if (&compare_output($answer,&get_logfile(1))) { unlink @files_to_touch; } # TEST 2: after vpath lookup ensure we don't get incorrect circular dependency # warnings due to change of struct file ptr. Savannah bug #13529. mkdir('vpath-d', 0777); run_make_test(q! vpath %.te vpath-d/ .SECONDARY: default: vpath-d/a vpath-d/b vpath-d/a: fail.te vpath-d/b : fail.te vpath-d/fail.te: !, '', "#MAKE#: Nothing to be done for 'default'.\n"); rmdir('vpath-d'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/vpath2000066400000000000000000000023371317072305000225760ustar00rootroot00000000000000$description = "This is part 2 in a series to test the vpath directive\n" ."It tests the three forms of the directive:\n" ." vpath pattern directive\n" ." vpath pattern (clears path associated with pattern)\n" ." vpath (clears all paths specified with vpath)\n"; $details = "This test simply adds many search paths using various vpath\n" ."directive forms and clears them afterwards. It has a simple\n" ."rule to print a message at the end to confirm that the makefile\n" ."ran with no errors.\n"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "VPATH = $workdir:$sourcedir\n"; print MAKEFILE "vpath %.c foo\n"; print MAKEFILE "vpath %.c $workdir\n"; print MAKEFILE "vpath %.c $sourcedir\n"; print MAKEFILE "vpath %.h $workdir\n"; print MAKEFILE "vpath %.c\n"; print MAKEFILE "vpath\n"; print MAKEFILE "all:\n"; print MAKEFILE "\t\@echo ALL IS WELL\n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile); # Create the answer to what should be produced by this Makefile $answer = "ALL IS WELL\n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/vpath3000066400000000000000000000015361317072305000225770ustar00rootroot00000000000000# -*-perl-*- $description = "Test the interaction of the -lfoo feature and vpath"; $details = ""; my @dirs_to_make = qw(a1 b1 a2 b2 b3); for my $d (@dirs_to_make) { mkdir($d, 0777); } my @files_to_touch = ("a1${pathsep}lib1.a", "a1${pathsep}libc.a", "b1${pathsep}lib1.so", "a2${pathsep}lib2.a", "b2${pathsep}lib2.so", "lib3.a", "b3${pathsep}lib3.so"); &touch(@files_to_touch); run_make_test(' vpath %.h b3 vpath %.a a1 vpath %.so b1 vpath % a2 b2 vpath % b3 all: -l1 -lc -l2 -l3; @echo $^ ', '', "a1${pathsep}lib1.a a1${pathsep}libc.a a2${pathsep}lib2.a lib3.a\n"); unlink(@files_to_touch); for my $d (@dirs_to_make) { rmdir($d); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/vpathgpath000066400000000000000000000021041317072305000235300ustar00rootroot00000000000000# -*-perl-*- $description = "Tests VPATH+/GPATH functionality."; $details = ""; $VP = "$workdir$pathsep"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "VPATH = $VP\n"; print MAKEFILE <<'EOMAKE'; GPATH = $(VPATH) .SUFFIXES: .a .b .c .d .PHONY: general rename notarget intermediate %.a: %.b: %.c: %.d: %.a : %.b ; cat $^ > $@ %.b : %.c ; cat $^ > $@ %.c :: %.d ; cat $^ > $@ # General testing info: general: foo.b foo.b: foo.c bar.c EOMAKE close(MAKEFILE); @touchedfiles = (); $off = -500; sub touchfiles { foreach (@_) { ($f = $_) =~ s,VP/,$VP,g; &utouch($off, $f); $off += 10; push(@touchedfiles, $f); } } # Run the general-case test &touchfiles("VP/foo.d", "VP/bar.d", "VP/foo.c", "VP/bar.c", "foo.b", "bar.d"); &run_make_with_options($makefile,"general",&get_logfile()); push(@touchedfiles, "bar.c"); $answer = "$make_name: Nothing to be done for 'general'.\n"; &compare_output($answer,&get_logfile(1)); unlink(@touchedfiles) unless $keep; 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/features/vpathplus000066400000000000000000000052451317072305000234210ustar00rootroot00000000000000# -*-perl-*- $description = "Tests the new VPATH+ functionality added in 3.76."; $details = ""; $VP = "$workdir$pathsep"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "VPATH = $VP\n"; print MAKEFILE <<'EOMAKE'; SHELL = /bin/sh .SUFFIXES: .a .b .c .d .PHONY: general rename notarget intermediate %.a: %.b: %.c: %.d: %.a : %.b cat $^ > $@ %.b : %.c cat $^ > $@ 2>/dev/null || exit 1 %.c :: %.d cat $^ > $@ # General testing info: general: foo.b foo.b: foo.c bar.c # Rename testing info: rename: $(VPATH)/foo.c foo.d # Target not made testing info: notarget: notarget.b notarget.c: notarget.d -@echo "not creating $@ from $^" # Intermediate files: intermediate: inter.a EOMAKE close(MAKEFILE); @touchedfiles = (); $off = -500; sub touchfiles { foreach (@_) { &utouch($off, $_); $off += 10; push(@touchedfiles, $_); } } # Run the general-case test &touchfiles("$VP/foo.d", "$VP/bar.d", "$VP/foo.c", "$VP/bar.c", "foo.b", "bar.d"); &run_make_with_options($makefile,"general",&get_logfile); push(@touchedfiles, "bar.c"); $answer = "cat bar.d > bar.c cat ${VP}foo.c bar.c > foo.b 2>/dev/null || exit 1 "; &compare_output($answer,&get_logfile(1)); # Test rules that don't make the target correctly &touchfiles("$VP/notarget.c", "notarget.b", "notarget.d"); $answer = "not creating notarget.c from notarget.d cat notarget.c > notarget.b 2>/dev/null || exit 1 $makefile:16: recipe for target 'notarget.b' failed $makefile:15: *** [notarget.b] Error 1 #0 notarget.b at work/features/vpathplus.mk:15 #1 notarget at work/features/vpathplus.mk:31 "; my $logfile = &get_logfile; &run_make_with_options($makefile, "notarget", $logfile, 512); my $slurp = &read_file_into_string ($logfile); $slurp =~ s{at .*work/features/}{at work/features/}gm; &compare_output_string($answer, $slurp, $logfile); # Test intermediate file handling (part 1) &touchfiles("$VP/inter.d"); &run_make_with_options($makefile,"intermediate",&get_logfile); push(@touchedfiles, "inter.a", "inter.b"); $answer = "cat ${VP}inter.d > inter.c cat inter.c > inter.b 2>/dev/null || exit 1 cat inter.b > inter.a rm inter.b inter.c "; &compare_output($answer,&get_logfile(1)); # Test intermediate file handling (part 2) &utouch(-20, "inter.a"); &utouch(-10, "$VP/inter.b"); &touch("$VP/inter.d"); push(@touchedfiles, "$VP/inter.b", "$VP/inter.d"); &run_make_with_options($makefile,"intermediate",&get_logfile); $answer = "cat ${VP}inter.d > inter.c cat inter.c > inter.b 2>/dev/null || exit 1 cat inter.b > inter.a rm inter.c "; &compare_output($answer,&get_logfile(1)); unlink @touchedfiles unless $keep; 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/000077500000000000000000000000001317072305000216345ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/abspath000066400000000000000000000034331317072305000232040ustar00rootroot00000000000000# -*-perl-*- $description = "Test the abspath functions."; $details = ""; run_make_test(' ifneq ($(realpath $(abspath .)),$(CURDIR)) $(warning .: abs="$(abspath .)" real="$(realpath $(abspath .))" curdir="$(CURDIR)") endif ifneq ($(realpath $(abspath ./)),$(CURDIR)) $(warning ./: abs="$(abspath ./)" real="$(realpath $(abspath ./))" curdir="$(CURDIR)") endif ifneq ($(realpath $(abspath .///)),$(CURDIR)) $(warning .///: abs="$(abspath .///)" real="$(realpath $(abspath .///))" curdir="$(CURDIR)") endif ifneq ($(abspath /),/) $(warning /: abspath="$(abspath /)") endif ifneq ($(abspath ///),/) $(warning ///: abspath="$(abspath ///)") endif ifneq ($(abspath /.),/) $(warning /.: abspath="$(abspath /.)") endif ifneq ($(abspath ///.),/) $(warning ///.: abspath="$(abspath ///.)") endif ifneq ($(abspath /./),/) $(warning /./: abspath="$(abspath /./)") endif ifneq ($(abspath /.///),/) $(warning /.///: abspath="$(abspath /.///)") endif ifneq ($(abspath /..),/) $(warning /..: abspath="$(abspath /..)") endif ifneq ($(abspath ///..),/) $(warning ///..: abspath="$(abspath ///..)") endif ifneq ($(abspath /../),/) $(warning /../: abspath="$(abspath /../)") endif ifneq ($(abspath /..///),/) $(warning /..///: abspath="$(abspath /..///)") endif ifneq ($(abspath /foo/bar/..),/foo) $(warning /foo/bar/..: abspath="$(abspath /foo/bar/..)") endif ifneq ($(abspath /foo/bar/../../../baz),/baz) $(warning /foo/bar/../../../baz: abspath="$(abspath /foo/bar/../../../baz)") endif ifneq ($(abspath /foo/bar/../ /..),/foo /) $(warning /foo/bar/../ /..: abspath="$(abspath /foo/bar/../ /..)") endif .PHONY: all all: ; @: ', '', ''); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/addprefix000066400000000000000000000022041317072305000235230ustar00rootroot00000000000000$description = "The following test creates a makefile to test the addprefix " ."function."; $details = ""; # IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(addprefix src${pathsep},a.b.z.foo hacks) \n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "src${pathsep}a.b.z.foo src${pathsep}hacks\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/addsuffix000066400000000000000000000013411317072305000235330ustar00rootroot00000000000000# -*-perl-*- $description = "Test the addsuffix function."; $details = ""; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(basename src${pathsep}a.b.z.foo.c src${pathsep}hacks src.bar${pathsep}a.b.z.foo.c src.bar${pathsep}hacks hacks) \n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "src${pathsep}a.b.z.foo src${pathsep}hacks src.bar${pathsep}a.b.z.foo src.bar${pathsep}hacks hacks\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/call000066400000000000000000000052721317072305000225000ustar00rootroot00000000000000# -*-perl-*- $description = "Test the call function.\n"; $details = "Try various uses of call and ensure they all give the correct results.\n"; open(MAKEFILE, "> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<'EOMAKE'; # Simple, just reverse two things # reverse = $2 $1 # A complex 'map' function, using recursive 'call'. # map = $(foreach a,$2,$(call $1,$a)) # Test using a builtin; this is silly as it's simpler to do without call # my-notdir = $(call notdir,$(1)) # Test using non-expanded builtins # my-foreach = $(foreach $(1),$(2),$(3)) my-if = $(if $(1),$(2),$(3)) # Test recursive invocations of call with different arguments # one = $(1) $(2) $(3) two = $(call one,$(1),foo,$(2)) # Test recursion on the user-defined function. As a special case make # won't error due to this. # Implement transitive closure using $(call ...) # DEP_foo = bar baz quux DEP_baz = quux blarp rest = $(wordlist 2,$(words ${1}),${1}) tclose = $(if $1,$(firstword $1)\ $(call tclose,$(sort ${DEP_$(firstword $1)} $(call rest,$1)))) all: ; @echo '$(call reverse,bar,foo)'; \ echo '$(call map,origin,MAKE reverse map)'; \ echo '$(call my-notdir,a/b c/d e/f)'; \ echo '$(call my-foreach)'; \ echo '$(call my-foreach,a,,,)'; \ echo '$(call my-if,a,b,c)'; \ echo '$(call two,bar,baz)'; \ echo '$(call tclose,foo)' EOMAKE # These won't work until/unless PR/1527 is resolved. # echo '$(call my-foreach,a,x y z,$(a)$(a))'; \ # echo '$(call my-if,,$(warning don't print this),ok)' # # $answer = "xx yy zz\nok\n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile); $answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n"; &compare_output($answer, &get_logfile(1)); # TEST eclipsing of arguments when invoking sub-calls $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile2"); print MAKEFILE <<'EOF'; all = $1 $2 $3 $4 $5 $6 $7 $8 $9 level1 = $(call all,$1,$2,$3,$4,$5) level2 = $(call level1,$1,$2,$3) level3 = $(call level2,$1,$2,$3,$4,$5) all: @echo $(call all,1,2,3,4,5,6,7,8,9,10,11) @echo $(call level1,1,2,3,4,5,6,7,8) @echo $(call level2,1,2,3,4,5,6,7,8) @echo $(call level3,1,2,3,4,5,6,7,8) EOF close(MAKEFILE); &run_make_with_options($makefile2, "", &get_logfile); $answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n"; &compare_output($answer,&get_logfile(1)); # Ensure that variables are defined in global scope even in a $(call ...) delete $ENV{X123}; run_make_test(' tst = $(eval export X123) $(call tst) all: ; @echo "$${X123-not set}" ', '', "\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/dir000066400000000000000000000021431317072305000223350ustar00rootroot00000000000000$description = "The following test creates a makefile to test the dir " ."function."; $details = ""; # IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(dir src${pathsep}foo.c hacks) \n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "src${pathsep} .${pathsep}\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/error000066400000000000000000000030531317072305000227110ustar00rootroot00000000000000# -*-Perl-*- $description = "\ The following test creates a makefile to test the error function."; $details = ""; open(MAKEFILE,"> $makefile"); print MAKEFILE 'err = $(error Error found!) ifdef ERROR1 $(error error is $(ERROR1)) endif ifdef ERROR2 $(error error is $(ERROR2)) endif ifdef ERROR3 all: some; @echo $(error error is $(ERROR3)) endif ifdef ERROR4 all: some; @echo error is $(ERROR4) @echo $(error error is $(ERROR4)) endif some: ; @echo Some stuff testvar: ; @: $(err) '; close(MAKEFILE); # Test #1 &run_make_with_options($makefile, "ERROR1=yes", &get_logfile, 512); $answer = "$makefile:4: *** error is yes. Stop.\n"; &compare_output($answer,&get_logfile(1)); # Test #2 &run_make_with_options($makefile, "ERROR2=no", &get_logfile, 512); $answer = "$makefile:8: *** error is no. Stop.\n"; &compare_output($answer,&get_logfile(1)); # Test #3 &run_make_with_options($makefile, "ERROR3=maybe", &get_logfile, 512); $answer = "Some stuff\n$makefile:12: *** error is maybe. Stop.\n"; &compare_output($answer,&get_logfile(1)); # Test #4 &run_make_with_options($makefile, "ERROR4=definitely", &get_logfile, 512); $answer = "Some stuff\n$makefile:16: *** error is definitely. Stop.\n"; &compare_output($answer,&get_logfile(1)); # Test #5 &run_make_with_options($makefile, "testvar", &get_logfile, 512); $answer = "$makefile:22: *** Error found!. Stop.\n"; &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/eval000066400000000000000000000067001317072305000225110ustar00rootroot00000000000000# -*-perl-*- $description = "Test the eval function."; $details = "This is a test of the eval function in GNU make. This function will evaluate inline makefile syntax and incorporate the results into its internal database.\n"; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; define Y all:: ; @echo $AA A = B endef X = $(eval $(value Y)) $(eval $(shell echo A = A)) $(eval $(Y)) $(eval A = C) $(eval $(X)) EOF close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile); # Create the answer to what should be produced by this Makefile $answer = "AA\nBA\n"; &compare_output($answer,&get_logfile(1)); # Test to make sure defining variables when we have extra scope pushed works # as expected. $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile2"); print MAKEFILE <<'EOF'; VARS = A B VARSET = $(1) = $(2) $(foreach v,$(VARS),$(eval $(call VARSET,$v,$v))) all: ; @echo A = $(A) B = $(B) EOF close(MAKEFILE); &run_make_with_options($makefile2, "", &get_logfile); # Create the answer to what should be produced by this Makefile $answer = "A = A B = B\n"; &compare_output($answer,&get_logfile(1)); # Test to make sure eval'ing inside conditionals works properly $makefile3 = &get_tmpfile; open(MAKEFILE,"> $makefile3"); print MAKEFILE <<'EOF'; FOO = foo all:: ; @echo it define Y all:: ; @echo worked endef ifdef BAR $(eval $(Y)) endif EOF close(MAKEFILE); &run_make_with_options($makefile3, "", &get_logfile); $answer = "it\n"; &compare_output($answer,&get_logfile(1)); &run_make_with_options($makefile3, "BAR=1", &get_logfile); $answer = "it\nworked\n"; &compare_output($answer,&get_logfile(1)); # TEST very recursive invocation of eval $makefile3 = &get_tmpfile; open(MAKEFILE,"> $makefile3"); print MAKEFILE <<'EOF'; ..9 := 0 1 2 3 4 5 6 7 8 9 rev=$(eval res:=)$(foreach word,$1,$(eval res:=${word} ${res}))${res} a:=$(call rev,${..9}) all: ; @echo '[$(a)]' EOF close(MAKEFILE); &run_make_with_options($makefile3, "", &get_logfile); $answer = "[ 9 8 7 6 5 4 3 2 1 0 ]\n"; &compare_output($answer,&get_logfile(1)); # TEST eval with no filename context. # The trick here is that because EVAR is taken from the environment, it must # be evaluated before every command is invoked. Make sure that works, when # we have no file context for reading_file (bug # 6195) $makefile4 = &get_tmpfile; open(MAKEFILE,"> $makefile4"); print MAKEFILE <<'EOF'; EVAR = $(eval FOBAR = 1) all: ; @echo "OK" EOF close(MAKEFILE); $extraENV{EVAR} = '1'; &run_make_with_options($makefile4, "", &get_logfile); $answer = "OK\n"; &compare_output($answer,&get_logfile(1)); # Clean out previous information to allow new run_make_test() interface. # If we ever convert all the above to run_make_test() we can remove this line. $makefile = undef; # Test handling of backslashes in strings to be evaled. run_make_test(' define FOO all: ; @echo hello \ world endef $(eval $(FOO)) ', '', 'hello world'); run_make_test(' define FOO all: ; @echo '."'".'he\llo'."'".' @echo world endef $(eval $(FOO)) ', '', 'he\llo world'); # We don't allow new target/prerequisite relationships to be defined within a # command script, because these are evaluated after snap_deps() and that # causes lots of problems (like core dumps!) # See Savannah bug # 12124. run_make_test('deps: ; $(eval deps: foo)', '', '#MAKEFILE#:1: *** prerequisites cannot be defined in recipes. Stop.', 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/file000066400000000000000000000035741317072305000225070ustar00rootroot00000000000000# -*-perl-*- $description = 'Test the $(file ...) function.'; # Test > and >> run_make_test(q! define A a b endef B = c d $(file >file.out,$(A)) $(foreach L,$(B),$(file >> file.out,$L)) x:;@echo hi; cat file.out !, '', "hi\na\nb\nc\nd"); unlink('file.out'); # Test >> to a non-existent file run_make_test(q! define A a b endef $(file >> file.out,$(A)) x:;@cat file.out !, '', "a\nb"); unlink('file.out'); # Test > with no content run_make_test(q! $(file >4touch) .PHONY:x x:;@cat 4touch !, '', ''); # Test >> with no content run_make_test(q! $(file >>4touch) .PHONY:x x:;@cat 4touch !, '', ''); unlink('4touch'); # Test > to a read-only file touch('file.out'); chmod(0444, 'file.out'); # Find the error that will be printed # This seems complicated, but we need the message from the C locale my $loc = undef; if ($has_POSIX) { $loc = POSIX::setlocale(POSIX::LC_MESSAGES); POSIX::setlocale(POSIX::LC_MESSAGES, 'C'); } my $e; open(my $F, '>', 'file.out') and die "Opened read-only file!\n"; $e = "$!"; $loc and POSIX::setlocale(POSIX::LC_MESSAGES, $loc); run_make_test(q! define A a b endef $(file > file.out,$(A)) x:;@cat file.out !, '', "#MAKEFILE#:6: *** open: file.out: $e. Stop.", 512); unlink('file.out'); # Use variables for operator and filename run_make_test(q! define A a b endef OP = > FN = file.out $(file $(OP) $(FN),$(A)) x:;@cat file.out !, '', "a\nb"); unlink('file.out'); # Don't add newlines if one already exists run_make_test(q! define A a b endef $(file >file.out,$(A)) x:;@cat file.out !, '', "a\nb"); unlink('file.out'); # Empty text run_make_test(q! $(file >file.out,) $(file >>file.out,) x:;@cat file.out !, '', "\n\n"); unlink('file.out'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/filter-out000066400000000000000000000027551317072305000236620ustar00rootroot00000000000000# -*-perl-*- $description = "Test the filter and filter-out functions."; $details = "The makefile created in this test has two variables. The filter-out function is first used to discard names ending in .o with a single simple pattern. The second filter-out function augments the simple pattern with three literal names, which are also added to the text argument. This tests an internal hash table which is only used if there are multiple literals present in both the pattern and text arguments. The result of both filter-out functions is the same single .elc name.\n"; # Basic test -- filter run_make_test(q! files1 := $(filter %.o, foo.elc bar.o lose.o) files2 := $(filter %.o foo.i, foo.i bar.i lose.i foo.elc bar.o lose.o) all: ; @echo '$(files1) $(files2)' !, '', "bar.o lose.o foo.i bar.o lose.o\n"); # Basic test -- filter-out run_make_test(q! files1 := $(filter-out %.o, foo.elc bar.o lose.o) files2 := $(filter-out foo.i bar.i lose.i %.o, foo.i bar.i lose.i foo.elc bar.o lose.o) all: ; @echo '$(files1) $(files2)' !, '', "foo.elc foo.elc\n"); # Escaped patterns run_make_test(q!all:;@echo '$(filter foo\%bar,foo%bar fooXbar)'!, '', "foo%bar\n"); run_make_test(q!all:;@echo '$(filter foo\%\%\\\\\%\%bar,foo%%\\%%bar fooX\\Ybar)'!, '', "foo%%\\%%bar\n"); run_make_test(q! X = $(filter foo\\\\\%bar,foo\%bar foo\Xbar) all:;@echo '$(X)'!, '', "foo\\%bar\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/findstring000066400000000000000000000022311317072305000237240ustar00rootroot00000000000000$description = "The following test creates a makefile to test the findstring " ."function."; $details = ""; # IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(findstring port, reporter)\n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile, 0); # Create the answer to what should be produced by this Makefile $answer = "port\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/flavor000066400000000000000000000011171317072305000230500ustar00rootroot00000000000000# -*-perl-*- $description = "Test the flavor function."; $details = ""; # Test #1: Test general logic. # run_make_test(' s := s r = r $(info u $(flavor u)) $(info s $(flavor s)) $(info r $(flavor r)) ra += ra rc ?= rc $(info ra $(flavor ra)) $(info rc $(flavor rc)) s += s r += r $(info s $(flavor s)) $(info r $(flavor r)) .PHONY: all all:;@: ', '', 'u undefined s simple r recursive ra recursive rc recursive s simple r recursive'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/foreach000066400000000000000000000040711317072305000231700ustar00rootroot00000000000000# -*-perl-*- # $Id$ $description = "Test the foreach function."; $details = "This is a test of the foreach function in gnu make. This function starts with a space separated list of names and a variable. Each name in the list is subsituted into the variable and the given text evaluated. The general form of the command is $(foreach var,$list,$text). Several types of foreach loops are tested\n"; # TEST 0 # Set an environment variable that we can test in the makefile. $extraENV{FOOFOO} = 'foo foo'; run_make_test("space = ' '".' null := auto_var = udef space CC null FOOFOO MAKE foo CFLAGS WHITE @ < foo = bletch null @ garf av = $(foreach var, $(auto_var), $(origin $(var)) ) override WHITE := BLACK for_var = $(addsuffix .c,foo $(null) $(foo) $(space) $(av) ) fe = $(foreach var2, $(for_var),$(subst .c,.o, $(var2) ) ) all: auto for2 auto : ; @echo $(av) for2: ; @echo $(fe)', '-e WHITE=WHITE CFLAGS=', "undefined file default file environment default file command line override automatic automatic foo.o bletch.o null.o @.o garf.o .o .o undefined.o file.o default.o file.o environment.o default.o file.o command.o line.o override.o automatic.o automatic.o"); delete $extraENV{FOOFOO}; # TEST 1: Test that foreach variables take precedence over global # variables in a global scope (like inside an eval). Tests bug #11913 run_make_test(' .PHONY: all target all: target x := BAD define mktarget target: x := $(x) target: ; @echo "$(x)" endef x := GLOBAL $(foreach x,FOREACH,$(eval $(value mktarget)))', '', 'FOREACH'); # TEST 2: Check some error conditions. run_make_test(' x = $(foreach ) y = $x all: ; @echo $y', '', "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.", 512); run_make_test(' x = $(foreach ) y := $x all: ; @echo $y', '', "#MAKEFILE#:2: *** insufficient number of arguments (1) to function 'foreach'. Stop.", 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/guile000066400000000000000000000050341317072305000226660ustar00rootroot00000000000000# -*-perl-*- $description = 'Test the $(guile ...) function.'; $details = 'This only works on systems that support it.'; # If this instance of make doesn't support GNU Guile, skip it # This detects if guile is loaded using the "load" directive # $makefile = get_tmpfile(); # open(MAKEFILE, "> $makefile") || die "Failed to open $makefile: $!\n"; # print MAKEFILE q! # -load guile # all: ; @echo $(filter guile,$(.LOADED)) # !; # close(MAKEFILE) || die "Failed to write $makefile: $!\n"; # $cmd = subst_make_string("#MAKEPATH# -f $makefile"); # $log = get_logfile(0); # $code = run_command_with_output($log, $cmd); # read_file_into_string ($log) eq "guile\n" and $FEATURES{guile} = 1; # If we don't have Guile support, never mind. exists $FEATURES{guile} or return -1; # Verify simple data type conversions # Currently we don't support vectors: # echo '$(guile (vector 1 2 3))'; \ run_make_test(q! x:;@echo '$(guile #f)'; \ echo '$(guile #t)'; \ echo '$(guile #\c)'; \ echo '$(guile 1234)'; \ echo '$(guile 'foo)'; \ echo '$(guile "bar")'; \ echo '$(guile (cons 'a 'b))'; \ echo '$(guile '(a b (c . d) 1 (2) 3))' !, '', "\n#t\nc\n1234\nfoo\nbar\na b\na b c d 1 2 3"); # Verify the gmk-expand function run_make_test(q! VAR = $(guile (gmk-expand "$(shell echo hi)")) x:;@echo '$(VAR)' !, '', "hi"); # Verify the gmk-eval function # Prove that the string is expanded only once (by eval) run_make_test(q! TEST = bye EVAL = VAR = $(TEST) $(shell echo there) $(guile (gmk-eval "$(value EVAL)")) TEST = hi x:;@echo '$(VAR)' !, '', "hi there"); # Verify the gmk-eval function with a list run_make_test(q! $(guile (gmk-eval '(VAR = 1 (2) () 3))) x:;@echo '$(VAR)' !, '', "1 2 3"); # Verify the gmk-var function run_make_test(q! VALUE = hi $(shell echo there) VAR = $(guile (gmk-var "VALUE")) x:;@echo '$(VAR)' !, '', "hi there"); # Verify the gmk-var function with a symbol run_make_test(q! VALUE = hi $(shell echo there) VAR = $(guile (gmk-var 'VALUE)) x:;@echo '$(VAR)' !, '', "hi there"); # Write a Guile program using define and run it run_make_test(q! # Define the "fib" function in Guile define fib ;; A procedure for counting the n:th Fibonacci number ;; See SICP, p. 37 (define (fib n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2)))))) endef $(guile $(fib)) # Now run it x:;@echo $(guile (fib $(FIB))) !, 'FIB=10', "55"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/if000066400000000000000000000016471317072305000221650ustar00rootroot00000000000000# -*-perl-*- $description = "Test the if function.\n"; $details = "Try various uses of if and ensure they all give the correct results.\n"; open(MAKEFILE, "> $makefile"); print MAKEFILE <1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(join a b c,foo hacks .pl1) \n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "afoo bhacks c.pl1\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/notdir000066400000000000000000000021451317072305000230600ustar00rootroot00000000000000$description = "The following test creates a makefile to test the notdir " ."function."; $details = ""; # IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := \$(notdir ${pathsep}src${pathsep}foo.c hacks) \n" ."all: \n" ."\t\@echo \$(string) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "foo.c hacks\n"; # COMPARE RESULTS # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/origin000066400000000000000000000025001317072305000230430ustar00rootroot00000000000000# -*-perl-*- $description = "Test the origin function."; $details = "This is a test of the origin function in gnu make. This function will report on where a variable was defined per the following list: 'undefined' never defined 'default' default definition 'environment' environment var without -e 'environment override' environment var with -e 'file' defined in makefile 'command line' defined on the command line 'override' defined by override in makefile 'automatic' Automatic variable\n"; # Set an environment variable $extraENV{MAKETEST} = 1; run_make_test(' foo := bletch garf auto_var = undefined CC MAKETEST MAKE foo CFLAGS WHITE @ av = $(foreach var, $(auto_var), $(origin $(var)) ) override WHITE := BLACK all: auto @echo $(origin undefined) @echo $(origin CC) @echo $(origin MAKETEST) @echo $(origin MAKE) @echo $(origin foo) @echo $(origin CFLAGS) @echo $(origin WHITE) @echo $(origin @) auto : @echo $(av)', '-e WHITE=WHITE CFLAGS=', 'undefined default environment default file command line override automatic undefined default environment default file command line override automatic'); # Reset an environment variable delete $extraENV{MAKETEST}; 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/realpath000066400000000000000000000022261317072305000233610ustar00rootroot00000000000000# -*-perl-*- $description = "Test the realpath functions."; $details = ""; run_make_test(' ifneq ($(realpath .),$(CURDIR)) $(error ) endif ifneq ($(realpath ./),$(CURDIR)) $(error ) endif ifneq ($(realpath .///),$(CURDIR)) $(error ) endif ifneq ($(realpath /),/) $(error ) endif ifneq ($(realpath /.),/) $(error ) endif ifneq ($(realpath /./),/) $(error ) endif ifneq ($(realpath /.///),/) $(error ) endif ifneq ($(realpath /..),/) $(error ) endif ifneq ($(realpath /../),/) $(error ) endif ifneq ($(realpath /..///),/) $(error ) endif ifneq ($(realpath . /..),$(CURDIR) /) $(error ) endif .PHONY: all all: ; @: ', '', ''); # On Windows platforms, "//" means something special. So, don't do these # tests there. if ($port_type ne 'W32') { run_make_test(' ifneq ($(realpath ///),/) $(error ) endif ifneq ($(realpath ///.),/) $(error ) endif ifneq ($(realpath ///..),/) $(error ) endif .PHONY: all all: ; @:', '', ''); } # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/shell000066400000000000000000000012701317072305000226660ustar00rootroot00000000000000# -*-perl-*- $description = 'Test the $(shell ...) function.'; $details = ''; # Test shells inside rules. run_make_test('.PHONY: all all: ; @echo $(shell echo hi) ','','hi'); # Test unescaped comment characters in shells. Savannah bug #20513 if ($all_tests) { run_make_test(q! FOO := $(shell echo '#') foo: ; echo '$(FOO)' !, '', "#\n"); } # Test shells inside exported environment variables. # This is the test that fails if we try to put make exported variables into # the environment for a $(shell ...) call. run_make_test(' export HI = $(shell echo hi) .PHONY: all all: ; @echo $$HI ','','hi'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/sort000066400000000000000000000031651317072305000225530ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to verify the ability of make to sort lists of object. Sort will also remove any duplicate entries. This will also be tested."; $details = "The make file is built with a list of object in a random order and includes some duplicates. Make should sort all of the elements remove all duplicates\n"; run_make_test(' foo := moon_light days foo1:= jazz bar := captured bar2 = boy end, has rise A midnight bar3:= $(foo) s1 := _by s2 := _and_a t1 := $(addsuffix $(s1), $(bar) ) t2 := $(addsuffix $(s2), $(foo1) ) t3 := $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) $(t2) t4 := $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) $(t3) t5 := $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) $(t4) t6 := $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) $(t5) t7 := $(t6) $(t6) $(t6) p1 := $(addprefix $(foo1), $(s2) ) blank:= all: @echo $(sort $(bar2) $(foo) $(addsuffix $(s1), $(bar) ) $(t2) $(bar2) $(bar3)) @echo $(sort $(blank) $(foo) $(bar2) $(t1) $(p1) ) @echo $(sort $(foo) $(bar2) $(t1) $(t4) $(t5) $(t7) $(t6) ) ', '', 'A boy captured_by days end, has jazz_and_a midnight moon_light rise A boy captured_by days end, has jazz_and_a midnight moon_light rise A boy captured_by days end, has jazz_and_a midnight moon_light rise '); # Test with non-space/tab whitespace. Note that you can't see the # original bug except using valgrind. run_make_test("FOO = a b\tc\rd\fe \f \f \f \f \ff all: ; \@echo \$(words \$(sort \$(FOO)))\n", '', "5\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/strip000066400000000000000000000032461317072305000227250ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to verify the ability of make to strip white space from lists of object.\n"; $details = "The make file is built with a list of objects that contain white space These are then run through the strip command to remove it. This is then verified by echoing the result.\n"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<'EOMAKE'; TEST1 := "Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING..." E := TEST2 := $E try this and this $E define TEST3 and these test out some blank lines endef .PHONY: all all: @echo '$(strip $(TEST1) )' @echo '$(strip $(TEST2) )' @echo '$(strip $(TEST3) )' space: ; @echo '$(strip ) $(strip )' EOMAKE # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile); $answer = "\"Is this TERMINAL fun? What makes you believe is this terminal fun? JAPAN is a WONDERFUL planet -- I wonder if we will ever reach their level of COMPARATIVE SHOPPING...\" try this and this and these test out some blank lines "; &compare_output($answer,&get_logfile(1)); &run_make_with_options($makefile,"space",&get_logfile); $answer = " \n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/substitution000066400000000000000000000015721317072305000243400ustar00rootroot00000000000000# -*-perl-*- $description = "Test the subst and patsubst functions"; $details = ""; # Generic patsubst test: test both the function and variable form. run_make_test(' foo := a.o b.o c.o bar := $(foo:.o=.c) bar2:= $(foo:%.o=%.c) bar3:= $(patsubst %.c,%.o,x.c.c bar.c) all:;@echo $(bar); echo $(bar2); echo $(bar3)', '', 'a.c b.c c.c a.c b.c c.c x.c.o bar.o'); # Patsubst without '%'--shouldn't match because the whole word has to match # in patsubst. Based on a bug report by Markus Mauhart run_make_test('all:;@echo $(patsubst Foo,Repl,FooFoo)', '', 'FooFoo'); # Variable subst where a pattern matches multiple times in a single word. # Based on a bug report by Markus Mauhart run_make_test(' A := fooBARfooBARfoo all:;@echo $(A:fooBARfoo=REPL)', '', 'fooBARREPL'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/suffix000066400000000000000000000040471317072305000230700ustar00rootroot00000000000000$description = "The following test creates a makefile to test the suffix\n" ."function. \n"; $details = "The suffix function will return the string following the last _._\n" ."the list provided. It will provide all of the unique suffixes found\n" ."in the list. The long strings are sorted to remove duplicates.\n"; # IF YOU NEED >1 MAKEFILE FOR THIS TEST, USE &get_tmpfile; TO GET # THE NAME OF THE MAKEFILE. THIS INSURES CONSISTENCY AND KEEPS TRACK OF # HOW MANY MAKEFILES EXIST FOR EASY DELETION AT THE END. # EXAMPLE: $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "string := word.pl general_test2.pl1 FORCE.pl word.pl3 generic_test.perl /tmp.c/bar foo.baz/bar.c MAKEFILES_variable.c\n" ."string2 := \$(string) \$(string) \$(string) \$(string) \$(string) \$(string) \$(string)\n" ."string3 := \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2) \$(string2)\n" ."string4 := \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3) \$(string3)\n" ."all: \n" ."\t\@echo \$(suffix \$(string)) \n" ."\t\@echo \$(sort \$(suffix \$(string4))) \n" ."\t\@echo \$(suffix \$(string) a.out) \n" ."\t\@echo \$(sort \$(suffix \$(string3))) \n"; # END of Contents of MAKEFILE close(MAKEFILE); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile # COMPARE RESULTS $answer = ".pl .pl1 .pl .pl3 .perl .c .c\n" .".c .perl .pl .pl1 .pl3\n" .".pl .pl1 .pl .pl3 .perl .c .c .out\n" .".c .perl .pl .pl1 .pl3\n"; # In this call to compare output, you should use the call &get_logfile(1) # to send the name of the last logfile created. You may also use # the special call &get_logfile(1) which returns the same as &get_logfile(1). &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/value000066400000000000000000000013341317072305000226740ustar00rootroot00000000000000# -*-perl-*- $description = "Test the value function."; $details = "This is a test of the value function in GNU make. This function will evaluate to the value of the named variable with no further expansion performed on it.\n"; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; export FOO = foo recurse = FOO = $FOO static := FOO = $(value FOO) all: ; @echo $(recurse) $(value recurse) $(static) $(value static) EOF close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile); # Create the answer to what should be produced by this Makefile $answer = "FOO = OO FOO = foo FOO = foo FOO = foo\n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/warning000066400000000000000000000025571317072305000232350ustar00rootroot00000000000000# -*-Perl-*- $description = "\ The following test creates a makefile to test the warning function."; $details = ""; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; ifdef WARNING1 $(warning warning is $(WARNING1)) endif ifdef WARNING2 $(warning warning is $(WARNING2)) endif ifdef WARNING3 all: some; @echo hi $(warning warning is $(WARNING3)) endif ifdef WARNING4 all: some; @echo hi @echo there $(warning warning is $(WARNING4)) endif some: ; @echo Some stuff EOF close(MAKEFILE); # Test #1 &run_make_with_options($makefile, "WARNING1=yes", &get_logfile, 0); $answer = "$makefile:2: warning is yes\nSome stuff\n"; &compare_output($answer,&get_logfile(1)); # Test #2 &run_make_with_options($makefile, "WARNING2=no", &get_logfile, 0); $answer = "$makefile:6: warning is no\nSome stuff\n"; &compare_output($answer,&get_logfile(1)); # Test #3 &run_make_with_options($makefile, "WARNING3=maybe", &get_logfile, 0); $answer = "Some stuff\n$makefile:10: warning is maybe\nhi\n"; &compare_output($answer,&get_logfile(1)); # Test #4 &run_make_with_options($makefile, "WARNING4=definitely", &get_logfile, 0); $answer = "Some stuff\n$makefile:14: warning is definitely\nhi\nthere\n"; &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/functions/wildcard000066400000000000000000000046001317072305000233500ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test wildcard expansions and the ability to put a command on the same line as the target name separated by a semi-colon."; $details = "\ This test creates 4 files by the names of 1.example, two.example and 3.example. We execute three tests. The first executes the print1 target which tests the '*' wildcard by echoing all filenames by the name of '*.example'. The second test echo's all files which match '?.example' and [a-z0-9].example. Lastly we clean up all of the files using the '*' wildcard as in the first test"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE < $makefile"); print MAKEFILE <<'EOF'; string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string) string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) all: @echo $(words $(string)) @echo $(words $(string4)) @echo $(word 1, $(string)) @echo $(word 100, $(string)) @echo $(word 1, $(string)) @echo $(word 1000, $(string3)) @echo $(wordlist 3, 4, $(string)) @echo $(wordlist 4, 3, $(string)) @echo $(wordlist 1, 6, $(string)) @echo $(wordlist 5, 7, $(string)) @echo $(wordlist 100, 110, $(string)) @echo $(wordlist 7, 10, $(string2)) EOF close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile); $answer = "6\n" ."2058\n" ."word.pl\n" ."\n" ."word.pl\n" ."\n" ."FORCE.pl word.pl\n" ."\n" ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n" ."generic_test.perl MAKEFILES_variable.pl\n" ."\n" ."word.pl general_test2.pl FORCE.pl word.pl\n"; &compare_output($answer, &get_logfile(1)); # Test error conditions run_make_test('FOO = foo bar biz baz word-e1: ; @echo $(word ,$(FOO)) word-e2: ; @echo $(word abc ,$(FOO)) word-e3: ; @echo $(word 1a,$(FOO)) wordlist-e1: ; @echo $(wordlist ,,$(FOO)) wordlist-e2: ; @echo $(wordlist abc ,,$(FOO)) wordlist-e3: ; @echo $(wordlist 1, 12a ,$(FOO))', 'word-e1', "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.", 512); run_make_test(undef, 'word-e2', "#MAKEFILE#:4: *** non-numeric first argument to 'word' function: 'abc '. Stop.", 512); run_make_test(undef, 'word-e3', "#MAKEFILE#:5: *** non-numeric first argument to 'word' function: '1a'. Stop.", 512); run_make_test(undef, 'wordlist-e1', "#MAKEFILE#:7: *** non-numeric first argument to 'wordlist' function: ''. Stop.", 512); run_make_test(undef, 'wordlist-e2', "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' function: 'abc '. Stop.", 512); run_make_test(undef, 'wordlist-e3', "#MAKEFILE#:9: *** non-numeric second argument to 'wordlist' function: ' 12a '. Stop.", 512); # Test error conditions again, but this time in a variable reference run_make_test('FOO = foo bar biz baz W = $(word $x,$(FOO)) WL = $(wordlist $s,$e,$(FOO)) word-e: ; @echo $(W) wordlist-e: ; @echo $(WL)', 'word-e x=', "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: ''. Stop.", 512); run_make_test(undef, 'word-e x=abc', "#MAKEFILE#:3: *** non-numeric first argument to 'word' function: 'abc'. Stop.", 512); run_make_test(undef, 'word-e x=0', "#MAKEFILE#:3: *** first argument to 'word' function must be greater than 0. Stop.", 512); run_make_test(undef, 'wordlist-e s= e=', "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: ''. Stop.", 512); run_make_test(undef, 'wordlist-e s=abc e=', "#MAKEFILE#:4: *** non-numeric first argument to 'wordlist' function: 'abc'. Stop.", 512); run_make_test(undef, 'wordlist-e s=4 e=12a', "#MAKEFILE#:4: *** non-numeric second argument to 'wordlist' function: '12a'. Stop.", 512); run_make_test(undef, 'wordlist-e s=0 e=12', "#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.", 512); # TEST #8 -- test $(firstword ) # run_make_test(' void := list := $(void) foo bar baz # a := $(word 1,$(list)) b := $(firstword $(list)) .PHONY: all all: @test "$a" = "$b" && echo $a ', '', 'foo'); # TEST #9 -- test $(lastword ) # run_make_test(' void := list := $(void) foo bar baz # a := $(word $(words $(list)),$(list)) b := $(lastword $(list)) .PHONY: all all: @test "$a" = "$b" && echo $a ', '', 'baz'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/000077500000000000000000000000001317072305000205575ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/bs-nl000066400000000000000000000053001317072305000215130ustar00rootroot00000000000000# -*-perl-*- $description = "Test backslash-newline handling."; $details = ""; # TEST #1 # ------- # Backslash-newlines in recipes # These are basic backslash-newlines with no tricks run_make_test("fast:;\@echo fa\\\nst\n", '', 'fast'); run_make_test("slow:;\@: no-op; echo sl\\\now\n", '', 'slow'); run_make_test("dquote:;\@echo \"dqu\\\note\"\n", '', 'dquote'); run_make_test("squote:;\@echo 'squ\\\note'\n", '', "squ\\\note"); # Ensure that a leading prefix character is omitted run_make_test("fast:;\@echo fa\\\n\tst\n", '', 'fast'); run_make_test("slow:;\@: no-op; echo sl\\\n\tow\n", '', 'slow'); run_make_test("dquote:;\@echo \"dqu\\\n\tote\"\n", '', 'dquote'); run_make_test("squote:;\@echo 'squ\\\n\tote'\n", '', "squ\\\note"); # Ensure that ONLY the leading prefix character is omitted run_make_test("fast:;\@echo fa\\\n\t st\n", '', 'fa st'); run_make_test("slow:;\@: no-op; echo sl\\\n\t\tow\n", '', "sl ow"); run_make_test("dquote:;\@echo \"dqu\\\n\t ote\"\n", '', 'dqu ote'); run_make_test("squote:;\@echo 'squ\\\n\t\t ote'\n", '', "squ\\\n\t ote"); # Backslash-newlines in variable values # Simple run_make_test(q! var = he\ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # Condense trailing space run_make_test(q! var = he \ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # Remove leading space run_make_test(q! var = he\ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # Multiple bs/nl condensed run_make_test(q! var = he\ \ \ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # POSIX: Preserve trailing space run_make_test(q! .POSIX: x = y var = he \ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # POSIX: One space per bs-nl run_make_test(q! .POSIX: x = y var = he\ \ \ llo var:;@echo '|$(var)|'!, '', "|he llo|"); # Savannah #39035: handle whitespace in call run_make_test(q! f = echo $(1) t:; @$(call f,"a \ b"); \ $(call f,"a \ b") !, '', "a b\na b\n"); # Savannah #38945: handle backslash CRLF # We need our own makefile so we can set binmode my $m1 = get_tmpfile(); open(MAKEFILE, "> $m1"); binmode(MAKEFILE); print MAKEFILE "FOO = foo \\\r\n"; close(MAKEFILE); my $m2 = get_tmpfile(); open(MAKEFILE, "> $m2"); print MAKEFILE "include $m1\ndefine BAR\nall: ; \@echo \$(FOO) bar\nendef\n\$(eval \$(BAR))\n"; close(MAKEFILE); run_make_with_options($m2, '', get_logfile()); compare_output("foo bar\n", get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/close_stdout000066400000000000000000000003741317072305000232150ustar00rootroot00000000000000# -*-perl-*- $description = "Make sure make exits with an error if stdout is full."; if (-e '/dev/full') { run_make_test('', '-v > /dev/full', '/^#MAKE#: write error/', 256); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/fopen-fail000066400000000000000000000007621317072305000225270ustar00rootroot00000000000000# -*-perl-*- $description = "Make sure make exits with an error if fopen fails."; # Recurse infinitely until we run out of open files, and ensure we # fail with a non-zero exit code. Don't bother to test the output # since it's hard to know what it will be, exactly. # See Savannah bug #27374. if ($ENV{TRAVIS}) { 1/0 } return -1; run_make_test(q! include $(lastword $(MAKEFILE_LIST)) !, '', undef, 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/general1000066400000000000000000000027761317072305000222140ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test the simple functionality of make. It mimics the rebuilding of a product with dependencies. It also tests the simple definition of VPATH."; open(MAKEFILE,"> $makefile"); print MAKEFILE < $makefile"); # The contents of the Makefile ... print MAKEFILE < $makefile2"); print MAKEFILE "all:;\@echo FOO = \$(FOO)\nFOO = foo"; close(MAKEFILE); &run_make_with_options($makefile2,"",&get_logfile); $answer = "FOO = foo\n"; &compare_output($answer,&get_logfile(1)); # TEST 3 # Check semicolons in variable references run_make_test(' $(if true,$(info true; true)) all: ; @: ', '', 'true; true'); # TEST 4 # Check that backslashes in command scripts are handled according to POSIX. # Checks Savannah bug # 1332. # Test the fastpath / no quotes run_make_test(' all: @echo foo\ bar @echo foo\ bar @echo foo\ bar @echo foo\ bar @echo foo \ bar @echo foo \ bar @echo foo \ bar @echo foo \ bar ', '', 'foobar foobar foo bar foo bar foo bar foo bar foo bar foo bar'); # Test the fastpath / single quotes run_make_test(" all: \@echo 'foo\\ bar' \@echo 'foo\\ bar' \@echo 'foo\\ bar' \@echo 'foo\\ bar' \@echo 'foo \\ bar' \@echo 'foo \\ bar' \@echo 'foo \\ bar' \@echo 'foo \\ bar' ", '', 'foo\ bar foo\ bar foo\ bar foo\ bar foo \ bar foo \ bar foo \ bar foo \ bar'); # Test the fastpath / double quotes run_make_test(' all: @echo "foo\ bar" @echo "foo\ bar" @echo "foo\ bar" @echo "foo\ bar" @echo "foo \ bar" @echo "foo \ bar" @echo "foo \ bar" @echo "foo \ bar" ', '', 'foobar foobar foo bar foo bar foo bar foo bar foo bar foo bar'); # Test the slow path / no quotes run_make_test(' all: @echo hi; echo foo\ bar @echo hi; echo foo\ bar @echo hi; echo foo\ bar @echo hi; echo foo\ bar @echo hi; echo foo \ bar @echo hi; echo foo \ bar @echo hi; echo foo \ bar @echo hi; echo foo \ bar ', '', 'hi foobar hi foobar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar'); # Test the slow path / no quotes. This time we put the slow path # determination _after_ the backslash-newline handling. run_make_test(' all: @echo foo\ bar; echo hi @echo foo\ bar; echo hi @echo foo\ bar; echo hi @echo foo\ bar; echo hi @echo foo \ bar; echo hi @echo foo \ bar; echo hi @echo foo \ bar; echo hi @echo foo \ bar; echo hi ', '', 'foobar hi foobar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar hi'); # Test the slow path / single quotes run_make_test(" all: \@echo hi; echo 'foo\\ bar' \@echo hi; echo 'foo\\ bar' \@echo hi; echo 'foo\\ bar' \@echo hi; echo 'foo\\ bar' \@echo hi; echo 'foo \\ bar' \@echo hi; echo 'foo \\ bar' \@echo hi; echo 'foo \\ bar' \@echo hi; echo 'foo \\ bar' ", '', 'hi foo\ bar hi foo\ bar hi foo\ bar hi foo\ bar hi foo \ bar hi foo \ bar hi foo \ bar hi foo \ bar'); # Test the slow path / double quotes run_make_test(' all: @echo hi; echo "foo\ bar" @echo hi; echo "foo\ bar" @echo hi; echo "foo\ bar" @echo hi; echo "foo\ bar" @echo hi; echo "foo \ bar" @echo hi; echo "foo \ bar" @echo hi; echo "foo \ bar" @echo hi; echo "foo \ bar" ', '', 'hi foobar hi foobar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar hi foo bar'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/general4000066400000000000000000000035431317072305000222100ustar00rootroot00000000000000# -*-perl-*- $description = "\ This tests random features of make's algorithms, often somewhat obscure, which have either broken at some point in the past or seem likely to break."; run_make_test(' # Make sure that subdirectories built as prerequisites are actually handled # properly. all: dir/subdir/file.a dir/subdir: ; @echo mkdir -p dir/subdir dir/subdir/file.b: dir/subdir ; @echo touch dir/subdir/file.b dir/subdir/%.a: dir/subdir/%.b ; @echo cp $< $@', '', "mkdir -p dir/subdir\ntouch dir/subdir/file.b\ncp dir/subdir/file.b dir/subdir/file.a\n"); # Test implicit rules &touch('foo.c'); run_make_test('foo: foo.o', 'CC="@echo cc" OUTPUT_OPTION=', 'cc -c foo.c cc foo.o -o foo'); unlink('foo.c'); # Test implicit rules with '$' in the name (see se_implicit) run_make_test(q! %.foo : baz$$bar ; @echo 'done $<' %.foo : bar$$baz ; @echo 'done $<' test.foo: baz$$bar bar$$baz: ; @echo '$@' !, '', "baz\$bar\ndone baz\$bar"); # Test implicit rules with '$' in the name (see se_implicit) # Use the '$' in the pattern. run_make_test(q! %.foo : %$$bar ; @echo 'done $<' test.foo: test$$bar: ; @echo '$@' !, '', "test\$bar\ndone test\$bar"); # Make sure that subdirectories built as prerequisites are actually handled # properly... this time with '$' run_make_test(q! all: dir/subdir/file.$$a dir/subdir: ; @echo mkdir -p '$@' dir/subdir/file.$$b: dir/subdir ; @echo touch '$@' dir/subdir/%.$$a: dir/subdir/%.$$b ; @echo 'cp $< $@' !, '', "mkdir -p dir/subdir\ntouch dir/subdir/file.\$b\ncp dir/subdir/file.\$b dir/subdir/file.\$a\n"); # Test odd whitespace at the beginning of a line run_make_test(" all: \f \\ \f \\ \013 \\ all: ; \@echo hi ", '', "hi\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/misc/utf8000066400000000000000000000005021317072305000213650ustar00rootroot00000000000000# -*-perl-*- $description = "Test utf8 handling."; $details = ""; # Variable names containing UTF8 characters run_make_test(" \xe2\x96\xaa := hello \$(info \$(\xe2\x96\xaa)) all: ", '', "hello\n#MAKE#: Nothing to be done for 'all'."); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/000077500000000000000000000000001317072305000213175ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/.gitignore000066400000000000000000000000041317072305000233010ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-B000066400000000000000000000033621317072305000223440ustar00rootroot00000000000000# -*-perl-*- $description = "Test make -B (always remake) option.\n"; $details = "\ Construct a simple makefile that builds a target. Invoke make once, so it builds everything. Invoke it again and verify that nothing is built. Then invoke it with -B and verify that everything is built again."; &touch('bar.x'); run_make_test(' .SUFFIXES: .PHONY: all all: foo foo: bar.x @echo cp $< $@ @echo "" > $@ ', '', 'cp bar.x foo'); run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'."); run_make_test(undef, '-B', 'cp bar.x foo'); # Put the timestamp for foo into the future; it should still be remade. utouch(1000, 'foo'); run_make_test(undef, '', "#MAKE#: Nothing to be done for 'all'."); run_make_test(undef, '-B', 'cp bar.x foo'); # Clean up rmfiles('bar.x', 'foo'); # Test -B with the re-exec feature: we don't want to re-exec forever # Savannah bug # 7566 run_make_test(' all: ; @: $(info MAKE_RESTARTS=$(MAKE_RESTARTS)) include foo.x foo.x: ; @touch $@ ', '-B', 'MAKE_RESTARTS= #MAKEFILE#:4: foo.x: No such file or directory MAKE_RESTARTS=1'); rmfiles('foo.x'); # Test -B with the re-exec feature: we DO want -B in the "normal" part of the # makefile. &touch('blah.x'); run_make_test(' all: blah.x ; @echo $@ $(info MAKE_RESTARTS=$(MAKE_RESTARTS)) include foo.x foo.x: ; @touch $@ blah.x: ; @echo $@ ', '-B', 'MAKE_RESTARTS= #MAKEFILE#:4: foo.x: No such file or directory MAKE_RESTARTS=1 blah.x all'); rmfiles('foo.x', 'blah.x'); # Test that $? is set properly with -B; all prerequisites will be newer! utouch(-10, 'x.b'); touch('x.a'); run_make_test(q! x.a: x.b ; @echo $? !, '-B', "x.b\n"); unlink(qw(x.a x.b)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-C000066400000000000000000000033221317072305000223410ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -C option to GNU make."; $details = "\ This test is similar to the clean test except that this test creates the file to delete in the work directory instead of the current directory. Make is called from another directory using the -C workdir option so that it can both find the makefile and the file to delete in the work directory."; $example = $workdir . $pathsep . "EXAMPLE"; open(MAKEFILE,"> $makefile"); print MAKEFILE < $makefile"); # The Contents of the MAKEFILE ... $mf2 = substr ($makefile2, index ($makefile2, $pathsep) + 1); print MAKEFILE < $makefile2"); print MAKEFILE <> $@ ', '', "echo >> b.x\necho >> a.x"); # Run it again: nothing should happen run_make_test(undef, '', "#MAKE#: 'a.x' is up to date."); # Now run it with -W b.x: should rebuild a.x run_make_test(undef, '-W b.x', 'echo >> a.x'); # Put the timestamp for a.x into the future; it should still be remade. utouch(1000, 'a.x'); run_make_test(undef, '', "#MAKE#: 'a.x' is up to date."); run_make_test(undef, '-W b.x', 'echo >> a.x'); # Clean up rmfiles('a.x', 'b.x'); # Test -W with the re-exec feature: we don't want to re-exec forever # Savannah bug # 7566 # First set it up with a normal build run_make_test(' all: baz.x ; @: include foo.x foo.x: bar.x @echo "\$$(info restarts=\$$(MAKE_RESTARTS))" > $@ @echo "touch $@" bar.x: ; echo >> $@ baz.x: bar.x ; @echo "touch $@" ', '', '#MAKEFILE#:3: foo.x: No such file or directory echo >> bar.x touch foo.x restarts=1 touch baz.x'); # Now run with -W bar.x # Tweak foo.x's timestamp so the update will change it. &utouch(1000, 'foo.x'); run_make_test(undef, '-W bar.x', "restarts=\ntouch foo.x\nrestarts=1\ntouch baz.x"); rmfiles('foo.x', 'bar.x'); # Test -W on vpath-found files: it should take effect. # Savannah bug # 15341 mkdir('x-dir', 0777); utouch(-20, 'x-dir/x'); touch('y'); run_make_test(' y: x ; @echo cp $< $@ ', '-W x-dir/x VPATH=x-dir', 'cp x-dir/x y'); # Make sure ./ stripping doesn't interfere with the match. run_make_test(' y: x ; @echo cp $< $@ ', '-W ./x-dir/x VPATH=x-dir', 'cp x-dir/x y'); run_make_test(undef, '-W x-dir/x VPATH=./x-dir', 'cp ./x-dir/x y'); unlink(qw(y x-dir/x)); rmdir('x-dir'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-e000066400000000000000000000006631317072305000224100ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to ..."; $details = ""; $extraENV{GOOGLE} = 'boggle'; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; GOOGLE = bazzle all:; @echo "$(GOOGLE)" EOF close(MAKEFILE); &run_make_with_options($makefile, '-e' ,&get_logfile); $answer = "boggle\n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-f000066400000000000000000000050311317072305000224030ustar00rootroot00000000000000$description = "The following test tests that if you specify greater \n" ."than one '-f makefilename' on the command line, \n" ."that make concatenates them. This test creates three \n" ."makefiles and specifies all of them with the -f option \n" ."on the command line. To make sure they were concatenated, \n" ."we then call make with the rules from the concatenated \n" ."makefiles one at a time. Finally, it calls all three \n" ."rules in one call to make and checks that the output\n" ."is in the correct order."; $makefile2 = &get_tmpfile; $makefile3 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "all: \n"; print MAKEFILE "\t\@echo This is the output from the original makefile\n"; # END of Contents of MAKEFILE close(MAKEFILE); # Create a second makefile open(MAKEFILE,"> $makefile2"); print MAKEFILE "TWO: \n"; print MAKEFILE "\t\@echo This is the output from makefile 2\n"; close(MAKEFILE); # Create a third makefile open(MAKEFILE,"> $makefile3"); print MAKEFILE "THREE: \n"; print MAKEFILE "\t\@echo This is the output from makefile 3\n"; close(MAKEFILE); # Create the answer to what should be produced by this Makefile $answer = "This is the output from the original makefile\n"; # Run make to catch the default rule &run_make_with_options($makefile,"-f $makefile2 -f $makefile3",&get_logfile,0); &compare_output($answer,&get_logfile(1)); # Run Make again with the rule from the second makefile: TWO $answer = "This is the output from makefile 2\n"; &run_make_with_options($makefile,"-f $makefile2 -f $makefile3 TWO",&get_logfile,0); &compare_output($answer,&get_logfile(1)); # Run Make again with the rule from the third makefile: THREE $answer = "This is the output from makefile 3\n"; &run_make_with_options($makefile, "-f $makefile2 -f $makefile3 THREE", &get_logfile, 0); &compare_output($answer,&get_logfile(1)); # Run Make again with ALL three rules in the order 2 1 3 to make sure # that all rules are executed in the proper order $answer = "This is the output from makefile 2\n"; $answer .= "This is the output from the original makefile\n"; $answer .= "This is the output from makefile 3\n"; &run_make_with_options($makefile, "-f $makefile2 -f $makefile3 TWO all THREE", &get_logfile, 0); &compare_output($answer,&get_logfile(1)); remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-k000066400000000000000000000061761317072305000224230ustar00rootroot00000000000000# -*-perl-*- $description = "Test the make -k (don't stop on error) option.\n"; $details = "\ The makefile created in this test is a simulation of building a small product. However, the trick to this one is that one of the dependencies of the main target does not exist. Without the -k option, make would fail immediately and not build any part of the target. What we are looking for here, is that make builds the rest of the dependencies even though it knows that at the end it will fail to rebuild the main target."; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE < $makefile2"); print MAKEFILE <<'EOF'; .SUFFIXES: all: exe1 exe2; @echo making $@ exe1 exe2: lib; @echo cp $^ $@ lib: foo.o; @echo cp $^ $@ foo.o: ; exit 1 EOF close(MAKEFILE); my $answer = "exit 1 $makefile2:9: recipe for target 'foo.o' failed $makefile2:9: *** [foo.o] Error 1 #0 foo.o at work/options/dash-k.mk.1:9 #1 lib at work/options/dash-k.mk.1:7 #2 exe1 at work/options/dash-k.mk.1:5 #3 all at work/options/dash-k.mk.1:3 $make_name: Target 'all' not remade because of errors. "; my $logfile = &get_logfile; &run_make_with_options($makefile2, "-k", $logfile, $error_code); my $slurp = &read_file_into_string ($logfile); $slurp =~ s{at .*work/options/}{at work/options/}gm; &compare_output_string($answer, $slurp, $logfile); # TEST -- make sure we keep the error code if we can't create an included # makefile. run_make_test('all: ; @echo hi include ifile ifile: no-such-file; @false ', '-k', "#MAKEFILE#:2: ifile: No such file or directory #MAKE#: *** No rule to make target 'no-such-file', needed by 'ifile'. #MAKE#: Failed to remake makefile 'ifile'. hi\n", 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-l000066400000000000000000000030001317072305000224030ustar00rootroot00000000000000# -*-perl-*- # Date: Tue, 11 Aug 1992 09:34:26 -0400 # From: pds@lemming.webo.dg.com (Paul D. Smith) $description = "Test load balancing (-l) option."; $details = "\ This test creates a makefile where all depends on three rules which contain the same body. Each rule checks for the existence of a temporary file; if it exists an error is generated. If it doesn't exist then it is created, the rule sleeps, then deletes the temp file again. Thus if any of the rules are run in parallel the test will fail. When make is called in this test, it is given the -l option with a value of 0.0001. This ensures that the load will be above this number and make will therefore decide that it cannot run more than one job even though -j 4 was also specified on the command line."; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE <<'EOF'; SHELL = /bin/sh define test if [ ! -f test-file ]; then \ echo >> test-file; sleep 2; rm -f test-file; \ else \ echo $@ FAILED; \ fi endef all : ONE TWO THREE ONE : ; @$(test) TWO : ; @$(test) THREE : ; @$(test) EOF # END of Contents of MAKEFILE close(MAKEFILE); $mkoptions = "-l 0.0001"; $mkoptions .= " -j 4" if ($parallel_jobs); # We have to wait longer than the default (5s). &run_make_with_options($makefile, $mkoptions, &get_logfile, 0, 8); $slurp = &read_file_into_string (&get_logfile(1)); if ($slurp !~ /cannot enforce load limit/) { &compare_output("", &get_logfile(1)); } 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-n000066400000000000000000000044131317072305000224160ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -n option.\n"; $details = "Try various uses of -n and ensure they all give the correct results.\n"; touch('orig'); run_make_test(q! final: intermediate ; echo >> $@ intermediate: orig ; echo >> $@ !, '', "echo >> intermediate\necho >> final\n"); # TEST 1 run_make_test(undef, '-Worig -n', "echo >> intermediate\necho >> final\n"); rmfiles(qw(orig intermediate final)); # We consider the actual updated timestamp of targets with all # recursive commands, even with -n. Switching this to the new model # is non-trivial because we use a trick below to change the log content # before we compare it ... $makefile2 = &get_tmpfile; open(MAKEFILE, "> $makefile2"); print MAKEFILE <<'EOF'; .SUFFIXES: BAR = # nothing FOO = +$(BAR) a: b; echo > $@ b: c; $(FOO) EOF close(MAKEFILE); &utouch(-20, 'b'); &utouch(-10, 'a'); &touch('c'); # TEST 2 &run_make_with_options($makefile2, "", &get_logfile); $answer = "$make_name: 'a' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST 3 &run_make_with_options($makefile2, "-n", &get_logfile); $answer = "$make_name: 'a' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST 4 unlink(qw(a b)); &run_make_with_options($makefile2, "-t -n", &get_logfile); open(DASH_N_LOG, ">>" . &get_logfile(1)); print DASH_N_LOG "a exists but should not!\n" if -e 'a'; print DASH_N_LOG "b exists but should not!\n" if -e 'b'; close(DASH_N_LOG); &compare_output("touch b\ntouch a\n", &get_logfile(1)); # CLEANUP unlink(qw(a b c)); # Ensure -n continues to be included with recursive/re-execed make # See Savannah bug #38051 $topmake = &get_tmpfile; $submake = &get_tmpfile; open(MAKEFILE, "> $topmake"); print MAKEFILE <<"EOF"; foo: ; \@\$(MAKE) -f "$submake" bar EOF close(MAKEFILE); # The bar target should print what would happen, but not actually run open(MAKEFILE, "> $submake"); print MAKEFILE <<'EOF'; inc: ; touch $@ -include inc bar: ; @echo $(strip $(MAKEFLAGS)) EOF close(MAKEFILE); &run_make_with_options($topmake, '-n --no-print-directory', &get_logfile); $answer = "$make_path -f \"$submake\" bar\ntouch inc\necho n --no-print-directory\n"; &compare_output($answer, &get_logfile(1)); unlink('inc'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-q000066400000000000000000000024631317072305000224240ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -q option.\n"; $details = "Try various uses of -q and ensure they all give the correct results.\n"; # TEST 0 run_make_test(qq! one: two: ; three: ; : four: ; \$(.XY) five: ; \\ \$(.XY) six: ; \\ \$(.XY) \t\$(.XY) seven: ; \\ \$(.XY) \t: foo \t\$(.XY) !, '-q one', ''); # TEST 1 run_make_test(undef, '-q two', ''); # TEST 2 run_make_test(undef, '-q three', '', 256); # TEST 3 run_make_test(undef, '-q four', ''); # TEST 4 run_make_test(undef, '-q five', ''); # TEST 5 run_make_test(undef, '-q six', ''); # TEST 6 run_make_test(undef, '-q seven', '', 256); # TEST 7 : Savannah bug # 7144 run_make_test(' one:: ; @echo one one:: ; @echo two ', '-q', '', 256); # TEST 7 : Savannah bug # 42249 # Make sure we exit with 1 even for prerequisite updates run_make_test(' build-stamp: ; echo $@ build-arch: build-stamp build-x: build-arch build-y: build-x ', '-q build-y', '', 256); # TEST 8 # Make sure we exit with 2 on error even with -q run_make_test(' build-stamp: ; echo $@ build-arch: build-stamp-2 build-x: build-arch build-y: build-x ', '-q build-y', "#MAKE#: *** No rule to make target 'build-stamp-2', needed by 'build-arch'. Stop.\n", 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/dash-t000066400000000000000000000030661317072305000224270ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -t option.\n"; $details = "Look out for regressions of prior bugs related to -t.\n"; # That means, nobody has even tried to make the tests below comprehensive # TEST 0 # bug reported by Henning Makholm on 2001-11-03: # make 3.79.1 touches only interm-[ab] but reports final-[a] as # 'up to date' without touching them. # The 'obvious' fix didn't work for double-colon rules, so pay special # attention to them. open(MAKEFILE, "> $makefile"); print MAKEFILE <<'EOMAKE'; final-a: interm-a ; echo >> $@ final-b: interm-b ; echo >> $@ interm-a:: orig1-a ; echo >> $@ interm-a:: orig2-a ; echo >> $@ interm-b:: orig1-b ; echo >> $@ interm-b:: orig2-b ; echo >> $@ EOMAKE close(MAKEFILE); &utouch(-30, 'orig1-a','orig2-b'); &utouch(-20, 'interm-a','interm-b'); &utouch(-10, 'final-a','final-b'); &touch('orig2-a','orig1-b'); &run_make_with_options($makefile, "-t final-a final-b", &get_logfile); $answer = "touch interm-a\ntouch final-a\ntouch interm-b\ntouch final-b\n"; &compare_output($answer, &get_logfile(1)); unlink('orig1-a', 'orig2-a', 'interm-a', 'final-a'); unlink('orig1-b', 'orig2-b', 'interm-b', 'final-b'); # TEST 1 # -t should not touch files with no commands. $makefile2 = &get_tmpfile; open(MAKEFILE, "> $makefile2"); print MAKEFILE <<'EOMAKE'; PHOOEY: xxx xxx: ; @: EOMAKE close(MAKEFILE); &run_make_with_options($makefile2, "-t", &get_logfile); $answer = "touch xxx\n"; &compare_output($answer, &get_logfile(1)); unlink('xxx'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/eval000066400000000000000000000014611317072305000221730ustar00rootroot00000000000000# -*-perl-*- $description = "Test the --eval option."; $details = "Verify that --eval options take effect, and are passed to sub-makes."; # Verify that --eval is evaluated first run_make_test(q! BAR = bar all: ; @echo all recurse: ; @$(MAKE) -f #MAKEFILE# && echo recurse!, '--eval=\$\(info\ eval\) FOO=\$\(BAR\)', "eval\nall"); # Make sure that --eval is handled correctly during recursion run_make_test(undef, '--no-print-directory --eval=\$\(info\ eval\) recurse', "eval\neval\nall\nrecurse"); # Make sure that --eval is handled correctly during restarting run_make_test(q! all: ; @echo $@ -include gen.mk gen.mk: ; @echo > $@ !, '--eval=\$\(info\ eval\)', "eval\neval\nall"); unlink('gen.mk'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/general000066400000000000000000000017351317072305000226650ustar00rootroot00000000000000# -*-perl-*- $description = "Test generic option processing.\n"; open(MAKEFILE, "> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "foo 1foo: ; \@echo \$\@\n"; close(MAKEFILE); # TEST 0 &run_make_with_options($makefile, "-j 1foo", &get_logfile); if (!$parallel_jobs) { $answer = "$make_name: Parallel jobs (-j) are not supported on this platform.\n$make_name: Resetting to single job (-j1) mode.\n1foo\n"; } else { $answer = "1foo\n"; } # TEST 1 # This test prints the usage string; I don't really know a good way to # test it. I guess I could invoke make with a known-bad option to see # what the usage looks like, then compare it to what I get here... :( # If I were always on UNIX, I could invoke it with 2>/dev/null, then # just check the error code. &run_make_with_options($makefile, "-j1foo 2>/dev/null", &get_logfile, 512); $answer = ""; &compare_output($answer, &get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/print-directory000066400000000000000000000014541317072305000244040ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -w option to GNU make."; # Simple test without -w run_make_test(q! all: ; @echo hi !, "", "hi\n"); # Simple test with -w run_make_test(undef, "-w", "#MAKE#: Entering directory '#PWD#'\nhi\n#MAKE#: Leaving directory '#PWD#'\n"); # Test makefile rebuild to ensure no enter/leave run_make_test(q! include foo all: ;@: foo: ; touch foo !, "", "#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n"); unlink('foo'); # Test makefile rebuild with -w run_make_test(q! include foo all: ;@: foo: ; touch foo !, "-w", "#MAKE#: Entering directory '#PWD#'\n#MAKEFILE#:2: foo: No such file or directory\ntouch foo\n#MAKE#: Leaving directory '#PWD#'\n"); unlink('foo'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/symlinks000066400000000000000000000042231317072305000231140ustar00rootroot00000000000000# -*-perl-*- $description = "Test the -L option."; $details = "Verify that symlink handling with and without -L works properly."; # Only run these tests if the system sypports symlinks # Apparently the Windows port of Perl reports that it does support symlinks # (in that the symlink() function doesn't fail) but it really doesn't, so # check for it explicitly. if ($port_type eq 'W32' || !( eval { symlink("",""); 1 })) { # This test is N/A -1; } else { # Set up a symlink sym -> dep # We'll make both dep and targ older than sym $pwd =~ m%/([^/]+)$%; $dirnm = $1; &utouch(-10, 'dep'); &utouch(-5, 'targ'); symlink("../$dirnm/dep", 'sym'); # Without -L, nothing should happen # With -L, it should update targ run_make_test('targ: sym ; @echo make $@ from $<', '', "#MAKE#: 'targ' is up to date."); run_make_test(undef, '-L', "make targ from sym"); # Now update dep; in all cases targ should be out of date. &touch('dep'); run_make_test(undef, '', "make targ from sym"); run_make_test(undef, '-L', "make targ from sym"); # Now update targ; in all cases targ should be up to date. &touch('targ'); run_make_test(undef, '', "#MAKE#: 'targ' is up to date."); run_make_test(undef, '-L', "#MAKE#: 'targ' is up to date."); # Add in a new link between sym and dep. Be sure it's newer than targ. sleep(1); rename('dep', 'dep1'); symlink('dep1', 'dep'); # Without -L, nothing should happen # With -L, it should update targ run_make_test(undef, '', "#MAKE#: 'targ' is up to date."); run_make_test(undef, '-L', "make targ from sym"); rmfiles('targ', 'dep', 'sym', 'dep1'); # Check handling when symlinks point to non-existent files. Without -L we # should get an error: with -L we should use the timestamp of the symlink. symlink("../$dirname/dep", 'sym'); run_make_test('targ: sym ; @echo make $@ from $<', '', "#MAKE#: *** No rule to make target 'sym', needed by 'targ'. Stop.", 512); run_make_test('targ: sym ; @echo make $@ from $<', '-L', 'make targ from sym'); rmfiles('targ', 'sym'); 1; } remake-4.1+dbg1.3~dfsg.1/tests/scripts/options/warn-undefined-variables000066400000000000000000000012551317072305000261210ustar00rootroot00000000000000# -*-perl-*- $description = "Test the --warn-undefined-variables option."; $details = "Verify that warnings are printed for referencing undefined variables."; # Without --warn-undefined-variables, nothing should happen run_make_test(' EMPTY = EREF = $(EMPTY) UREF = $(UNDEFINED) SEREF := $(EREF) SUREF := $(UREF) all: ; @echo ref $(EREF) $(UREF)', '', 'ref'); # With --warn-undefined-variables, it should warn me run_make_test(undef, '--warn-undefined-variables', "#MAKEFILE#:7: warning: undefined variable 'UNDEFINED' #MAKEFILE#:9: warning: undefined variable 'UNDEFINED' ref"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/remake/000077500000000000000000000000001317072305000210705ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/remake/tasks000066400000000000000000000010531317072305000221370ustar00rootroot00000000000000# -*-perl-*- $description = "Test remake --tasks and --targets.\n"; $details = "\ See that make --tasks shows some targets and assocated comments"; # TEST #0 --tasks # ------- run_make_test(' #: A simple comment all: echo "Simple comment" ', '-r -R --tasks', 'all # A simple comment '); # TEST #0 --targets # ------- run_make_test(' #: A simple comment all: echo "Simple comment" ', '-r -R --targets', ' .DEFAULT .SUFFIXES all # A simple comment work/remake/tasks.mk.1 '); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/000077500000000000000000000000001317072305000212755ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/DEFAULT000066400000000000000000000026631317072305000223130ustar00rootroot00000000000000$description = "The following test creates a makefile to override part\n" ."of one Makefile with Another Makefile with the .DEFAULT\n" ."rule."; $details = "This tests the use of the .DEFAULT special target to say that \n" ."to remake any target that cannot be made fram the information\n" ."in the containing makefile, make should look in another makefile\n" ."This test gives this makefile the target bar which is not \n" ."defined here but passes the target bar on to another makefile\n" ."which does have the target bar defined.\n"; $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "foo:\n"; print MAKEFILE "\t\@echo Executing rule FOO\n\n"; print MAKEFILE ".DEFAULT:\n"; print MAKEFILE "\t\@\$(MAKE) -f $makefile2 \$\@ \n"; # END of Contents of MAKEFILE close(MAKEFILE); open(MAKEFILE,"> $makefile2"); print MAKEFILE "bar:\n"; print MAKEFILE "\t\@echo Executing rule BAR\n\n"; close(MAKEFILE); &run_make_with_options($makefile,'bar',&get_logfile); # Create the answer to what should be produced by this Makefile $answer = "${make_name}[1]: Entering directory '$pwd'\n" . "Executing rule BAR\n" . "${make_name}[1]: Leaving directory '$pwd'\n"; # COMPARE RESULTS &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/FORCE000066400000000000000000000014211317072305000220540ustar00rootroot00000000000000# -*-perl-*- $description = "The following tests rules without Commands or Dependencies."; $details = "If the rule ...\n"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE ".IGNORE :\n"; print MAKEFILE "clean: FORCE\n"; print MAKEFILE "\t$delete_command clean\n"; print MAKEFILE "FORCE:\n"; # END of Contents of MAKEFILE close(MAKEFILE); # Create a file named "clean". This is the same name as the target clean # and tricks the target into thinking that it is up to date. (Unless you # use the .PHONY target. &touch("clean"); $answer = "$delete_command clean\n"; &run_make_with_options($makefile,"clean",&get_logfile); &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/INTERMEDIATE000066400000000000000000000054121317072305000230740ustar00rootroot00000000000000# -*-perl-*- $description = "Test the behaviour of the .INTERMEDIATE target."; $details = "\ Test the behavior of the .INTERMEDIATE special target. Create a makefile where a file would not normally be considered intermediate, then specify it as .INTERMEDIATE. Build and ensure it's deleted properly. Rebuild to ensure that it's not created if it doesn't exist but doesn't need to be built. Change the original and ensure that the intermediate file and the ultimate target are both rebuilt, and that the intermediate file is again deleted. Try this with implicit rules and explicit rules: both should work.\n"; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; .INTERMEDIATE: foo.e bar.e # Implicit rule test %.d : %.e ; cp $< $@ %.e : %.f ; cp $< $@ foo.d: foo.e # Explicit rule test foo.c: foo.e bar.e; cat $^ > $@ EOF close(MAKEFILE); # TEST #0 &utouch(-20, 'foo.f', 'bar.f'); &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n"; &compare_output($answer, &get_logfile(1)); # TEST #1 &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "$make_name: 'foo.d' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST #2 &utouch(-10, 'foo.d'); &touch('foo.f'); &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "cp foo.f foo.e\ncp foo.e foo.d\nrm foo.e\n"; &compare_output($answer, &get_logfile(1)); # TEST #3 &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n"; &compare_output($answer, &get_logfile(1)); # TEST #4 &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "$make_name: 'foo.c' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST #5 &utouch(-10, 'foo.c'); &touch('foo.f'); &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "cp foo.f foo.e\ncp bar.f bar.e\ncat foo.e bar.e > foo.c\nrm bar.e foo.e\n"; &compare_output($answer, &get_logfile(1)); # TEST #6 -- added for PR/1669: don't remove files mentioned on the cmd line. &run_make_with_options($makefile,'foo.e',&get_logfile); $answer = "cp foo.f foo.e\n"; &compare_output($answer, &get_logfile(1)); unlink('foo.f', 'foo.e', 'foo.d', 'foo.c', 'bar.f', 'bar.e', 'bar.d', 'bar.c'); # TEST #7 -- added for PR/1423 $makefile2 = &get_tmpfile; open(MAKEFILE, "> $makefile2"); print MAKEFILE <<'EOF'; all: foo foo.a: ; touch $@ %: %.a ; touch $@ .INTERMEDIATE: foo.a EOF close(MAKEFILE); &run_make_with_options($makefile2, '-R', &get_logfile); $answer = "touch foo.a\ntouch foo\nrm foo.a\n"; &compare_output($answer, &get_logfile(1)); unlink('foo'); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/ONESHELL000066400000000000000000000026561317072305000224420ustar00rootroot00000000000000# -*-perl-*- $description = "Test the behaviour of the .ONESHELL target."; $details = ""; # Some shells (*shakes fist at Solaris*) cannot handle multiple flags in # separate arguments. my $t = `/bin/sh -e -c true 2>/dev/null`; my $multi_ok = $? == 0; # Simple run_make_test(q! .ONESHELL: all: a=$$$$ [ 0"$$a" -eq "$$$$" ] || echo fail !, '', 'a=$$ [ 0"$a" -eq "$$" ] || echo fail '); # Simple but use multi-word SHELLFLAGS if ($multi_ok) { run_make_test(q! .ONESHELL: .SHELLFLAGS = -e -c all: a=$$$$ [ 0"$$a" -eq "$$$$" ] || echo fail !, '', 'a=$$ [ 0"$a" -eq "$$" ] || echo fail '); } # Again, but this time with inner prefix chars run_make_test(q! .ONESHELL: all: a=$$$$ @-+ [ 0"$$a" -eq "$$$$" ] || echo fail !, '', 'a=$$ [ 0"$a" -eq "$$" ] || echo fail '); # This time with outer prefix chars run_make_test(q! .ONESHELL: all: @a=$$$$ [ 0"$$a" -eq "$$$$" ] || echo fail !, '', ''); # This time with outer and inner prefix chars run_make_test(q! .ONESHELL: all: @a=$$$$ -@ +[ 0"$$a" -eq "$$$$" ] || echo fail !, '', ''); # Now try using a different interpreter run_make_test(q! .RECIPEPREFIX = > .ONESHELL: SHELL = #PERL# .SHELLFLAGS = -e all: > @$$a=5 > +7; > @y=qw(a b c); >print "a = $$a, y = (@y)\n"; !, '', "a = 12, y = (a b c)\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/PHONY000066400000000000000000000026101317072305000221140ustar00rootroot00000000000000# -*-perl-*- $description = "The following tests the use of a PHONY target. It makes\n" ."sure that the rules under a target get executed even if\n" ."a filename of the same name of the target exists in the\n" ."directory.\n"; $details = "This makefile in this test declares the target clean to be a \n" ."PHONY target. We then create a file named \"clean\" in the \n" ."directory. Although this file exists, the rule under the target\n" ."clean should still execute because of it's phony status."; $example = "EXAMPLE_FILE"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE ".PHONY : clean \n"; print MAKEFILE "all: \n"; print MAKEFILE "\t\@echo This makefile did not clean the dir ... good\n"; print MAKEFILE "clean: \n"; print MAKEFILE "\t$delete_command $example clean\n"; # END of Contents of MAKEFILE close(MAKEFILE); &touch($example); # Create a file named "clean". This is the same name as the target clean # and tricks the target into thinking that it is up to date. (Unless you # use the .PHONY target. &touch("clean"); $answer = "$delete_command $example clean\n"; &run_make_with_options($makefile,"clean",&get_logfile); if (-f $example) { $test_passed = 0; } &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/POSIX000066400000000000000000000034121317072305000221220ustar00rootroot00000000000000# -*-perl-*- $description = "Test the behaviour of the .POSIX target."; $details = ""; # Ensure turning on .POSIX enables the -e flag for the shell # We can't assume the exit value of "false" because on different systems it's # different. my $script = 'false; true'; my $flags = '-ec'; my $out = `/bin/sh $flags '$script' 2>&1`; my $err = $? >> 8; setup_for_test(); open(MAKEFILE,"> $makefile"); print MAKEFILE qq{ .SHELLFLAGS = $flags .POSIX: all: ; \@$script }; my $out = `/bin/sh $flags '$script' 2>&1`; my $answer = qq{#MAKEFILE#:4: recipe for target 'all' failed #MAKEFILE#:4: *** [all] Error $err #0 all at #MAKEFILE#:4 }; $logfile = &get_logfile; run_make_with_options($makefile, '', $logfile, 512); my $slurp = &read_file_into_string ($logfile); $slurp =~ s:^#0 all at .*work/targets/:#0 all at work/targets/:gm; &compare_output_string($answer, $slurp, $logfile); # Test the default value of various POSIX-specific variables my %POSIX = (AR => 'ar', ARFLAGS => 'rvU', YACC => 'yacc', YFLAGS => '', LEX => 'lex', LFLAGS => '', LDFLAGS => '', CC => 'c99', CFLAGS => '-O', FC => 'fort77', FFLAGS => '-O 1', GET => 'get', GFLAGS => '', SCCSFLAGS => '', SCCSGETFLAGS => '-s'); my $make = join('', map { "\t\@echo '$_=\$($_)'\n" } sort keys %POSIX); my $r = join('', map { "$_=$POSIX{$_}\n"} sort keys %POSIX); run_make_test(qq! .POSIX: all: $make !, '', $r); # Make sure that local settings take precedence %extraENV = map { $_ => "xx-$_" } keys %POSIX; $r = join('', map { "$_=xx-$_\n"} sort keys %POSIX); run_make_test(undef, '', $r); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/SECONDARY000066400000000000000000000075251317072305000225600ustar00rootroot00000000000000#! -*-perl-*- $description = "Test the behaviour of the .SECONDARY target."; $details = "\ Test the behavior of the .SECONDARY special target. Create a makefile where a file would not normally be considered intermediate, then specify it as .SECONDARY. Build and note that it's not automatically deleted. Delete the file. Rebuild to ensure that it's not created if it doesn't exist but doesn't need to be built. Change the original and ensure that the secondary file and the ultimate target are both rebuilt, and that the secondary file is not deleted. Try this with implicit rules and explicit rules: both should work.\n"; open(MAKEFILE,"> $makefile"); print MAKEFILE <<'EOF'; .SECONDARY: foo.e # Implicit rule test %.d : %.e ; cp $< $@ %.e : %.f ; cp $< $@ foo.d: foo.e # Explicit rule test foo.c: foo.e ; cp $< $@ EOF close(MAKEFILE); # TEST #1 &utouch(-20, 'foo.f'); &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "cp foo.f foo.e\ncp foo.e foo.d\n"; &compare_output($answer, &get_logfile(1)); # TEST #2 unlink('foo.e'); &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "$make_name: 'foo.d' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST #3 &utouch(-10, 'foo.d'); &touch('foo.f'); &run_make_with_options($makefile,'foo.d',&get_logfile); $answer = "cp foo.f foo.e\ncp foo.e foo.d\n"; &compare_output($answer, &get_logfile(1)); # TEST #4 &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "cp foo.e foo.c\n"; &compare_output($answer, &get_logfile(1)); # TEST #5 unlink('foo.e'); &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "$make_name: 'foo.c' is up to date.\n"; &compare_output($answer, &get_logfile(1)); # TEST #6 &utouch(-10, 'foo.c'); &touch('foo.f'); &run_make_with_options($makefile,'foo.c',&get_logfile); $answer = "cp foo.f foo.e\ncp foo.e foo.c\n"; &compare_output($answer, &get_logfile(1)); unlink('foo.f', 'foo.e', 'foo.d', 'foo.c'); # TEST #7 -- test the "global" .SECONDARY, with no targets. $makefile2 = &get_tmpfile; open(MAKEFILE, "> $makefile2"); print MAKEFILE <<'EOF'; .SECONDARY: final: intermediate intermediate: source final intermediate source: echo $< > $@ EOF close(MAKEFILE); &utouch(-10, 'source'); touch('final'); &run_make_with_options($makefile2, '', &get_logfile); $answer = "$make_name: 'final' is up to date.\n"; &compare_output($answer, &get_logfile(1)); unlink('source', 'final', 'intermediate'); # TEST #8 -- test the "global" .SECONDARY, with .PHONY. touch('version2'); run_make_test(' .PHONY: version .SECONDARY: version2: version ; @echo GOOD all: version2', 'all', 'GOOD'); unlink('version2'); # TEST #9 -- Savannah bug #15919 # The original fix for this bug caused a new bug, shown here. touch(qw(1.a 2.a)); run_make_test(' %.c : %.b ; cp $< $@ %.b : %.a ; cp $< $@ all : 1.c 2.c 2.a: 1.c', '-rR -j', 'cp 1.a 1.b cp 1.b 1.c cp 2.a 2.b cp 2.b 2.c rm 1.b 2.b'); unlink(qw(1.a 2.a 1.c 2.c)); # TEST #10 -- Savannah bug #15919 touch('test.0'); run_make_test(' .SECONDARY : test.1 test.2 test.3 test : test.4 %.4 : %.int %.3 ; touch $@ %.int : %.3 %.2 ; touch $@ %.3 : | %.2 ; touch $@ %.2 : %.1 ; touch $@ %.1 : %.0 ; touch $@', '-rR -j 2', 'touch test.1 touch test.2 touch test.3 touch test.int touch test.4 rm test.int'); # After a touch of test.0 it should give the same output, except we don't need # to rebuild test.3 (order-only) sleep(1); touch('test.0'); run_make_test(undef, '-rR -j 2', 'touch test.1 touch test.2 touch test.int touch test.4 rm test.int'); # With both test.0 and test.3 updated it should still build everything except # test.3 sleep(1); touch('test.0', 'test.3'); run_make_test(undef, '-rR -j 2', 'touch test.1 touch test.2 touch test.int touch test.4 rm test.int'); unlink(qw(test.0 test.1 test.2 test.3 test.4)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/SILENT000066400000000000000000000015631317072305000222230ustar00rootroot00000000000000# -*-perl-*- $description = "The following tests the special target .SILENT. By simply\n" ."mentioning this as a target, it tells make not to print\n" ."commands before executing them."; $details = "This test is the same as the clean test except that it should\n" ."not echo its command before deleting the specified file.\n"; $example = "EXAMPLE_FILE"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE ".SILENT : clean\n"; print MAKEFILE "clean: \n"; print MAKEFILE "\t$delete_command EXAMPLE_FILE\n"; # END of Contents of MAKEFILE close(MAKEFILE); &touch($example); $answer = ""; &run_make_with_options($makefile,"clean",&get_logfile,0); if (-f $example) { $test_passed = 0; } &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/targets/clean000066400000000000000000000021611317072305000223020ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to delete a \n" ."file in the directory. It tests to see if make will \n" ."NOT execute the command unless the rule is given in \n" ."the make command line."; $example = "EXAMPLE_FILE"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE "all: \n"; print MAKEFILE "\t\@echo This makefile did not clean the dir... good\n"; print MAKEFILE "clean: \n"; print MAKEFILE "\t$delete_command EXAMPLE_FILE\n"; # END of Contents of MAKEFILE close(MAKEFILE); &touch($example); &run_make_with_options($makefile,"",&get_logfile,0); # Create the answer to what should be produced by this Makefile $answer = "This makefile did not clean the dir... good\n"; &compare_output($answer,&get_logfile(1)) || &error ("abort"); $answer = "$delete_command $example\n"; &run_make_with_options($makefile,"clean",&get_logfile,0); if (-f $example) { $test_passed = 0; } &compare_output($answer,&get_logfile(1)) || &error ("abort"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/test_template000066400000000000000000000017671317072305000224340ustar00rootroot00000000000000# -*-perl-*- $description = ""; $details = ""; # Run a make test. See the documentation of run_make_test() in # run_make_tests.pl, but briefly the first argument is a string with the # contents of a makefile to be tested, the second is a string containing the # arguments to be passed to the make invocation, the third is a string # containing the expected output. The fourth is the expected exit code for # make. If not specified, it's assumed that the make program should succeed # (exit with 0). run_make_test('Your test makefile goes here', 'Arguments to pass to make go here', 'Expected output from the invocation goes here'); # There are various special tokens, options, etc. See the full documentation # in run_make_tests.pl. # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/000077500000000000000000000000001317072305000215745ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/CURDIR000066400000000000000000000006771317072305000225210ustar00rootroot00000000000000# -*-perl-*- $description = "This tests the CURDIR varaible."; $details = "Echo CURDIR both with and without -C. Also ensure overrides work."; open(MAKEFILE,"> $makefile"); print MAKEFILE "all: ; \@echo \$(CURDIR)\n"; close(MAKEFILE); # TEST #1 # ------- &run_make_with_options($makefile,"",&get_logfile); $answer = "$pwd\n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/DEFAULT_GOAL000066400000000000000000000022541317072305000234100ustar00rootroot00000000000000# -*-perl-*- $description = "Test the .DEFAULT_GOAL special variable."; $details = ""; # Test #1: basic logic. # run_make_test(' # Basics. # foo: ; @: ifneq ($(.DEFAULT_GOAL),foo) $(error ) endif # Reset to empty. # .DEFAULT_GOAL := bar: ; @: ifneq ($(.DEFAULT_GOAL),bar) $(error ) endif # Change to a different goal. # .DEFAULT_GOAL := baz baz: ; @echo $@ ', '', 'baz'); # Test #2: unknown goal. # run_make_test(' .DEFAULT_GOAL = foo ', '', "#MAKE#: *** No rule to make target 'foo'. Stop.", 512); # Test #3: more than one goal. # run_make_test(' .DEFAULT_GOAL := foo bar ', '', '#MAKE#: *** .DEFAULT_GOAL contains more than one target. Stop.', 512); # Test #4: Savannah bug #12226. # run_make_test(' define rule foo: ; @echo $$@ endef define make-rule $(eval $(rule)) endef $(call make-rule) ', '', 'foo'); # TEST #5: .DEFAULT_GOAL containing just whitespace (Savannah bug #25697) run_make_test(' N = .DEFAULT_GOAL = $N $N # Just whitespace foo: ; @echo "boo" ', '', "#MAKE#: *** No targets. Stop.\n", 512); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/GNUMAKEFLAGS000066400000000000000000000031331317072305000233630ustar00rootroot00000000000000# -*-perl-*- $description = "Test proper behavior of GNUMAKEFLAGS"; # Accept flags from GNUMAKEFLAGS as well as MAKEFLAGS # Results always go in MAKEFLAGS $extraENV{'GNUMAKEFLAGS'} = '-e -r -R'; run_make_test(q! all: ; @echo $(MAKEFLAGS) !, '', 'erR'); # Long arguments mean everything is prefixed with "-" $extraENV{'GNUMAKEFLAGS'} = '--no-print-directory -e -r -R --trace'; run_make_test(q! all: ; @echo $(MAKEFLAGS) !, '', "Reading makefiles... Updating goal targets.... File 'all' does not exist. Must remake target 'all'. #MAKEFILE#:2: target 'all' does not exist ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo erR -xnormal --no-print-directory ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< erR -xnormal --no-print-directory Successfully remade target file 'all'. "); # Verify that re-exec / recursion doesn't duplicate flags from GNUMAKEFLAGS unlink('x.mk'); $extraENV{GNUMAKEFLAGS} = '-Itst/bad'; run_make_test(q! recurse: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; #MAKEPATH# -f #MAKEFILE# all all: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS -include x.mk x.mk: ; @echo $@; echo MAKEFLAGS = $$MAKEFLAGS; echo GNUMAKEFLAGS = $$GNUMAKEFLAGS; echo > $@ !, "", "x.mk\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\nrecurse\nMAKEFLAGS = -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Entering directory '#PWD#'\nall\nMAKEFLAGS = w -Itst/bad\nGNUMAKEFLAGS =\n#MAKE#[1]: Leaving directory '#PWD#'\n"); unlink('x.mk'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/INCLUDE_DIRS000066400000000000000000000015031317072305000234220ustar00rootroot00000000000000# -*-perl-*- $description = "Test the .INCLUDE_DIRS special variable."; $details = ""; use Cwd; $dir = cwd; $dir =~ s,.*/([^/]+)$,../$1,; # Test #1: The content of .INCLUDE_DIRS depends on the platform for which # make was built. What we know for sure is that it shouldn't be # empty. # run_make_test(' ifeq ($(.INCLUDE_DIRS),) $(warning .INCLUDE_DIRS is empty) endif .PHONY: all all:;@: ', '', ''); # Test #2: Make sure -I paths end up in .INCLUDE_DIRS. # run_make_test(' ifeq ($(dir),) $(warning dir is empty) endif ifeq ($(filter $(dir),$(.INCLUDE_DIRS)),) $(warning .INCLUDE_DIRS does not contain $(dir)) endif .PHONY: all all:;@: ', "-I$dir dir=$dir", ''); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/LIBPATTERNS000066400000000000000000000015641317072305000233140ustar00rootroot00000000000000# -*-perl-*- $description = "Test .LIBPATTERNS special variable."; $details = ""; # TEST 0: basics touch('mtest_foo.a'); run_make_test(' .LIBPATTERNS = mtest_%.a all: -lfoo ; @echo "build $@ from $<" ', '', "build all from mtest_foo.a\n"); # TEST 1: Handle elements that are not patterns. run_make_test(' .LIBPATTERNS = mtest_foo.a mtest_%.a all: -lfoo ; @echo "build $@ from $<" ', '', "#MAKE#: .LIBPATTERNS element 'mtest_foo.a' is not a pattern build all from mtest_foo.a\n"); # TEST 2: target-specific override # Uncomment this when we add support, see Savannah bug #25703 # run_make_test(' # .LIBPATTERNS = mbad_%.a # all: .LIBPATTERNS += mtest_%.a # all: -lfoo ; @echo "build $@ from $<" # ', # '', "build all from mtest_foo.a\n"); unlink('mtest_foo.a'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/MAKE000066400000000000000000000007311317072305000222350ustar00rootroot00000000000000# -*-perl-*- $description = "Test proper behavior of the MAKE variable"; $details = "DETAILS"; run_make_test(q! TMP := $(MAKE) MAKE := $(subst X=$(X),,$(MAKE)) all: @echo $(TMP) $(MAKE) -f #MAKEFILE# foo foo: @echo $(MAKE) !, '', "#MAKEPATH#\n#MAKEPATH# -f #MAKEFILE# foo\n" . "#MAKE#[1]: Entering directory '#PWD#'\n" . "#MAKEPATH#\n#MAKE#[1]: Leaving directory '#PWD#'\n"); rmfiles("foo"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/MAKECMDGOALS000066400000000000000000000021521317072305000233460ustar00rootroot00000000000000# -*-perl-*- $description = "Test the MAKECMDGOALS variable."; $details = "\ We construct a makefile with various targets, all of which print out \$(MAKECMDGOALS), then call it different ways."; open(MAKEFILE,"> $makefile"); print MAKEFILE "\ .DEFAULT all: \@echo \$(MAKECMDGOALS) "; close(MAKEFILE); # TEST #1 &run_make_with_options($makefile, "", &get_logfile, 0); $answer = "\n"; &compare_output($answer,&get_logfile(1)); # TEST #2 &run_make_with_options($makefile, "all", &get_logfile, 0); $answer = "all\n"; &compare_output($answer,&get_logfile(1)); # TEST #3 &run_make_with_options($makefile, "foo bar baz yaz", &get_logfile, 0); $answer = "foo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\nfoo bar baz yaz\n"; &compare_output($answer,&get_logfile(1)); # This tells the test driver that the perl test script executed properly. 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/MAKEFILES000066400000000000000000000020771317072305000230250ustar00rootroot00000000000000# -*-perl-*- $description = "Test the MAKEFILES variable."; $makefile2 = &get_tmpfile; $makefile3 = &get_tmpfile; open(MAKEFILE,"> $makefile"); print MAKEFILE 'all: ; @echo DEFAULT RULE: M2=$(M2) M3=$(M3)', "\n"; close(MAKEFILE); open(MAKEFILE,"> $makefile2"); print MAKEFILE < $makefile3"); print MAKEFILE <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo erR -xnormal --no-print-directory ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< erR -xnormal --no-print-directory Successfully remade target file 'all'. "); # Recursive invocations of make should accumulate MAKEFLAGS values. # Savannah bug #2216 run_make_test(q! MSG = Fails all: @echo '$@: MAKEFLAGS=$(MAKEFLAGS)' @MSG=Works $(MAKE) -e -f #MAKEFILE# jump jump: @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)' @$(MAKE) -f #MAKEFILE# print print: @echo '$@ $(MSG): MAKEFLAGS=$(MAKEFLAGS)' .PHONY: all jump print !, '--no-print-directory', 'all: MAKEFLAGS= --no-print-directory jump Works: MAKEFLAGS=e --no-print-directory print Works: MAKEFLAGS=e --no-print-directory'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/MAKELEVEL000066400000000000000000000012011317072305000230160ustar00rootroot00000000000000# -*-perl-*- $description = "The following test creates a makefile to test makelevels in Make. It prints \$(MAKELEVEL) and then prints the environment variable MAKELEVEL"; open(MAKEFILE,"> $makefile"); # The Contents of the MAKEFILE ... print MAKEFILE < $@ bar.x: ; @touch $@ ', '', 'MAKE_RESTARTS= #MAKEFILE#:4: foo.x: No such file or directory MAKE_RESTARTS=1 foo.x:1: bar.x: No such file or directory MAKE_RESTARTS=2'); rmfiles('foo.x', 'bar.x'); # Test multiple restarts and make sure the variable is cleaned up run_make_test(' recurse: @echo recurse MAKE_RESTARTS=$$MAKE_RESTARTS @$(MAKE) -f #MAKEFILE# all all: @echo all MAKE_RESTARTS=$$MAKE_RESTARTS $(info MAKE_RESTARTS=$(MAKE_RESTARTS)) include foo.x foo.x: ; @echo "include bar.x" > $@ bar.x: ; @touch $@ ', '', "MAKE_RESTARTS= #MAKEFILE#:8: foo.x: No such file or directory MAKE_RESTARTS=1 foo.x:1: bar.x: No such file or directory MAKE_RESTARTS=2 recurse MAKE_RESTARTS= #MAKE#[1]: Entering directory '#PWD#' MAKE_RESTARTS= all MAKE_RESTARTS= #MAKE#[1]: Leaving directory '#PWD#'"); rmfiles('foo.x', 'bar.x'); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/MFILE_LIST000066400000000000000000000011531317072305000232060ustar00rootroot00000000000000# -*-perl-*- $description = "Test the MAKEFILE_LIST variable."; $makefile2 = &get_tmpfile; open(MAKEFILE,"> $makefile"); print MAKEFILE < $makefile2"); print MAKEFILE "m2 := \$(MAKEFILE_LIST)\n"; close(MAKEFILE); &run_make_with_options($makefile, "", &get_logfile); $answer = "$makefile\n$makefile $makefile2\n$makefile $makefile2\n"; &compare_output($answer,&get_logfile(1)); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/SHELL000066400000000000000000000062221317072305000223700ustar00rootroot00000000000000# -*-perl-*- $description = "Test proper handling of SHELL."; # Find the default value when SHELL is not set. On UNIX it will be /bin/sh, # but on other platforms who knows? resetENV(); delete $ENV{SHELL}; $mshell = `echo 'all:;\@echo \$(SHELL)' | $make_path -f-`; chop $mshell; # According to POSIX, the value of SHELL in the environment has no impact on # the value in the makefile. # Note %extraENV takes precedence over the default value for the shell. $extraENV{SHELL} = '/dev/null'; run_make_test('all:;@echo "$(SHELL)"', '', $mshell); # According to POSIX, any value of SHELL set in the makefile should _NOT_ be # exported to the subshell! I wanted to set SHELL to be $^X (perl) in the # makefile, but make runs $(SHELL) -c 'commandline' and that doesn't work at # all when $(SHELL) is perl :-/. So, we just add an extra initial /./ which # works well on UNIX and seems to work OK on at least some non-UNIX systems. $extraENV{SHELL} = $mshell; run_make_test("SHELL := /./$mshell\n".' all:;@echo "$(SHELL) $$SHELL" ', '', "/./$mshell $mshell"); # As a GNU make extension, if make's SHELL variable is explicitly exported, # then we really _DO_ export it. $extraENV{SHELL} = $mshell; run_make_test("export SHELL := /./$mshell\n".' all:;@echo "$(SHELL) $$SHELL" ', '', "/./$mshell /./$mshell"); # Test out setting of SHELL, both exported and not, as a target-specific # variable. $extraENV{SHELL} = $mshell; run_make_test("all: SHELL := /./$mshell\n".' all:;@echo "$(SHELL) $$SHELL" ', '', "/./$mshell $mshell"); $extraENV{SHELL} = $mshell; run_make_test(" SHELL := /././$mshell one: two two: export SHELL := /./$mshell\n".' one two:;@echo "$@: $(SHELL) $$SHELL" ', '', "two: /./$mshell /./$mshell\none: /././$mshell $mshell\n"); # Test .SHELLFLAGS # We don't know the output here: on Solaris for example, every line printed # by the shell in -x mode has a trailing space (!!) my $script = 'true; true'; my $flags = '-xc'; my $out = `/bin/sh $flags '$script' 2>&1`; run_make_test(qq! .SHELLFLAGS = $flags all: ; \@$script !, '', $out); # Do it again but add spaces to SHELLFLAGS # Some shells (*shakes fist at Solaris*) cannot handle multiple flags in # separate arguments. my $t = `/bin/sh -e -c true 2>/dev/null`; my $multi_ok = $? == 0; if ($multi_ok) { $flags = '-x -c'; run_make_test(qq! .SHELLFLAGS = $flags all: ; \@$script !, '', $out); } # We can't just use "false" because on different systems it provides a # different exit code--once again Solaris: false exits with 255 not 1 $script = 'true; false; true'; $flags = '-xec'; $out = `/bin/sh $flags '$script' 2>&1`; my $err = $? >> 8; setup_for_test(); open(MAKEFILE,"> $makefile"); print MAKEFILE qq{ .SHELLFLAGS = $flags all: ; \@$script }; my $answer = qq|$out#MAKEFILE#:3: recipe for target 'all' failed #MAKEFILE#:3: *** [all] Error $err #0 all at #MAKEFILE#:3 |; $logfile = &get_logfile; run_make_with_options($makefile, '', $logfile, 512); my $slurp = &read_file_into_string ($logfile); $slurp =~ s:^#0 all at .*work/variables/:#0 all at work/variables/:gm; &compare_output_string($answer, $slurp, $logfile); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/automatic000066400000000000000000000060121317072305000235040ustar00rootroot00000000000000# -*-perl-*- $description = "Test automatic variable setting."; $details = ""; use Cwd; $dir = cwd; $dir =~ s,.*/([^/]+)$,../$1,; open(MAKEFILE, "> $makefile"); print MAKEFILE "dir = $dir\n"; print MAKEFILE <<'EOF'; .SUFFIXES: .SUFFIXES: .x .y .z $(dir)/foo.x : baz.z $(dir)/bar.y baz.z @echo '$$@ = $@, $$(@D) = $(@D), $$(@F) = $(@F)' @echo '$$* = $*, $$(*D) = $(*D), $$(*F) = $(*F)' @echo '$$< = $<, $$( $makefile2"); print MAKEFILE "dir = $dir\n"; print MAKEFILE <<'EOF'; .SECONDEXPANSION: .SUFFIXES: .DEFAULT: ; @echo '$@' $(dir)/foo $(dir)/bar: $@.x $$@.x $$$@.x $$$$@.x $$(@D).x $$(@F).x $(dir)/x.z $(dir)/y.z: $(dir)/%.z : $@.% $$@.% $$$@.% $$$$@.% $$(@D).% $$(@F).% $(dir)/biz: $$(@).x $${@}.x $${@D}.x $${@F}.x EOF close(MAKEFILE); &run_make_with_options($makefile2, "$dir/foo $dir/bar", &get_logfile); $answer = ".x\n$dir/foo.x\nx\n\$@.x\n$dir.x\nfoo.x\n$dir/bar.x\nbar.x\n"; &compare_output($answer, &get_logfile(1)); &run_make_with_options($makefile2, "$dir/x.z $dir/y.z", &get_logfile); $answer = ".x\n$dir/x.z.x\nx\n\$@.x\n$dir.x\nx.z.x\n.y\n$dir/y.z.y\n\y\n\$@.y\n$dir.y\ny.z.y\n"; &compare_output($answer, &get_logfile(1)); &run_make_with_options($makefile2, "$dir/biz", &get_logfile); $answer = "$dir/biz.x\n$dir.x\nbiz.x\n"; &compare_output($answer, &get_logfile(1)); # TEST #2 -- test for Savannah bug #12320. # run_make_test(' .SUFFIXES: .b .src mbr.b: mbr.src @echo $* mbr.src: ; @:', '', 'mbr'); # TEST #3 -- test for Savannah bug #8154 # Make sure that nonexistent prerequisites are listed in $?, since they are # considered reasons for the target to be rebuilt. # # See also Savannah bugs #16002 and #16051. touch('foo'); run_make_test(' foo: bar ; @echo "\$$? = $?" bar: ;', '', '$? = bar'); unlink('foo'); # TEST #4: ensure prereq ordering is correct when the commmand target has none # See Savannah bug #21198 run_make_test(' all : A B all : ; @echo $@ -- $^ -- $< all : C D all : E F A B C D E F G H : ; @: ', '', "all -- A B C D E F -- A\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/define000066400000000000000000000104271317072305000227550ustar00rootroot00000000000000# -*-perl-*- $description = "Test define/endef variable assignments."; $details = ""; # TEST 0: old-style basic define/endef run_make_test(' define multi @echo hi echo there endef all: ; $(multi) ', '', "hi\necho there\nthere\n"); # TEST 1: Various new-style define/endef run_make_test(' FOO = foo define multi = echo hi @echo $(FOO) endef # this is the end define simple := @echo $(FOO) endef define posix ::= @echo $(FOO) endef append = @echo a define append += @echo b endef define cond ?= # this is a conditional @echo first endef define cond ?= @echo second endef FOO = there all: ; $(multi) $(simple) $(posix) $(append) $(cond) ', '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n"); # TEST 1a: Various new-style define/endef, with no spaces run_make_test(' FOO = foo define multi= echo hi @echo $(FOO) endef # this is the end define simple:= @echo $(FOO) endef define posix::= @echo $(FOO) endef append = @echo a define append+= @echo b endef define cond?= # this is a conditional @echo first endef define cond?= @echo second endef FOO = there all: ; $(multi) $(simple) $(posix) $(append) $(cond) ', '', "echo hi\nhi\nthere\nfoo\nfoo\na\nb\nfirst\n"); # TEST 2: define in true section of conditional (containing conditional) run_make_test(' FOO = foo NAME = def def = ifdef BOGUS define $(subst e,e,$(NAME)) = ifeq (1,1) FOO = bar endif endef endif $(eval $(def)) all: ; @echo $(FOO) ', 'BOGUS=1', "bar\n"); # TEST 3: define in false section of conditional (containing conditional) run_make_test(undef, '', "foo\n"); # TEST 4: nested define (supported?) run_make_test(' define outer define inner A = B endef endef $(eval $(outer)) outer: ; @echo $(inner) ', '', "A = B\n"); # TEST 5: NEGATIVE: Missing variable name run_make_test(' NAME = define $(NAME) = ouch endef all: ; @echo ouch ', '', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512); # TEST 6: NEGATIVE: extra text after define run_make_test(' NAME = define NAME = $(NAME) ouch endef all: ; @echo ok ', '', "#MAKEFILE#:3: extraneous text after 'define' directive\nok\n"); # TEST 7: NEGATIVE: extra text after endef run_make_test(' NAME = define NAME = ouch endef $(NAME) all: ; @echo ok ', '', "#MAKEFILE#:5: extraneous text after 'endef' directive\nok\n"); # TEST 8: NEGATIVE: missing endef run_make_test(' NAME = all: ; @echo ok define NAME = ouch endef$(NAME) ', '', "#MAKEFILE#:4: *** missing 'endef', unterminated 'define'. Stop.\n", 512); # ------------------------- # Make sure that prefix characters apply properly to define/endef values. # # There's a bit of oddness here if you try to use a variable to hold the # prefix character for a define. Even though something like this: # # define foo # echo bar # endef # # all: ; $(V)$(foo) # # (where V=@) can be seen by the user to be obviously different than this: # # define foo # $(V)echo bar # endef # # all: ; $(foo) # # and the user thinks it should behave the same as when the "@" is literal # instead of in a variable, that can't happen because by the time make # expands the variables for the command line and sees it begins with a "@" it # can't know anymore whether the prefix character came before the variable # reference or was included in the first line of the variable reference. # TEST #5 # ------- run_make_test(' define FOO $(V1)echo hello $(V2)echo world endef all: ; @$(FOO) ', '', 'hello world'); # TEST #6 # ------- run_make_test(undef, 'V1=@ V2=@', 'hello world'); # TEST #7 # ------- run_make_test(' define FOO $(V1)echo hello $(V2)echo world endef all: ; $(FOO) ', 'V1=@', 'hello echo world world'); # TEST #8 # ------- run_make_test(undef, 'V2=@', 'echo hello hello world'); # TEST #9 # ------- run_make_test(undef, 'V1=@ V2=@', 'hello world'); # TEST #10 # ------- # Test the basics; a "@" internally to the variable applies to only one line. # A "@" before the variable applies to the entire variable. run_make_test(' define FOO @echo hello echo world endef define BAR echo hello echo world endef all: foo bar foo: ; $(FOO) bar: ; @$(BAR) ', '', 'hello echo world world hello world '); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/flavors000066400000000000000000000026311317072305000231750ustar00rootroot00000000000000# -*-perl-*- $description = "Test various flavors of make variable setting."; $details = ""; # TEST 0: Recursive run_make_test(' ugh = Goodbye foo = $(bar) bar = ${ugh} ugh = Hello all: ; @echo $(foo) ', '', "Hello\n"); # TEST 1: Simple run_make_test(' bar = Goodbye foo := $(bar) bar = ${ugh} ugh = Hello all: ; @echo $(foo) ', '', "Goodbye\n"); # TEST 2: Append to recursive run_make_test(' foo = Hello ugh = Goodbye foo += $(bar) bar = ${ugh} ugh = Hello all: ; @echo $(foo) ', '', "Hello Hello\n"); # TEST 3: Append to simple run_make_test(' foo := Hello ugh = Goodbye bar = ${ugh} foo += $(bar) ugh = Hello all: ; @echo $(foo) ', '', "Hello Goodbye\n"); # TEST 4: Conditional pre-set run_make_test(' foo = Hello ugh = Goodbye bar = ${ugh} foo ?= $(bar) ugh = Hello all: ; @echo $(foo) ', '', "Hello\n"); # TEST 5: Conditional unset run_make_test(' ugh = Goodbye bar = ${ugh} foo ?= $(bar) ugh = Hello all: ; @echo $(foo) ', '', "Hello\n"); # TEST 6: Simple using POSIX syntax run_make_test(' bar = Goodbye foo ::= $(bar) bar = ${ugh} ugh = Hello all: ; @echo $(foo) ', '', "Goodbye\n"); # TEST 7: POSIX syntax no spaces run_make_test(' bar = Goodbye foo::=$(bar) bar = ${ugh} ugh = Hello all: ; @echo $(foo) ', '', "Goodbye\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/negative000066400000000000000000000020771317072305000233270ustar00rootroot00000000000000# -*-perl-*- $description = "Run some negative tests (things that should fail)."; # TEST #0 # Check that non-terminated variable references are detected (and # reported using the best filename/lineno info run_make_test(' foo = bar x = $(foo y = $x all: ; @echo $y ', '', '#MAKEFILE#:3: *** unterminated variable reference. Stop.', 512); # TEST #1 # Bogus variable value passed on the command line. run_make_test(undef, 'x=\$\(other', '#MAKEFILE#:4: *** unterminated variable reference. Stop.', 512); # TEST #2 # Again, but this time while reading the makefile. run_make_test(' foo = bar x = $(foo y = $x z := $y all: ; @echo $y ', '', '#MAKEFILE#:3: *** unterminated variable reference. Stop.', 512); # TEST #3 # Bogus variable value passed on the command line. run_make_test(undef, 'x=\$\(other', '#MAKEFILE#:4: *** unterminated variable reference. Stop.', 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/private000066400000000000000000000045421317072305000231760ustar00rootroot00000000000000# -*-perl-*- $description = "Test 'private' variables."; $details = ""; # 1: Simple verification that private variables are not inherited &run_make_test(' a: F = g a: F = a b: private F = b a b c: ; @echo $@: F=$(F) a: b b: c ', '', "c: F=a\nb: F=b\na: F=a\n"); # 2: Again, but this time we start with "b" so "a"'s variable is not in scope &run_make_test(undef, 'b', "c: F=g\nb: F=b\n"); # 3: Verification with pattern-specific variables &run_make_test(' t.a: F1 = g F2 = g %.a: private F1 = a %.a: F2 = a t.a t.b: ; @echo $@: F1=$(F1) / F2=$(F2) t.a: t.b ', '', "t.b: F1=g / F2=a\nt.a: F1=a / F2=a\n"); # 4: Test private global variables &run_make_test(' a: private F = g G := $(F) a: b: F = b a b: ; @echo $@: F=$(F) / G=$(G) a: b ', '', "b: F=b / G=g\na: F= / G=g\n"); # 5: Multiple conditions on the same variable. Test export. delete $ENV{'_X'}; &run_make_test(' _X = x a: export override private _X = a a: ; @echo _X=$(_X) / _X=$$_X ', '', "_X=a / _X=a"); # 6: Test override. &run_make_test(undef, '_X=c', "_X=a / _X=a\n"); # 7: Ensure keywords still work as targets &run_make_test(' a: export override private foo bar foo bar export override private: ; @echo $@ ', '', "export\noverride\nprivate\nfoo\nbar\n"); # 8: Ensure keywords still work as variables &run_make_test(' private = g a: private = a a: b a b: ; @echo $@=$(private) ', '', "b=a\na=a\n"); # 9: make sure private suppresses inheritance run_make_test(q! DEFS = FOO all: bar1 bar1: private DEFS += 1 bar3: private DEFS += 3 bar1: bar2 bar2: bar3 bar1 bar2 bar3: ; @echo '$@: $(DEFS)' !, '', "bar3: FOO 3\nbar2: FOO\nbar1: FOO 1\n"); # 10: Test append with pattern-specific variables and private run_make_test(q! IA = global PA = global PS = global S = global PS = global SV = global b%: IA += b% b%: private PA += b% b%: private PS = b% bar: all bar: IA += bar bar: private PA += bar bar: private PS = bar a%: IA += a% a%: private PA += a% a%: private PS = a% all: IA += all all: private PA += all all: private PS = all bar all: ; @echo '$@: IA=$(IA)'; echo '$@: PA=$(PA)'; echo '$@: PS=$(PS)' !, '', "all: IA=global b% bar a% all all: PA=global a% all all: PS=all bar: IA=global b% bar bar: PA=global b% bar bar: PS=bar\n"); 1; remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/special000066400000000000000000000043621317072305000231440ustar00rootroot00000000000000# -*-perl-*- $description = "Test special GNU make variables."; $details = ""; &run_make_test(' X1 := $(sort $(filter FOO BAR,$(.VARIABLES))) FOO := foo X2 := $(sort $(filter FOO BAR,$(.VARIABLES))) BAR := bar all: @echo X1 = $(X1) @echo X2 = $(X2) @echo LAST = $(sort $(filter FOO BAR,$(.VARIABLES))) ', '', "X1 =\nX2 = FOO\nLAST = BAR FOO\n"); # $makefile2 = &get_tmpfile; # open(MAKEFILE, "> $makefile2"); # print MAKEFILE <<'EOF'; # X1 := $(sort $(.TARGETS)) # all: foo # @echo X1 = $(X1) # @echo X2 = $(X2) # @echo LAST = $(sort $(.TARGETS)) # X2 := $(sort $(.TARGETS)) # foo: # EOF # close(MAKEFILE); # # TEST #2 # # ------- # &run_make_with_options($makefile2, "", &get_logfile); # $answer = "X1 =\nX2 = all\nLAST = all foo\n"; # &compare_output($answer, &get_logfile(1)); # Test the .RECIPEPREFIX variable &run_make_test(' define foo : foo-one\ foo-two : foo-three : foo-four endef orig: ; : orig-one : orig-two \ orig-three \ orig-four \ orig-five \\\\ : orig-six $(foo) .RECIPEPREFIX = > test: ; : test-one >: test-two \ test-three \ >test-four \ > test-five \\\\ >: test-six >$(foo) .RECIPEPREFIX = reset: ; : reset-one : reset-two \ reset-three \ reset-four \ reset-five \\\\ : reset-six $(foo) ', 'orig test reset', ': orig-one : orig-two \ orig-three \ orig-four \ orig-five \\\\ : orig-six : foo-one foo-two : foo-three : foo-four : test-one : test-two \ test-three \ test-four \ test-five \\\\ : test-six : foo-one foo-two : foo-three : foo-four : reset-one : reset-two \ reset-three \ reset-four \ reset-five \\\\ : reset-six : foo-one foo-two : foo-three : foo-four'); # Test that the "did you mean TAB" message is printed properly run_make_test(q! $x. !, '', '#MAKEFILE#:2: *** missing separator. Stop.', 512); run_make_test(q! foo: bar !, '', '#MAKEFILE#:3: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.', 512); run_make_test(q! .RECIPEPREFIX = : foo: bar !, '', '#MAKEFILE#:4: *** missing separator. Stop.', 512); 1; ### Local Variables: ### eval: (setq whitespace-action (delq 'auto-cleanup whitespace-action)) ### End: remake-4.1+dbg1.3~dfsg.1/tests/scripts/variables/undefine000066400000000000000000000016731317072305000233230ustar00rootroot00000000000000# -*-perl-*- $description = "Test variable undefine."; $details = ""; # TEST 0: basic undefine functionality run_make_test(' a = a b := b define c c endef $(info $(flavor a) $(flavor b) $(flavor c)) n := b undefine a undefine $n undefine c $(info $(flavor a) $(flavor b) $(flavor c)) all: ;@: ', '', "recursive simple recursive\nundefined undefined undefined"); # TEST 1: override run_make_test(' undefine a override undefine b $(info $(flavor a) $(flavor b)) all: ;@: ', 'a=a b=b', "recursive undefined"); 1; # TEST 2: undefine in eval (make sure we undefine from the global var set) run_make_test(' define undef $(eval undefine $$1) endef a := a $(call undef,a) $(info $(flavor a)) all: ;@: ', '', "undefined"); # TEST 3: Missing variable name run_make_test(' a = undefine $a all: ;@echo ouch ', '', "#MAKEFILE#:3: *** empty variable name. Stop.\n", 512); 1; remake-4.1+dbg1.3~dfsg.1/tests/spec/000077500000000000000000000000001317072305000170675ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/spec/.gitignore000066400000000000000000000000041317072305000210510ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/tests/spec/data/000077500000000000000000000000001317072305000200005ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/spec/data/.gitignore000066400000000000000000000000411317072305000217630ustar00rootroot00000000000000/*~ remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break-all.right000066400000000000000000000007741317072305000227010ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> break third Breakpoint 1 on target third: file triple.Makefile, line 5. remake<1> continue triple.Makefile:5) third: remake<2> continue triple.Makefile:5) third remake<3> continue ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5) third remake<4> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break-end.right000066400000000000000000000006461317072305000226750ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> break third end Breakpoint 1 on target third: file triple.Makefile, line 5. remake<1> continue ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5) third remake<2> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break-expand.right000066400000000000000000000006041317072305000234000ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... test2.Makefile:3 File `all' does not exist. test2.Makefile:5) make.txt: ../doc/remake.texi remake<0> break $(PACKAGE).txt Breakpoint 1 on target make.txt: file test2.Makefile, line 5. Warning: target is in the process of being updated; so it might not get stopped at again. remake<1> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break-prereq.right000066400000000000000000000004321317072305000234160ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> break third prereq Breakpoint 1 on target third: file triple.Makefile, line 5. remake<1> continue triple.Makefile:5) third: remake<2> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break-run.right000066400000000000000000000004251317072305000227260ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> break third run Breakpoint 1 on target third: file triple.Makefile, line 5. remake<1> continue triple.Makefile:5) third remake<2> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/break.right000066400000000000000000000003561317072305000221270ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1 File `first' does not exist. triple.Makefile:1) first: second remake<0> Breakpoint 1 on target third. remake<0> triple.Makefile:5) third remake<1> remake-4.1+dbg1.3~dfsg.1/tests/spec/data/commented.right000066400000000000000000000001121317072305000230040ustar00rootroot00000000000000first second # This is the second target third # This is the third target remake-4.1+dbg1.3~dfsg.1/tests/spec/data/continue.right000066400000000000000000000025221317072305000226640ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> continue third Breakpoint 1 on target third: file triple.Makefile, line 5. triple.Makefile:1 File `first' does not exist. triple.Makefile:3 File `second' does not exist. triple.Makefile:5) third: remake<1> finish 10 Level 10 is too large; maximum value is 2. remake<2> finish 2 triple.Makefile:5 File `third' does not exist. triple.Makefile:5 Must remake target `third'. triple.Makefile:6 to update target `third'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5 Successfully remade target file `third'. triple.Makefile:3 Must remake target `second'. triple.Makefile:4 to update target `second'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo second done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< second done triple.Makefile:3 Successfully remade target file `second'. triple.Makefile:1 Must remake target `first'. triple.Makefile:2 to update target `first'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo first done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< first done triple.Makefile:1 Successfully remade target file `first'. triple.Makefile:1) first remake<3> remake-4.1+dbg1.3~dfsg.1/tests/spec/data/description-trace.right000066400000000000000000000001201317072305000244470ustar00rootroot00000000000000all # This is the main target check # test things dist # Build distribution foo remake-4.1+dbg1.3~dfsg.1/tests/spec/data/info-rule.right000066400000000000000000000017541317072305000227460ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... implicit.Makefile:2 File `foo.x' does not exist. implicit.Makefile:11) bar: remake<0> # Implicit Rules foo.% $(%_a) $(%_b) bar %.out: %.a %.ln %.o % %.o %.c % %.c %.ln %.c %.o %.c %.cc: %: %.cc %.o: %.cc %.C: %: %.C %.o: %.C %.cpp: %: %.cpp %.o: %.cpp %.p: %: %.p %.o: %.p %.f: %: %.f %.o: %.f %.F: %: %.F %.o: %.F %.f: %.F %.m: %: %.m %.o: %.m %.r: %: %.r %.o: %.r %.f: %.r %.y: %.ln: %.y %.c: %.y %.l: %.ln: %.l %.c: %.l %.r: %.l %.ym: %.m: %.ym %.yl: %.s: %: %.s %.o: %.s %.S: %: %.S %.o: %.S %.s: %.S %.mod: %: %.mod %.o: %.mod %.sym: %.def: %.sym: %.def %.h: %.info: %.dvi: %.tex: %.dvi: %.tex %.texinfo: %.info: %.texinfo %.dvi: %.texinfo %.texi: %.info: %.texi %.dvi: %.texi %.txinfo: %.info: %.txinfo %.dvi: %.txinfo %.w: %.c: %.w %.tex: %.w %.ch: %.web: %.p: %.web %.tex: %.web %.sh: %: %.sh %.elc: %.el: (%): % %.out: % %.c: %.w %.ch %.tex: %.w %.ch %:: %,v %:: RCS/%,v %:: RCS/% %:: s.% %:: SCCS/s.% remake<1> remake-4.1+dbg1.3~dfsg.1/tests/spec/data/info-target.right000066400000000000000000000004071317072305000232570ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... order-only.Makefile:1) foo: bar remake<0> target @ order foo: | baz remake<1> target @ nonorder foo: bar remake<2> target @ depend foo: bar | baz remake<3> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/info-targets.right000066400000000000000000000027011317072305000234410ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> info targets .C .C.o .DEFAULT .F .F.f .F.o .S .S.o .S.s .SUFFIXES .a .c .c.ln .c.o .cc .cc.o .ch .cpp .cpp.o .def .def.sym .dvi .el .elc .f .f.o .h .info .l .l.c .l.ln .l.r .lm.m .ln .m .m.o .mod .mod.o .o .out .p .p.o .r .r.f .r.o .s .s.o .sh .sym .tex .tex.dvi .texi .texi.dvi .texi.info .texinfo .texinfo.dvi .texinfo.info .txinfo .txinfo.dvi .txinfo.info .w .w.c .w.tex .web .web.p .web.tex .y .y.c .y.ln .yl .ym .ym.m /src/external-vcs/remake/tests/spec/example/triple.Makefile triple.Makefile:1: first triple.Makefile:3: second triple.Makefile:5: third remake<1> info targets names .C .C.o .DEFAULT .F .F.f .F.o .S .S.o .S.s .SUFFIXES .a .c .c.ln .c.o .cc .cc.o .ch .cpp .cpp.o .def .def.sym .dvi .el .elc .f .f.o .h .info .l .l.c .l.ln .l.r .lm.m .ln .m .m.o .mod .mod.o .o .out .p .p.o .r .r.f .r.o .s .s.o .sh .sym .tex .tex.dvi .texi .texi.dvi .texi.info .texinfo .texinfo.dvi .texinfo.info .txinfo .txinfo.dvi .txinfo.info .w .w.c .w.tex .web .web.p .web.tex .y .y.c .y.ln .yl .ym .ym.m /src/external-vcs/remake/tests/spec/example/triple.Makefile first second third remake<2> info targets positions triple.Makefile:1 triple.Makefile:3 triple.Makefile:5 remake<3> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/list.right000066400000000000000000000011711317072305000220120ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> list triple.Makefile:1 first: second # commands to execute (from `triple.Makefile', line 2): @echo first done remake<1> list third triple.Makefile:5 third: # commands to execute (from `triple.Makefile', line 6): echo third done remake<2> list 3 triple.Makefile:3 second: third # commands to execute (from `triple.Makefile', line 4): @echo second done remake<3> list 6 ** Can't find target or pattern on line 6. Use 'info lines' to get a list of and pattern lines. remake<4> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/norl.right000066400000000000000000000023611317072305000220130ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> Breakpoint 1 on target third: file triple.Makefile, line 5. triple.Makefile:1 File `first' does not exist. triple.Makefile:3 File `second' does not exist. triple.Makefile:5) third: triple.Makefile:5 File `third' does not exist. triple.Makefile:5 Must remake target `third'. triple.Makefile:6 to update target `third'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5 Successfully remade target file `third'. triple.Makefile:3 Must remake target `second'. triple.Makefile:4 to update target `second'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo second done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< second done triple.Makefile:3 Successfully remade target file `second'. triple.Makefile:1 Must remake target `first'. triple.Makefile:2 to update target `first'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo first done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< first done triple.Makefile:1 Successfully remade target file `first'. triple.Makefile:1) first remake<0> remake-4.1+dbg1.3~dfsg.1/tests/spec/data/opt-x-trace.right000066400000000000000000000020641317072305000232040ustar00rootroot00000000000000Reading makefiles... Updating goal targets.... triple.Makefile:1 File `first' does not exist. triple.Makefile:3 File `second' does not exist. triple.Makefile:5 File `third' does not exist. triple.Makefile:5 Must remake target `third'. triple.Makefile:6 to update target `third'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5 Successfully remade target file `third'. triple.Makefile:3 Must remake target `second'. triple.Makefile:4 to update target `second'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo second done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< second done triple.Makefile:3 Successfully remade target file `second'. triple.Makefile:1 Must remake target `first'. triple.Makefile:2 to update target `first'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo first done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< first done triple.Makefile:1 Successfully remade target file `first'. remake-4.1+dbg1.3~dfsg.1/tests/spec/data/opt-y-trace.right000066400000000000000000000014471317072305000232110ustar00rootroot00000000000000Reading makefiles... Updating goal targets.... triple.Makefile:1 File `first' does not exist. triple.Makefile:3 File `second' does not exist. triple.Makefile:5 File `third' does not exist. triple.Makefile:5 Must remake target `third'. triple.Makefile:6 to update target `third'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< third done triple.Makefile:5 Successfully remade target file `third'. triple.Makefile:3 Must remake target `second'. triple.Makefile:4 to update target `second'. second done triple.Makefile:3 Successfully remade target file `second'. triple.Makefile:1 Must remake target `first'. triple.Makefile:2 to update target `first'. first done triple.Makefile:1 Successfully remade target file `first'. remake-4.1+dbg1.3~dfsg.1/tests/spec/data/remakerc000066400000000000000000000001001317072305000215030ustar00rootroot00000000000000expand "This is a test of the source system." target @ depends remake-4.1+dbg1.3~dfsg.1/tests/spec/data/set.right000066400000000000000000000016111317072305000216310ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... implicit.Makefile:2 File `foo.x' does not exist. implicit.Makefile:11) bar: remake<0> set set basename -- Set if we are to show short or long filenames is off. set debug -- Set GNU Make debug mask (set via --debug or -d) is 3361. set ignore-errors -- Set value of GNU Make --ignore-errors (or -i) flag is off. set keep-going -- Set value of GNU Make --keep-going (or -k) flag is off. set silent -- Set value of GNU Make --silent (or -s) flags. is off. set variable -- Set a GNU Make variable VARIABLE remake<1> set silent on silent is on. remake<2> set silent off silent is off. remake<3> set keep-going off keep-going is off. remake<4> expand $(word 2) remake: *** insufficient number of arguments (1) to function `word'. Stop. ** Internal error jumped back to debugger loop remake<5> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/source.right000066400000000000000000000004141317072305000223360ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> source /src/external-vcs/remake/tests/spec/data/remakerc "This is a test of the source system." first: second remake<1> quit remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/data/step3.right000066400000000000000000000021451317072305000220770ustar00rootroot00000000000000Reading makefiles... Updating makefiles.... Updating goal targets.... triple.Makefile:1) first: second remake<0> step triple.Makefile:1 File `first' does not exist. triple.Makefile:3) second: third remake<1> step triple.Makefile:3 File `second' does not exist. triple.Makefile:5) third: remake<2> step triple.Makefile:5 File `third' does not exist. triple.Makefile:5 Must remake target `third'. triple.Makefile:6 to update target `third'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo third done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< triple.Makefile:5) third remake<3> step third done triple.Makefile:5 Successfully remade target file `third'. triple.Makefile:5) third remake<4> step triple.Makefile:3 Must remake target `second'. triple.Makefile:4 to update target `second'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> echo second done ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< triple.Makefile:3) second remake<5> second done triple.Makefile:3 Successfully remade target file `second'. triple.Makefile:3) second remake<6> remake: That's all, folks... remake-4.1+dbg1.3~dfsg.1/tests/spec/example/000077500000000000000000000000001317072305000205225ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/tests/spec/example/.gitignore000066400000000000000000000000041317072305000225040ustar00rootroot00000000000000/*~ remake-4.1+dbg1.3~dfsg.1/tests/spec/example/commented.Makefile000066400000000000000000000002251317072305000241330ustar00rootroot00000000000000first: second @echo first done #: This is the second target second: third @echo second done #: This is the third target third: echo third done remake-4.1+dbg1.3~dfsg.1/tests/spec/example/debug-call.Makefile000066400000000000000000000001471317072305000241620ustar00rootroot00000000000000first: second $(debugger 2) @echo $@ done second: third @echo second done third: echo third done remake-4.1+dbg1.3~dfsg.1/tests/spec/example/debugger.Makefile000066400000000000000000000002771317072305000237530ustar00rootroot00000000000000# Makefile to show an explicit call to the debugger #: main target with an explicit call to the debugger all: $(debugger ) # note the space before the closing parenthesis echo "all here" remake-4.1+dbg1.3~dfsg.1/tests/spec/example/implicit.Makefile000066400000000000000000000001641317072305000237740ustar00rootroot00000000000000.SECONDEXPANSION: foo.x: foo.%: $$(%_a) $$(%_b) bar @: foo.x: x_a := bar %.x: x_b := baz bar baz: ; @echo '$@' remake-4.1+dbg1.3~dfsg.1/tests/spec/example/order-only.Makefile000066400000000000000000000001361317072305000242530ustar00rootroot00000000000000foo: bar | baz @echo '$$^ = $^' @echo '$$| = $|' touch $@ .PHONY: baz bar baz: touch $@ remake-4.1+dbg1.3~dfsg.1/tests/spec/example/simple.Makefile000066400000000000000000000002731317072305000234540ustar00rootroot00000000000000#: This is the main target all: echo all here #: test things check: echo check here # This target Has no description foo: echo foo here #: Build distribution dist: echo dist here remake-4.1+dbg1.3~dfsg.1/tests/spec/example/test2.Makefile000066400000000000000000000001451317072305000232220ustar00rootroot00000000000000PACKAGE=make all: $(PACKAGE).txt $(PACKAGE).txt: ../doc/remake.texi makeinfo --no-headers $< > $@ remake-4.1+dbg1.3~dfsg.1/tests/spec/example/triple.Makefile000066400000000000000000000001321317072305000234540ustar00rootroot00000000000000first: second @echo first done second: third @echo second done third: echo third done remake-4.1+dbg1.3~dfsg.1/tests/spec/helper.rb000066400000000000000000000032171317072305000206760ustar00rootroot00000000000000require 'rubygems' require 'rspec' require 'tmpdir' module RemakeTestHelper unless defined?(SPEC_DIR) SPEC_DIR = File.dirname(__FILE__) EXAMPLE_DIR = File.join(SPEC_DIR, 'example') DATA_DIR = File.join(SPEC_DIR, 'data') MAKE_PROG = File.join(SPEC_DIR, '..', '..', 'remake') Filter_filename = Proc.new{|makefile_short, lines| lines.each do |line| line.gsub!(/^.*(#{makefile_short}\.Makefile:\d+)/,'\1') line.gsub!(/ file .*(#{makefile_short})\.Makefile, line/,' file \1.Makefile, line') line.gsub!(/^# commands to execute \(from `.*#{makefile_short}/, "# commands to execute (from `#{makefile_short}") end } end module_function def run_remake(test_name, opts, makefile_short=nil) makefile_short = test_name unless makefile_short makefile = File.join(EXAMPLE_DIR, makefile_short + '.Makefile') rightfile = File.join(DATA_DIR, test_name + '.right') expected_output = File.open(rightfile, 'r').readlines.map{|l| l.chomp} cmd = "#{MAKE_PROG} #{opts[:flags]} #{makefile}" cmd = "#{opts[:input]} | #{cmd}" if opts[:input] lines = `#{cmd} 2>&1`.split("\n") lines = lines[6..-1] unless opts[:full] opts[:filter].call(makefile_short, lines) if opts[:filter] exit_status = opts[:exitstatus] || 77 if $?.exitstatus != exit_status puts expected_output end $?.exitstatus.should == exit_status unless opts[:no_check_output] if lines != expected_output File.open(Dir::tmpdir + "/#{test_name}.check", 'w') do |f| lines.map {|l| f.puts(l) } end end lines.should == expected_output end end end remake-4.1+dbg1.3~dfsg.1/tests/spec/run-tests.rb000077500000000000000000000001221317072305000213560ustar00rootroot00000000000000#!/usr/bin/env ruby dir = File.dirname(__FILE__) system("rspec #{dir}/test-*.rb") remake-4.1+dbg1.3~dfsg.1/tests/spec/test-break.rb000066400000000000000000000021771317072305000214640ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "breakpoints" do include RemakeTestHelper it 'should be able to do set a breakpoint on a target with subopt' do ['end', 'prereq', 'run'].each do |break_opt| opts = { :filter => Filter_filename, :flags =>'-X -f', :input => "echo 'break third #{break_opt} continue quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake("#{test_name}-#{break_opt}", opts, 'triple') end end it 'should be able to do set a breakpoint on a target' do opts = { :filter => Filter_filename, :flags =>'-X -f', :input => "echo 'break third continue continue continue quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake("#{test_name}-all", opts, 'triple') end it 'should be able to do set a breakpoint on a target with expansion' do opts = { :filter => Filter_filename, :flags =>'-X -f', :input => "echo 'break $(PACKAGE).txt quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake("#{test_name}-expand", opts, 'test2') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-commented.rb000066400000000000000000000005751317072305000223530ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "remake --tasks" do include RemakeTestHelper it 'should show commented targets on tasks' do opts = { :exitstatus => 0, :flags => '--tasks -f', :full => true } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'commented') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-continue.rb000066400000000000000000000006601317072305000222170ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "continue" do include RemakeTestHelper it 'should be able to do handle simple debugger stepping' do opts = { :filter => Filter_filename, :exitstatus => 0, :flags => '-X -f', :input => "echo 'continue third finish 10 finish 2 '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-info-rule.rb000066400000000000000000000006761317072305000223020ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "info rule" do include RemakeTestHelper it 'should be able to do run an "info rule" command' do opts = { :filter => Filter_filename, :no_check_output => true, :flags => '-X -f', :input => "echo 'info rule quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'implicit') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-info-target.rb000066400000000000000000000007241317072305000226130ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "info target" do include RemakeTestHelper it 'should run info target order, nonorder, and depend command' do opts = { :filter => Filter_filename, :flags => '-X -f', :input => "echo 'target @ order target @ nonorder target @ depend quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'order-only') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-info-targets.rb000066400000000000000000000007351317072305000230000ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "info target" do include RemakeTestHelper it 'should run "info targets", and with options "name" and "position"' do opts = { :filter => Filter_filename, :flags => '-X -f', :input => "echo 'info targets info targets names info targets positions quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-list.rb000066400000000000000000000007121317072305000213440ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "list" do include RemakeTestHelper it 'should be able to run plain list, list with line number, and target' do opts = { :filter => Filter_filename, :exitstatus => 77, :flags =>'-X -f', :input => "echo 'list list third list 3 list 6 quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake("#{test_name}", opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-norl.rb000066400000000000000000000007001317072305000213400ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "no readline" do include RemakeTestHelper it 'should be able to do work without readline support' do opts = { :filter => Filter_filename, :exitstatus => 0, :flags => '-X --no-readline -f', :input => "echo 'continue third finish 2 '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-set.rb000066400000000000000000000007211317072305000211640ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "test-set" do include RemakeTestHelper it 'should be able to do run a "set" command' do opts = { :filter => Filter_filename, :flags => '-X -f', :input => "echo 'set set silent on set silent off set keep-going off expand $(word 2) quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'implicit') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-source.rb000066400000000000000000000006351317072305000216750ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "debugger 'source' command" do include RemakeTestHelper it 'should be able to do run a source command' do opts = { :filter => Filter_filename, :flags => '-X -f', :input => "echo 'source #{DATA_DIR}/remakerc quit '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-step3.rb000066400000000000000000000006271317072305000214340ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "debugger stepping" do include RemakeTestHelper it 'should be able to do handle simple debugger stepping' do opts = { :filter => Filter_filename, :flags => '-X -f', :input => "echo 'step step step step step '" } test_name = File.basename(__FILE__, '.rb')[5..-1] run_remake(test_name, opts, 'triple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-tasks.rb000066400000000000000000000005371317072305000215230ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "A --tasks options" do include RemakeTestHelper before(:each) do @opts = { :exitstatus => 0, :full => true, } end it 'should be able to give trace descriptions)' do @opts[:flags] = '--tasks -f' run_remake('description-trace', @opts, 'simple') end end remake-4.1+dbg1.3~dfsg.1/tests/spec/test-trace.rb000066400000000000000000000016031317072305000214670ustar00rootroot00000000000000#!/usr/bin/env ruby require_relative 'helper' describe "A simple trace" do include RemakeTestHelper before(:each) do @opts = { :filter => Filter_filename, :exitstatus => 0, } end it 'should be able to do handle --trace (no options)' do ['--trace --file', '-x -f'].each do |flags| p flags if $DEBUG @opts[:flags] = flags run_remake('opt-x-trace', @opts, 'triple') end end it 'should be able to do handle -y (--trace=nohshell options)' do ['--trace=noshell -f', '-y -f'].each do |flags| p flags if $DEBUG @opts[:flags] = flags run_remake('opt-y-trace', @opts, 'triple') end end # it 'should be give a warning for -x and -y' do # flags = ['-x -y', '-y -x'].each do |flags| # p flags if $DEBUG # @opts[:flags] = flags # run_remake('opt-x-y-trace', @opts, 'simple') # end # end end remake-4.1+dbg1.3~dfsg.1/tests/test_driver.pl000066400000000000000000001215531317072305000210330ustar00rootroot00000000000000#!/usr/bin/perl # -*-perl-*- # # Modification history: # Written 91-12-02 through 92-01-01 by Stephen McGee. # Modified 92-02-11 through 92-02-22 by Chris Arthur to further generalize. # # Copyright (C) 1991-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # Test driver routines used by a number of test suites, including # those for SCS, make, roll_dir, and scan_deps (?). # # this routine controls the whole mess; each test suite sets up a few # variables and then calls &toplevel, which does all the real work. # $Id$ # The number of test categories we've run $categories_run = 0; # The number of test categroies that have passed $categories_passed = 0; # The total number of individual tests that have been run $total_tests_run = 0; # The total number of individual tests that have passed $total_tests_passed = 0; # The number of tests in this category that have been run $tests_run = 0; # The number of tests in this category that have passed $tests_passed = 0; # Yeesh. This whole test environment is such a hack! $test_passed = 1; # Timeout in seconds. If the test takes longer than this we'll fail it. $test_timeout = 5; $test_timeout = 10 if $^O eq 'VMS'; # Path to Perl $perl_name = $^X; # %makeENV is the cleaned-out environment. %makeENV = (); # %extraENV are any extra environment variables the tests might want to set. # These are RESET AFTER EVERY TEST! %extraENV = (); sub vms_get_process_logicals { # Sorry for the long note here, but to keep this test running on # VMS, it is needed to be understood. # # Perl on VMS by default maps the %ENV array to the system wide logical # name table. # # This is a very large dynamically changing table. # On Linux, this would be the equivalent of a table that contained # every mount point, temporary pipe, and symbolic link on every # file system. You normally do not have permission to clear or replace it, # and if you did, the results would be catastrophic. # # On VMS, added/changed %ENV items show up in the process logical # name table. So to track changes, a copy of it needs to be captured. my $raw_output = `show log/process/access_mode=supervisor`; my @raw_output_lines = split('\n',$raw_output); my %log_hash; foreach my $line (@raw_output_lines) { if ($line =~ /^\s+"([A-Za-z\$_]+)"\s+=\s+"(.+)"$/) { $log_hash{$1} = $2; } } return \%log_hash } # %origENV is the caller's original environment if ($^O ne 'VMS') { %origENV = %ENV; } else { my $proc_env = vms_get_process_logicals; %origENV = %{$proc_env}; } sub resetENV { # We used to say "%ENV = ();" but this doesn't work in Perl 5.000 # through Perl 5.004. It was fixed in Perl 5.004_01, but we don't # want to require that here, so just delete each one individually. if ($^O ne 'VMS') { foreach $v (keys %ENV) { delete $ENV{$v}; } %ENV = %makeENV; } else { my $proc_env = vms_get_process_logicals(); my %delta = %{$proc_env}; foreach my $v (keys %delta) { if (exists $origENV{$v}) { if ($origENV{$v} ne $delta{$v}) { $ENV{$v} = $origENV{$v}; } } else { delete $ENV{$v}; } } } foreach $v (keys %extraENV) { $ENV{$v} = $extraENV{$v}; delete $extraENV{$v}; } } sub toplevel { # Pull in benign variables from the user's environment foreach (# UNIX-specific things 'TZ', 'TMPDIR', 'HOME', 'USER', 'LOGNAME', 'PATH', 'LD_LIBRARY_PATH', # Purify things 'PURIFYOPTIONS', # Windows NT-specific stuff 'Path', 'SystemRoot', # DJGPP-specific stuff 'DJDIR', 'DJGPP', 'SHELL', 'COMSPEC', 'HOSTNAME', 'LFN', 'FNCASE', '387', 'EMU387', 'GROUP' ) { $makeENV{$_} = $ENV{$_} if $ENV{$_}; } # Make sure our compares are not foiled by locale differences $makeENV{LC_ALL} = 'C'; # HACK. On Debian, ar is now compiled with determinism, which makes # make tests fail. Pass in the U modifier to revert that behaviour change # If ar has not been changed, this should be a no-op. $makeENV{ARFLAGS} = 'rvU'; # Replace the environment with the new one # %origENV = %ENV unless $^O eq 'VMS'; resetENV(); $| = 1; # unbuffered output $debug = 0; # debug flag $profile = 0; # profiling flag $verbose = 0; # verbose mode flag $detail = 0; # detailed verbosity $keep = 0; # keep temp files around $workdir = "work"; # The directory where the test will start running $scriptdir = "scripts"; # The directory where we find the test scripts $tmpfilesuffix = "t"; # the suffix used on tmpfiles $default_output_stack_level = 0; # used by attach_default_output, etc. $default_input_stack_level = 0; # used by attach_default_input, etc. $cwd = "."; # don't we wish we knew $cwdslash = ""; # $cwd . $pathsep, but "" rather than "./" &get_osname; # sets $osname, $vos, $pathsep, and $short_filenames &set_defaults; # suite-defined &parse_command_line (@ARGV); print "OS name = '$osname'\n" if $debug; $workpath = "$cwdslash$workdir"; $scriptpath = "$cwdslash$scriptdir"; &set_more_defaults; # suite-defined &print_banner; if ($osname eq 'VMS' && $cwdslash eq "") { # Porting this script to VMS revealed a small bug in opendir() not # handling search lists correctly when the directory only exists in # one of the logical_devices. Need to find the first directory in # the search list, as that is where things will be written to. my @dirs = split("/", $pwd); my $logical_device = $ENV{$dirs[1]}; if ($logical_device =~ /([A-Za-z0-9_]+):(:?.+:)+/) { # A search list was found. Grab the first logical device # and use it instead of the search list. $dirs[1]=$1; my $lcl_pwd = join('/', @dirs); $workpath = $lcl_pwd . '/' . $workdir } } if (-d $workpath) { print "Clearing $workpath...\n"; &remove_directory_tree("$workpath/") || &error ("Couldn't wipe out $workpath\n"); } else { mkdir ($workpath, 0777) || &error ("Couldn't mkdir $workpath: $!\n"); } if (!-d $scriptpath) { &error ("Failed to find $scriptpath containing perl test scripts.\n"); } if (@TESTS) { print "Making work dirs...\n"; foreach $test (@TESTS) { if ($test =~ /^([^\/]+)\//) { $dir = $1; push (@rmdirs, $dir); -d "$workpath/$dir" || mkdir ("$workpath/$dir", 0777) || &error ("Couldn't mkdir $workpath/$dir: $!\n"); } } } else { print "Finding tests...\n"; opendir (SCRIPTDIR, $scriptpath) || &error ("Couldn't opendir $scriptpath: $!\n"); @dirs = grep (!/^(\..*|CVS|RCS)$/, readdir (SCRIPTDIR) ); closedir (SCRIPTDIR); foreach $dir (@dirs) { next if ($dir =~ /^(\..*|CVS|RCS)$/ || ! -d "$scriptpath/$dir"); push (@rmdirs, $dir); # VMS can have overlayed file systems, so directories may repeat. next if -d "$workpath/$dir"; mkdir ("$workpath/$dir", 0777) || &error ("Couldn't mkdir $workpath/$dir: $!\n"); opendir (SCRIPTDIR, "$scriptpath/$dir") || &error ("Couldn't opendir $scriptpath/$dir: $!\n"); @files = grep (!/^(\..*|CVS|RCS|.*~)$/, readdir (SCRIPTDIR) ); closedir (SCRIPTDIR); foreach $test (@files) { -d $test and next; push (@TESTS, "$dir/$test"); } } } if (@TESTS == 0) { &error ("\nNo tests in $scriptpath, and none were specified.\n"); } print "\n"; run_all_tests(); foreach $dir (@rmdirs) { rmdir ("$workpath/$dir"); } $| = 1; $categories_failed = $categories_run - $categories_passed; $total_tests_failed = $total_tests_run - $total_tests_passed; if ($total_tests_failed) { print "\n$total_tests_failed Test"; print "s" unless $total_tests_failed == 1; print " in $categories_failed Categor"; print ($categories_failed == 1 ? "y" : "ies"); print " Failed (See .$diffext* files in $workdir dir for details) :-(\n\n"; return 0; } else { print "\n$total_tests_passed Test"; print "s" unless $total_tests_passed == 1; print " in $categories_passed Categor"; print ($categories_passed == 1 ? "y" : "ies"); print " Complete ... No Failures :-)\n\n"; return 1; } } sub get_osname { # Set up an initial value. In perl5 we can do it the easy way. $osname = defined($^O) ? $^O : ''; if ($osname eq 'VMS') { $vos = 0; $pathsep = "/"; return; } # Find a path to Perl # See if the filesystem supports long file names with multiple # dots. DOS doesn't. $short_filenames = 0; (open (TOUCHFD, "> fancy.file.name") && close (TOUCHFD)) || ($short_filenames = 1); unlink ("fancy.file.name") || ($short_filenames = 1); if (! $short_filenames) { # Thanks go to meyering@cs.utexas.edu (Jim Meyering) for suggesting a # better way of doing this. (We used to test for existence of a /mnt # dir, but that apparently fails on an SGI Indigo (whatever that is).) # Because perl on VOS translates /'s to >'s, we need to test for # VOSness rather than testing for Unixness (ie, try > instead of /). mkdir (".ostest", 0777) || &error ("Couldn't create .ostest: $!\n", 1); open (TOUCHFD, "> .ostest>ick") && close (TOUCHFD); chdir (".ostest") || &error ("Couldn't chdir to .ostest: $!\n", 1); } if (! $short_filenames && -f "ick") { $osname = "vos"; $vos = 1; $pathsep = ">"; } else { # the following is regrettably knarly, but it seems to be the only way # to not get ugly error messages if uname can't be found. # Hmmm, BSD/OS 2.0's uname -a is excessively verbose. Let's try it # with switches first. eval "chop (\$osname = `sh -c 'uname -nmsr 2>&1'`)"; if ($osname =~ /not found/i) { $osname = "(something posixy with no uname)"; } elsif ($@ ne "" || $?) { eval "chop (\$osname = `sh -c 'uname -a 2>&1'`)"; if ($@ ne "" || $?) { $osname = "(something posixy)"; } } $vos = 0; $pathsep = "/"; } if (! $short_filenames) { chdir ("..") || &error ("Couldn't chdir to ..: $!\n", 1); unlink (".ostest>ick"); rmdir (".ostest") || &error ("Couldn't rmdir .ostest: $!\n", 1); } } sub parse_command_line { @argv = @_; # use @ARGV if no args were passed in if (@argv == 0) { @argv = @ARGV; } # look at each option; if we don't recognize it, maybe the suite-specific # command line parsing code will... while (@argv) { $option = shift @argv; if ($option =~ /^-debug$/i) { print "\nDEBUG ON\n"; $debug = 1; } elsif ($option =~ /^-usage$/i) { &print_usage; exit 0; } elsif ($option =~ /^-(h|help)$/i) { &print_help; exit 0; } elsif ($option =~ /^-profile$/i) { $profile = 1; } elsif ($option =~ /^-verbose$/i) { $verbose = 1; } elsif ($option =~ /^-detail$/i) { $detail = 1; $verbose = 1; } elsif ($option =~ /^-keep$/i) { $keep = 1; } elsif (&valid_option($option)) { # The suite-defined subroutine takes care of the option } elsif ($option =~ /^-/) { print "Invalid option: $option\n"; &print_usage; exit 0; } else # must be the name of a test { $option =~ s/\.pl$//; push(@TESTS,$option); } } } sub max { local($num) = shift @_; local($newnum); while (@_) { $newnum = shift @_; if ($newnum > $num) { $num = $newnum; } } return $num; } sub print_centered { local($width, $string) = @_; local($pad); if (length ($string)) { $pad = " " x ( ($width - length ($string) + 1) / 2); print "$pad$string"; } } sub print_banner { local($info); local($line); local($len); $info = "Running tests for $testee on $osname\n"; # $testee is suite-defined $len = &max (length ($line), length ($testee_version), length ($banner_info), 73) + 5; $line = ("-" x $len) . "\n"; if ($len < 78) { $len = 78; } &print_centered ($len, $line); &print_centered ($len, $info); &print_centered ($len, $testee_version); # suite-defined &print_centered ($len, $banner_info); # suite-defined &print_centered ($len, $line); print "\n"; } sub run_all_tests { $categories_run = 0; $lasttest = ''; foreach $testname (sort @TESTS) { # Skip duplicates on VMS caused by logical name search lists. next if $testname eq $lasttest; $lasttest = $testname; $suite_passed = 1; # reset by test on failure $num_of_logfiles = 0; $num_of_tmpfiles = 0; $description = ""; $details = ""; $old_makefile = undef; $testname =~ s/^$scriptpath$pathsep//; $perl_testname = "$scriptpath$pathsep$testname"; $testname =~ s/(\.pl|\.perl)$//; $testpath = "$workpath$pathsep$testname"; # Leave enough space in the extensions to append a number, even # though it needs to fit into 8+3 limits. if ($short_filenames) { $logext = 'l'; $diffext = 'd'; $baseext = 'b'; $runext = 'r'; $extext = ''; } else { $logext = 'log'; $diffext = 'diff'; $baseext = 'base'; $runext = 'run'; $extext = '.'; } $extext = '_' if $^O eq 'VMS'; $log_filename = "$testpath.$logext"; $diff_filename = "$testpath.$diffext"; $base_filename = "$testpath.$baseext"; $run_filename = "$testpath.$runext"; $tmp_filename = "$testpath.$tmpfilesuffix"; setup_for_test(); $output = "........................................................ "; substr($output,0,length($testname)) = "$testname "; print $output; $tests_run = 0; $tests_passed = 0; # Run the test! $code = do $perl_testname; ++$categories_run; $total_tests_run += $tests_run; $total_tests_passed += $tests_passed; # How did it go? if (!defined($code)) { # Failed to parse or called die if (length ($@)) { warn "\n*** Test died ($testname): $@\n"; } else { warn "\n*** Couldn't parse $perl_testname\n"; } $status = "FAILED ($tests_passed/$tests_run passed)"; } elsif ($code == -1) { # Skipped... not supported $status = "N/A"; --$categories_run; } elsif ($code != 1) { # Bad result... this shouldn't really happen. Usually means that # the suite forgot to end with "1;". warn "\n*** Test returned $code\n"; $status = "FAILED ($tests_passed/$tests_run passed)"; } elsif ($tests_run == 0) { # Nothing was done!! $status = "FAILED (no tests found!)"; } elsif ($tests_run > $tests_passed) { # Lose! $status = "FAILED ($tests_passed/$tests_run passed)"; } else { # Win! ++$categories_passed; $status = "ok ($tests_passed passed)"; # Clean up for ($i = $num_of_tmpfiles; $i; $i--) { rmfiles($tmp_filename . num_suffix($i)); } for ($i = $num_of_logfiles ? $num_of_logfiles : 1; $i; $i--) { rmfiles($log_filename . num_suffix($i)); rmfiles($base_filename . num_suffix($i)); } } # If the verbose option has been specified, then a short description # of each test is printed before displaying the results of each test # describing WHAT is being tested. if ($verbose) { if ($detail) { print "\nWHAT IS BEING TESTED\n"; print "--------------------"; } print "\n\n$description\n\n"; } # If the detail option has been specified, then the details of HOW # the test is testing what it says it is testing in the verbose output # will be displayed here before the results of the test are displayed. if ($detail) { print "\nHOW IT IS TESTED\n"; print "----------------"; print "\n\n$details\n\n"; } print "$status\n"; } } # If the keep flag is not set, this subroutine deletes all filenames that # are sent to it. sub rmfiles { local(@files) = @_; if (!$keep) { return (unlink @files); } return 1; } sub print_standard_usage { local($plname,@moreusage) = @_; local($line); print "usage:\t$plname [testname] [-verbose] [-detail] [-keep]\n"; print "\t\t\t[-profile] [-usage] [-help] [-debug]\n"; foreach (@moreusage) { print "\t\t\t$_\n"; } } sub print_standard_help { local(@morehelp) = @_; local($line); local($tline); local($t) = " "; $line = "Test Driver For $testee"; print "$line\n"; $line = "=" x length ($line); print "$line\n"; &print_usage; print "\ntestname\n" . "${t}You may, if you wish, run only ONE test if you know the name\n" . "${t}of that test and specify this name anywhere on the command\n" . "${t}line. Otherwise ALL existing tests in the scripts directory\n" . "${t}will be run.\n" . "-verbose\n" . "${t}If this option is given, a description of every test is\n" . "${t}displayed before the test is run. (Not all tests may have\n" . "${t}descriptions at this time)\n" . "-detail\n" . "${t}If this option is given, a detailed description of every\n" . "${t}test is displayed before the test is run. (Not all tests\n" . "${t}have descriptions at this time)\n" . "-profile\n" . "${t}If this option is given, then the profile file\n" . "${t}is added to other profiles every time $testee is run.\n" . "${t}This option only works on VOS at this time.\n" . "-keep\n" . "${t}You may give this option if you DO NOT want ANY\n" . "${t}of the files generated by the tests to be deleted. \n" . "${t}Without this option, all files generated by the test will\n" . "${t}be deleted IF THE TEST PASSES.\n" . "-debug\n" . "${t}Use this option if you would like to see all of the system\n" . "${t}calls issued and their return status while running the tests\n" . "${t}This can be helpful if you're having a problem adding a test\n" . "${t}to the suite, or if the test fails!\n"; foreach $line (@morehelp) { $tline = $line; if (substr ($tline, 0, 1) eq "\t") { substr ($tline, 0, 1) = $t; } print "$tline\n"; } } ####################################################################### ########### Generic Test Driver Subroutines ########### ####################################################################### sub get_caller { local($depth); local($package); local($filename); local($linenum); $depth = defined ($_[0]) ? $_[0] : 1; ($package, $filename, $linenum) = caller ($depth + 1); return "$filename: $linenum"; } sub error { local($message) = $_[0]; local($caller) = &get_caller (1); if (defined ($_[1])) { $caller = &get_caller ($_[1] + 1) . " -> $caller"; } die "$caller: $message"; } sub compare_output { local($answer,$logfile) = @_; local($slurp, $answer_matched) = ('', 0); ++$tests_run; if (! defined $answer) { print "Ignoring output ........ " if $debug; $answer_matched = 1; } else { print "Comparing Output ........ " if $debug; $slurp = &read_file_into_string ($logfile); # For make, get rid of any time skew error before comparing--too bad this # has to go into the "generic" driver code :-/ $slurp =~ s/^.*modification time .*in the future.*\n//gm; $slurp =~ s/^.*Clock skew detected.*\n//gm; if ($slurp eq $answer) { $answer_matched = 1; } else { # See if it is a slash or CRLF problem local ($answer_mod, $slurp_mod) = ($answer, $slurp); $answer_mod =~ tr,\\,/,; $answer_mod =~ s,\r\n,\n,gs; $slurp_mod =~ tr,\\,/,; $slurp_mod =~ s,\r\n,\n,gs; $answer_matched = ($slurp_mod eq $answer_mod); if ($^O eq 'VMS') { # VMS has extra blank lines in output sometimes. # Ticket #41760 if (!$answer_matched) { $slurp_mod =~ s/\n\n+/\n/gm; $slurp_mod =~ s/\A\n+//g; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS adding a "Waiting for unfinished jobs..." # Remove it for now to see what else is going on. if (!$answer_matched) { $slurp_mod =~ s/^.+\*\*\* Waiting for unfinished jobs.+$//m; $slurp_mod =~ s/\n\n/\n/gm; $slurp_mod =~ s/^\n+//gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS wants target device to exist or generates an error, # Some test tagets look like VMS devices and trip this. if (!$answer_matched) { $slurp_mod =~ s/^.+\: no such device or address.*$//gim; $slurp_mod =~ s/\n\n/\n/gm; $slurp_mod =~ s/^\n+//gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS error message has a different case if (!$answer_matched) { $slurp_mod =~ s/no such file /No such file /gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS is putting comas instead of spaces in output if (!$answer_matched) { $slurp_mod =~ s/,/ /gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS Is sometimes adding extra leading spaces to output? if (!$answer_matched) { my $slurp_mod = $slurp_mod; $slurp_mod =~ s/^ +//gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS port not handling POSIX encoded child status # Translate error case it for now. if (!$answer_matched) { $slurp_mod =~ s/0x1035a00a/1/gim; $answer_matched = 1 if $slurp_mod =~ /\Q$answer_mod\E/i; } if (!$answer_matched) { $slurp_mod =~ s/0x1035a012/2/gim; $answer_matched = ($slurp_mod eq $answer_mod); } # Tests are using a UNIX null command, temp hack # until this can be handled by the VMS port. # ticket # 41761 if (!$answer_matched) { $slurp_mod =~ s/^.+DCL-W-NOCOMD.*$//gim; $slurp_mod =~ s/\n\n+/\n/gm; $slurp_mod =~ s/^\n+//gm; $answer_matched = ($slurp_mod eq $answer_mod); } # Tests are using exit 0; # this generates a warning that should stop the make, but does not if (!$answer_matched) { $slurp_mod =~ s/^.+NONAME-W-NOMSG.*$//gim; $slurp_mod =~ s/\n\n+/\n/gm; $slurp_mod =~ s/^\n+//gm; $answer_matched = ($slurp_mod eq $answer_mod); } # VMS is sometimes adding single quotes to output? if (!$answer_matched) { my $noq_slurp_mod = $slurp_mod; $noq_slurp_mod =~ s/\'//gm; $answer_matched = ($noq_slurp_mod eq $answer_mod); # And missing an extra space in output if (!$answer_matched) { $noq_answer_mod = $answer_mod; $noq_answer_mod =~ s/\h\h+/ /gm; $answer_matched = ($noq_slurp_mod eq $noq_answer_mod); } # VMS adding ; to end of some lines. if (!$answer_matched) { $noq_slurp_mod =~ s/;\n/\n/gm; $answer_matched = ($noq_slurp_mod eq $noq_answer_mod); } # VMS adding trailing space to end of some quoted lines. if (!$answer_matched) { $noq_slurp_mod =~ s/\h+\n/\n/gm; $answer_matched = ($noq_slurp_mod eq $noq_answer_mod); } # And VMS missing leading blank line if (!$answer_matched) { $noq_answer_mod =~ s/\A\n//g; $answer_matched = ($noq_slurp_mod eq $noq_answer_mod); } # Unix double quotes showing up as single quotes on VMS. if (!$answer_matched) { $noq_answer_mod =~ s/\"//g; $answer_matched = ($noq_slurp_mod eq $noq_answer_mod); } } } # If it still doesn't match, see if the answer might be a regex. if (!$answer_matched && $answer =~ m,^/(.+)/$,) { $answer_matched = ($slurp =~ /$1/); if (!$answer_matched && $answer_mod =~ m,^/(.+)/$,) { $answer_matched = ($slurp_mod =~ /$1/); } } } } if ($answer_matched && $test_passed) { print "ok\n" if $debug; ++$tests_passed; return 1; } if (! $answer_matched) { print "DIFFERENT OUTPUT\n" if $debug; &create_file (&get_basefile, $answer); &create_file (&get_runfile, $command_string); print "\nCreating Difference File ...\n" if $debug; # Create the difference file local($command) = "diff -c " . &get_basefile . " " . $logfile; &run_command_with_output(&get_difffile,$command); } return 0; } sub compare_output_string { my($answer,$slurp,$logfile) = @_; my($answer_matched) = (0); print "Comparing Output ........ " if $debug; $slurp = subst_make_string($slurp); $answer = subst_make_string($answer); # For make, get rid of any time skew error before comparing--too bad this # has to go into the "generic" driver code :-/ $slurp =~ s/^.*modification time .*in the future.*\n//gm; $slurp =~ s/^.*Clock skew detected.*\n//gm; ++$tests_run; if ($slurp eq $answer) { $answer_matched = 1; } else { # See if it is a slash or CRLF problem my ($answer_mod) = $answer; $answer_mod =~ tr,\\,/,; $answer_mod =~ s,\r\n,\n,gs; $slurp =~ tr,\\,/,; $slurp =~ s,\r\n,\n,gs; $answer_matched = ($slurp eq $answer_mod); } if ($answer_matched && $test_passed) { print "ok\n" if $debug; ++$tests_passed; return 1; } if (! $answer_matched) { if ($debug) { print "DIFFERENT OUTPUT\n"; print "+++1:\n$answer\n"; print "+++2:\n$slurp\n"; } &create_file (&get_basefile, $answer); print "\nCreating Difference File ...\n" if $debug; # Create the difference file open(LOGFILE, ">$logfile") && print(LOGFILE $slurp) && close(LOGFILE); local($command) = "diff -c " . &get_basefile . " " . $logfile; &run_command_with_output(&get_difffile,$command); } $suite_passed = 0; return 0; } sub read_file_into_string { local($filename) = @_; local($oldslash) = $/; undef $/; open (RFISFILE, $filename) || return ""; local ($slurp) = ; close (RFISFILE); $/ = $oldslash; return $slurp; } my @OUTSTACK = (); my @ERRSTACK = (); sub attach_default_output { local ($filename) = @_; local ($code); if ($vos) { $code = system "++attach_default_output_hack $filename"; $code == -2 || &error ("adoh death\n", 1); return 1; } my $dup = undef; open($dup, '>&', STDOUT) or error("ado: $! duping STDOUT\n", 1); push @OUTSTACK, $dup; $dup = undef; open($dup, '>&', STDERR) or error("ado: $! duping STDERR\n", 1); push @ERRSTACK, $dup; open(STDOUT, '>', $filename) or error("ado: $filename: $!\n", 1); open(STDERR, ">&STDOUT") or error("ado: $filename: $!\n", 1); } # close the current stdout/stderr, and restore the previous ones from # the "stack." sub detach_default_output { local ($code); if ($vos) { $code = system "++detach_default_output_hack"; $code == -2 || &error ("ddoh death\n", 1); return 1; } @OUTSTACK or error("default output stack has flown under!\n", 1); close(STDOUT); close(STDERR) unless $^O eq 'VMS'; open (STDOUT, '>&', pop @OUTSTACK) or error("ddo: $! duping STDOUT\n", 1); open (STDERR, '>&', pop @ERRSTACK) or error("ddo: $! duping STDERR\n", 1); } # This runs a command without any debugging info. sub _run_command { my $code; # We reset this before every invocation. On Windows I think there is only # one environment, not one per process, so I think that variables set in # test scripts might leak into subsequent tests if this isn't reset--??? resetENV(); eval { if ($^O eq 'VMS') { local $SIG{ALRM} = sub { my $e = $ERRSTACK[0]; print $e "\nTest timed out after $test_timeout seconds\n"; die "timeout\n"; }; # alarm $test_timeout; system(@_); my $severity = ${^CHILD_ERROR_NATIVE} & 7; $code = 0; if (($severity & 1) == 0) { $code = 512; } # Get the vms status. my $vms_code = ${^CHILD_ERROR_NATIVE}; # Remove the print status bit $vms_code &= ~0x10000000; # Posix code translation. if (($vms_code & 0xFFFFF000) == 0x35a000) { $code = (($vms_code & 0xFFF) >> 3) * 256; } } else { my $pid = fork(); if (! $pid) { exec(@_) or die "Cannot execute $_[0]\n"; } local $SIG{ALRM} = sub { my $e = $ERRSTACK[0]; print $e "\nTest timed out after $test_timeout seconds\n"; die "timeout\n"; }; alarm $test_timeout; waitpid($pid, 0) > 0 or die "No such pid: $pid\n"; $code = $?; } alarm 0; }; if ($@) { # The eval failed. If it wasn't SIGALRM then die. $@ eq "timeout\n" or die "Command failed: $@"; # Timed out. Resend the alarm to our process group to kill the children. $SIG{ALRM} = 'IGNORE'; kill -14, $$; $code = 14; } return $code; } # run one command (passed as a list of arg 0 - n), returning 0 on success # and nonzero on failure. sub run_command { print "\nrun_command: @_\n" if $debug; my $code = _run_command(@_); print "run_command returned $code.\n" if $debug; print "vms status = ${^CHILD_ERROR_NATIVE}\n" if $debug and $^O eq 'VMS'; return $code; } # run one command (passed as a list of arg 0 - n, with arg 0 being the # second arg to this routine), returning 0 on success and non-zero on failure. # The first arg to this routine is a filename to connect to the stdout # & stderr of the child process. sub run_command_with_output { my $filename = shift; print "\nrun_command_with_output($filename,$runname): @_\n" if $debug; &attach_default_output ($filename); my $code = eval { _run_command(@_) }; my $err = $@; &detach_default_output; $err and die $err; print "run_command_with_output returned $code.\n" if $debug; print "vms status = ${^CHILD_ERROR_NATIVE}\n" if $debug and $^O eq 'VMS'; return $code; } # performs the equivalent of an "rm -rf" on the first argument. Like # rm, if the path ends in /, leaves the (now empty) directory; otherwise # deletes it, too. sub remove_directory_tree { local ($targetdir) = @_; local ($nuketop) = 1; local ($ch); $ch = substr ($targetdir, length ($targetdir) - 1); if ($ch eq "/" || $ch eq $pathsep) { $targetdir = substr ($targetdir, 0, length ($targetdir) - 1); $nuketop = 0; } if (! -e $targetdir) { return 1; } &remove_directory_tree_inner ("RDT00", $targetdir) || return 0; if ($nuketop) { rmdir $targetdir || return 0; } return 1; } sub remove_directory_tree_inner { local ($dirhandle, $targetdir) = @_; local ($object); local ($subdirhandle); opendir ($dirhandle, $targetdir) || return 0; $subdirhandle = $dirhandle; $subdirhandle++; while ($object = readdir ($dirhandle)) { if ($object =~ /^(\.\.?|CVS|RCS)$/) { next; } $object = "$targetdir$pathsep$object"; lstat ($object); if (-d _ && &remove_directory_tree_inner ($subdirhandle, $object)) { rmdir $object || return 0; } else { if ($^O ne 'VMS') { unlink $object || return 0; } else { # VMS can have multiple versions of a file. 1 while unlink $object; } } } closedir ($dirhandle); return 1; } # We used to use this behavior for this function: # #sub touch #{ # local (@filenames) = @_; # local ($now) = time; # local ($file); # # foreach $file (@filenames) # { # utime ($now, $now, $file) # || (open (TOUCHFD, ">> $file") && close (TOUCHFD)) # || &error ("Couldn't touch $file: $!\n", 1); # } # return 1; #} # # But this behaves badly on networked filesystems where the time is # skewed, because it sets the time of the file based on the _local_ # host. Normally when you modify a file, it's the _remote_ host that # determines the modtime, based on _its_ clock. So, instead, now we open # the file and write something into it to force the remote host to set # the modtime correctly according to its clock. # sub touch { local ($file); foreach $file (@_) { (open(T, ">> $file") && print(T "\n") && close(T)) || &error("Couldn't touch $file: $!\n", 1); } } # Touch with a time offset. To DTRT, call touch() then use stat() to get the # access/mod time for each file and apply the offset. sub utouch { local ($off) = shift; local ($file); &touch(@_); local (@s) = stat($_[0]); utime($s[8]+$off, $s[9]+$off, @_); } # open a file, write some stuff to it, and close it. sub create_file { local ($filename, @lines) = @_; open (CF, "> $filename") || &error ("Couldn't open $filename: $!\n", 1); foreach $line (@lines) { print CF $line; } close (CF); } # create a directory tree described by an associative array, wherein each # key is a relative pathname (using slashes) and its associated value is # one of: # DIR indicates a directory # FILE:contents indicates a file, which should contain contents +\n # LINK:target indicates a symlink, pointing to $basedir/target # The first argument is the dir under which the structure will be created # (the dir will be made and/or cleaned if necessary); the second argument # is the associative array. sub create_dir_tree { local ($basedir, %dirtree) = @_; local ($path); &remove_directory_tree ("$basedir"); mkdir ($basedir, 0777) || &error ("Couldn't mkdir $basedir: $!\n", 1); foreach $path (sort keys (%dirtree)) { if ($dirtree {$path} =~ /^DIR$/) { mkdir ("$basedir/$path", 0777) || &error ("Couldn't mkdir $basedir/$path: $!\n", 1); } elsif ($dirtree {$path} =~ /^FILE:(.*)$/) { &create_file ("$basedir/$path", $1 . "\n"); } elsif ($dirtree {$path} =~ /^LINK:(.*)$/) { symlink ("$basedir/$1", "$basedir/$path") || &error ("Couldn't symlink $basedir/$path -> $basedir/$1: $!\n", 1); } else { &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1); } } if ($just_setup_tree) { die "Tree is setup...\n"; } } # compare a directory tree with an associative array in the format used # by create_dir_tree, above. # The first argument is the dir under which the structure should be found; # the second argument is the associative array. sub compare_dir_tree { local ($basedir, %dirtree) = @_; local ($path); local ($i); local ($bogus) = 0; local ($contents); local ($target); local ($fulltarget); local ($found); local (@files); local (@allfiles); opendir (DIR, $basedir) || &error ("Couldn't open $basedir: $!\n", 1); @allfiles = grep (!/^(\.\.?|CVS|RCS)$/, readdir (DIR) ); closedir (DIR); if ($debug) { print "dirtree: (%dirtree)\n$basedir: (@allfiles)\n"; } foreach $path (sort keys (%dirtree)) { if ($debug) { print "Checking $path ($dirtree{$path}).\n"; } $found = 0; foreach $i (0 .. $#allfiles) { if ($allfiles[$i] eq $path) { splice (@allfiles, $i, 1); # delete it if ($debug) { print " Zapped $path; files now (@allfiles).\n"; } lstat ("$basedir/$path"); $found = 1; last; } } if (!$found) { print "compare_dir_tree: $path does not exist.\n"; $bogus = 1; next; } if ($dirtree {$path} =~ /^DIR$/) { if (-d _ && opendir (DIR, "$basedir/$path") ) { @files = readdir (DIR); closedir (DIR); @files = grep (!/^(\.\.?|CVS|RCS)$/ && ($_ = "$path/$_"), @files); push (@allfiles, @files); if ($debug) { print " Read in $path; new files (@files).\n"; } } else { print "compare_dir_tree: $path is not a dir.\n"; $bogus = 1; } } elsif ($dirtree {$path} =~ /^FILE:(.*)$/) { if (-l _ || !-f _) { print "compare_dir_tree: $path is not a file.\n"; $bogus = 1; next; } if ($1 ne "*") { $contents = &read_file_into_string ("$basedir/$path"); if ($contents ne "$1\n") { print "compare_dir_tree: $path contains wrong stuff." . " Is:\n$contentsShould be:\n$1\n"; $bogus = 1; } } } elsif ($dirtree {$path} =~ /^LINK:(.*)$/) { $target = $1; if (!-l _) { print "compare_dir_tree: $path is not a link.\n"; $bogus = 1; next; } $contents = readlink ("$basedir/$path"); $contents =~ tr/>/\//; $fulltarget = "$basedir/$target"; $fulltarget =~ tr/>/\//; if (!($contents =~ /$fulltarget$/)) { if ($debug) { $target = $fulltarget; } print "compare_dir_tree: $path should be link to $target, " . "not $contents.\n"; $bogus = 1; } } else { &error ("Bogus dirtree type: \"$dirtree{$path}\"\n", 1); } } if ($debug) { print "leftovers: (@allfiles).\n"; } foreach $file (@allfiles) { print "compare_dir_tree: $file should not exist.\n"; $bogus = 1; } return !$bogus; } # this subroutine generates the numeric suffix used to keep tmp filenames, # log filenames, etc., unique. If the number passed in is 1, then a null # string is returned; otherwise, we return ".n", where n + 1 is the number # we were given. sub num_suffix { local($num) = @_; if (--$num > 0) { return "$extext$num"; } return ""; } # This subroutine returns a log filename with a number appended to # the end corresponding to how many logfiles have been created in the # current running test. An optional parameter may be passed (0 or 1). # If a 1 is passed, then it does NOT increment the logfile counter # and returns the name of the latest logfile. If either no parameter # is passed at all or a 0 is passed, then the logfile counter is # incremented and the new name is returned. sub get_logfile { local($no_increment) = @_; $num_of_logfiles += !$no_increment; return ($log_filename . &num_suffix ($num_of_logfiles)); } # This subroutine returns a base (answer) filename with a number # appended to the end corresponding to how many logfiles (and thus # base files) have been created in the current running test. # NO PARAMETERS ARE PASSED TO THIS SUBROUTINE. sub get_basefile { return ($base_filename . &num_suffix ($num_of_logfiles)); } # This subroutine returns a difference filename with a number appended # to the end corresponding to how many logfiles (and thus diff files) # have been created in the current running test. sub get_difffile { return ($diff_filename . &num_suffix ($num_of_logfiles)); } # This subroutine returns a command filename with a number appended # to the end corresponding to how many logfiles (and thus command files) # have been created in the current running test. sub get_runfile { return ($run_filename . &num_suffix ($num_of_logfiles)); } # just like logfile, only a generic tmp filename for use by the test. # they are automatically cleaned up unless -keep was used, or the test fails. # Pass an argument of 1 to return the same filename as the previous call. sub get_tmpfile { local($no_increment) = @_; $num_of_tmpfiles += !$no_increment; return ($tmp_filename . &num_suffix ($num_of_tmpfiles)); } 1; remake-4.1+dbg1.3~dfsg.1/trace.c000066400000000000000000000056311317072305000162420ustar00rootroot00000000000000/* $Id: trace.c,v 1.6 2005/12/20 15:11:24 rockyb Exp $ Copyright (C) 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2008, 2012 R. Bernstein This file is part of GNU Make. GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Header for routines related to tracing and debugging support */ /* AIX likes this: */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "trace.h" #include "print.h" #include "debug.h" #include "debugger/cmd.h" /** Pointer to top of current target call stack */ target_stack_node_t *p_stack_top; /** Pointer to top of current target floc stack */ floc_stack_node_t *p_stack_floc_top = NULL; /*! Push "target" to the call stack. */ extern target_stack_node_t * trace_push_target (target_stack_node_t *p, file_t *p_target) { target_stack_node_t *new_node = CALLOC(target_stack_node_t, 1); /* We allocate and make a copy of p_target in case we want to modify information, like the file location or target name on the fly as we process file commands or handle dependencies from target patterns. */ new_node->p_target = CALLOC (file_t, 1); memcpy(new_node->p_target, p_target, sizeof(file_t)); new_node->p_shared_target = p_target; new_node->p_parent = p; if (p_target && p_target->floc.filenm != NULL) { if ( db_level & DB_VERBOSE ) { print_file_target_prefix(p_target); printf("\n"); } } return new_node; }; /*! Pop the next target from the call stack.. */ extern void trace_pop_target (target_stack_node_t *p) { if (NULL == p) return; free(p->p_target); free(p); } /*! Push "p_floc" to the floc stack. Return the new stack top. */ extern void trace_push_floc (gmk_floc *p_floc) { floc_stack_node_t *new_node = CALLOC (floc_stack_node_t, 1); /* We DO NOT allocate and make a copy of p_floc so that as we read the Makefile, the line number gets updated automatically. Slick, huh? Also it shortens and simplifies code a bit. */ new_node->p_floc = p_floc; new_node->p_parent = p_stack_floc_top; p_stack_floc_top = new_node; }; /*! Pop the next target from the floc stack. */ extern void trace_pop_floc (void) { if (NULL == p_stack_floc_top) return; else { floc_stack_node_t *p_new_top = p_stack_floc_top->p_parent; free(p_stack_floc_top); p_stack_floc_top = p_new_top; } } remake-4.1+dbg1.3~dfsg.1/trace.h000066400000000000000000000074341317072305000162520ustar00rootroot00000000000000/* Copyright (C) 2004, 2005, 2007, 2008 Rocky Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file trace.h * * \brief Header for routines related to tracing and debugging support. */ #ifndef REMAKE_TRACE_H #define REMAKE_TRACE_H #include "types.h" #include "filedef.h" typedef enum { continue_execution, /**< Get out of debug read loop and continue execution as normal. */ next_execution, /**< Get out of debug read loop and continue execution as but don't enter debugger for the any remaining commands. */ skip_execution, /**< Get out of debug read loop, but skip execution of next command or action. */ debug_readloop, /**< Stay in debugger read loop - used only inside debugger read loop. */ debug_cmd_error /**< Command error but stay in debugger read loop - used only inside debugger read loop. */ } debug_return_t; typedef enum { DEBUG_BRKPT_BEFORE_PREREQ = 0, DEBUG_BRKPT_AFTER_PREREQ = 1, DEBUG_BRKPT_AFTER_CMD = 2, DEBUG_GOAL_UPDATED_HIT = 3, DEBUG_READ_HIT = 4, DEBUG_ERROR_HIT = 5, DEBUG_STEP_HIT = 6, DEBUG_STEP_COMMAND = 7, DEBUG_EXPLICIT_CALL = 8, DEBUG_STACK_CHANGING = 99, DEBUG_NOT_GIVEN = 100 } debug_enter_reason_t; typedef enum { INFO_TARGET_POSITION = 1, INFO_TARGET_NAME = 2, INFO_TARGET_POSITION_AND_NAME = 3, /* 1 & 2 */ INFO_TARGET_TASKS = 4, INFO_TARGET_TASK_COMMENT = 8, INFO_TARGET_TASKS_WITH_COMMENTS = 12, /* 4 & 8 */ } info_target_output_mask_t; /*! debugger command interface. */ /*! A call "stack". Well, since we'll have to deal with multiple child "jobs" it's not really a stack but a tree. */ /*! \brief Node for an item in the target call stack */ typedef struct target_stack_node { file_t *p_target; file_t *p_shared_target; struct target_stack_node *p_parent; } target_stack_node_t; /** Pointer to top of current target call stack */ extern target_stack_node_t *p_stack_top; /*! Push "p_target" to the call stack. Return the new stack top. if b_debugger is true we might enter the debugger. */ extern target_stack_node_t *trace_push_target (target_stack_node_t *p, file_t *p_target); /*! Pop the next target from the call stack.. */ extern void trace_pop_target (target_stack_node_t *p); /*! \brief Node for an item in the "include Makefile" stack */ typedef struct floc_stack_node { gmk_floc *p_floc; struct floc_stack_node *p_parent; } floc_stack_node_t; /** Pointer to top of current target floc stack */ extern floc_stack_node_t *p_stack_floc_top; /*! Push "p_floc" to the floc stack. Return the new stack top. */ extern void trace_push_floc (gmk_floc *p_floc); /*! Pop the next floc from the call stack.. */ extern void trace_pop_floc (void); /*! Show just a list of targets */ extern void dbg_cmd_info_targets(info_target_output_mask_t output_mask); #endif /*REMAKE_TRACE_H*/ remake-4.1+dbg1.3~dfsg.1/types.h000066400000000000000000000051711317072305000163140ustar00rootroot00000000000000/* Miscellaneous types Copyright (c) 2005, 2008, 2011 Rocky Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file types.h * * \brief Miscellaneous types */ #ifndef REMAKE_TYPES_H #define REMAKE_TYPES_H #include "config.h" #include "make.h" #define UNUSED_ARGUMENT(x) (void)x #if defined(HAVE_STDINT_H) # include #elif defined(HAVE_INTTYPES_H) # include #endif /* HAVE_STDINT_H */ #if defined(HAVE_STDBOOL_H) # include #else /* ISO/IEC 9899:1999 missing -- enabling workaround */ # define false 0 # define true 1 # define bool uint8_t #endif /*HAVE_STDBOOL_H*/ /** Debugger breakpoint type */ typedef enum { BRK_NONE = 0x00, /**< Mask when none of the below are set. */ BRK_BEFORE_PREREQ = 0x01, /**< Stop after prequisites checking done */ BRK_AFTER_PREREQ = 0x02, /**< Stop after prequisites checking done */ BRK_AFTER_CMD = 0x04, /**< Stop after running commands */ BRK_ALL = (BRK_BEFORE_PREREQ|BRK_AFTER_PREREQ|BRK_AFTER_CMD), BRK_TEMP = 0x08, /**< Temporary or one-time breakpoint */ } breakpoint_mask_t; typedef unsigned int brkpt_mask_t; typedef unsigned long int lineno_t; typedef struct child child_t; typedef struct commands commands_t; typedef struct dep dep_t; typedef struct file file_t; typedef struct nameseq nameseq_t; typedef struct pattern_var pattern_var_t; typedef struct pspec pspec_t; typedef struct rule rule_t; typedef struct stringlist stringlist_t; typedef struct variable variable_t; typedef enum variable_origin variable_origin_t; typedef struct variable_set variable_set_t; typedef struct variable_set_list variable_set_list_t; #define CALLOC(t, n) ((t *) calloc (sizeof (t), (n))) #endif /*REMAKE_TYPES_H*/ /* * Local variables: * eval: (c-set-style "gnu") * indent-tabs-mode: nil * End: */ remake-4.1+dbg1.3~dfsg.1/unittest/000077500000000000000000000000001317072305000166525ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/unittest/.gitignore000066400000000000000000000001231317072305000206360ustar00rootroot00000000000000/*.Po /Makefile /Makefile.in /test-suite.log /test_*.log /test_*.trs /test_profile remake-4.1+dbg1.3~dfsg.1/unittest/Makefile.am000066400000000000000000000005421317072305000207070ustar00rootroot00000000000000AM_CPPFLAGS = -I$(abs_top_srcdir) test_profile_SOURCES = test_profile.c test_profile_LDADD = \ ../mock.o \ ../version.o \ ../alloc.o \ ../globals.o \ ../misc.o \ ../output.o \ ../file_basic.o \ ../hash.o \ ../profile.o \ ../strcache.o \ @LIBINTL@ check_PROGRAMS = test_profile TESTS = $(check_PROGRAMS) MOSTLYCLEANFILES = callgrind.out.* remake-4.1+dbg1.3~dfsg.1/unittest/test_profile.c000066400000000000000000000031101317072305000215100ustar00rootroot00000000000000/* Copyright (C) 2015, 2017 R. Bernstein This file is part of GNU Make (remake variant). GNU Make is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 Make; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../config.h" #include "../types.h" #include "../file_basic.h" #include "../profile.h" int main(int argc, const char * const* argv) { bool rc = init_callgrind(PACKAGE_TARNAME " " PACKAGE_VERSION, argv); init_hash_files(); if (rc) { file_t *target = enter_file("Makefile"); file_t *target2, *target3; target->floc.filenm = "Makefile"; target2 = enter_file("all"); target2->floc.filenm = "Makefile"; target2->floc.lineno = 5; target2->elapsed_time = 500; add_target(target2, NULL); target3 = enter_file("all-recursive"); target3->floc.filenm = "Makefile"; target3->floc.lineno = 5; target3->elapsed_time = 1000; add_target(target3, target2); close_callgrind("Program termination"); } if (rc == true) { return 0; } else { return 1; } } remake-4.1+dbg1.3~dfsg.1/variable.c000066400000000000000000001570221317072305000167330ustar00rootroot00000000000000/* Internals of variables for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include "filedef.h" #include "dep.h" #include "job.h" #include "commands.h" #include "variable.h" #include "rule.h" #ifdef WINDOWS32 #include "pathstuff.h" #endif #include "hash.h" /* Chain of all pattern-specific variables. */ static struct pattern_var *pattern_vars; /* Pointer to the last struct in the pack of a specific size, from 1 to 255.*/ static struct pattern_var *last_pattern_vars[256]; /*! Return a string describing origin. */ const char * origin2str(variable_origin_t origin) { switch (origin) { case o_default: return _("default"); break; case o_env: return _("environment"); break; case o_file: return _("makefile"); break; case o_env_override: return _("environment under -e"); break; case o_command: return _("command line"); break; case o_override: return _("`override' directive"); break; case o_automatic: return _("automatic"); break; case o_debugger: return _("debugger"); break; case o_invalid: default: return _("invalid"); } } /* Create a new pattern-specific variable struct. The new variable is inserted into the PATTERN_VARS list in the shortest patterns first order to support the shortest stem matching (the variables are matched in the reverse order so the ones with the longest pattern will be considered first). Variables with the same pattern length are inserted in the definition order. */ struct pattern_var * create_pattern_var (const char *target, const char *suffix) { register unsigned int len = strlen (target); register struct pattern_var *p = xmalloc (sizeof (struct pattern_var)); if (pattern_vars != 0) { if (len < 256 && last_pattern_vars[len] != 0) { p->next = last_pattern_vars[len]->next; last_pattern_vars[len]->next = p; } else { /* Find the position where we can insert this variable. */ register struct pattern_var **v; for (v = &pattern_vars; ; v = &(*v)->next) { /* Insert at the end of the pack so that patterns with the same length appear in the order they were defined .*/ if (*v == 0 || (*v)->len > len) { p->next = *v; *v = p; break; } } } } else { pattern_vars = p; p->next = 0; } p->target = target; p->len = len; p->suffix = suffix + 1; if (len < 256) last_pattern_vars[len] = p; return p; } /* Look up a target in the pattern-specific variable list. */ static struct pattern_var * lookup_pattern_var (struct pattern_var *start, const char *target) { struct pattern_var *p; unsigned int targlen = strlen (target); for (p = start ? start->next : pattern_vars; p != 0; p = p->next) { const char *stem; unsigned int stemlen; if (p->len > targlen) /* It can't possibly match. */ continue; /* From the lengths of the filename and the pattern parts, find the stem: the part of the filename that matches the %. */ stem = target + (p->suffix - p->target - 1); stemlen = targlen - p->len + 1; /* Compare the text in the pattern before the stem, if any. */ if (stem > target && !strneq (p->target, target, stem - target)) continue; /* Compare the text in the pattern after the stem, if any. We could test simply using streq, but this way we compare the first two characters immediately. This saves time in the very common case where the first character matches because it is a period. */ if (*p->suffix == stem[stemlen] && (*p->suffix == '\0' || streq (&p->suffix[1], &stem[stemlen+1]))) break; } return p; } /* Hash table of all global variable definitions. */ static unsigned long variable_hash_1 (const void *keyv) { struct variable const *key = (struct variable const *) keyv; return_STRING_N_HASH_1 (key->name, key->length); } static unsigned long variable_hash_2 (const void *keyv) { struct variable const *key = (struct variable const *) keyv; return_STRING_N_HASH_2 (key->name, key->length); } static int variable_hash_cmp (const void *xv, const void *yv) { struct variable const *x = (struct variable const *) xv; struct variable const *y = (struct variable const *) yv; int result = x->length - y->length; if (result) return result; return_STRING_N_COMPARE (x->name, y->name, x->length); } #ifndef VARIABLE_BUCKETS #define VARIABLE_BUCKETS 523 #endif #ifndef PERFILE_VARIABLE_BUCKETS #define PERFILE_VARIABLE_BUCKETS 23 #endif #ifndef SMALL_SCOPE_VARIABLE_BUCKETS #define SMALL_SCOPE_VARIABLE_BUCKETS 13 #endif static struct variable_set global_variable_set; static struct variable_set_list global_setlist = { 0, &global_variable_set, 0 }; struct variable_set_list *current_variable_set_list = &global_setlist; /* Implement variables. */ void init_hash_global_variable_set (void) { hash_init (&global_variable_set.table, VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); } /* Define variable named NAME with value VALUE in SET. VALUE is copied. LENGTH is the length of NAME, which does not need to be null-terminated. ORIGIN specifies the origin of the variable (makefile, command line or environment). If RECURSIVE is nonzero a flag is set in the variable saying that it should be recursively re-expanded. */ struct variable * define_variable_in_set (const char *name, unsigned int length, const char *value, enum variable_origin origin, int recursive, struct variable_set *set, const gmk_floc *flocp) { struct variable *v; struct variable **var_slot; struct variable var_key; if (set == NULL) set = &global_variable_set; var_key.name = (char *) name; var_key.length = length; var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); if (env_overrides && origin == o_env) origin = o_env_override; v = *var_slot; if (! HASH_VACANT (v)) { if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; /* A variable of this name is already defined. If the old definition is from a stronger source than this one, don't redefine it. */ if ((int) origin >= (int) v->origin) { free (v->value); v->value = xstrdup (value); if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; } return v; } /* Create a new variable definition and add it to the hash table. */ v = xmalloc (sizeof (struct variable)); v->name = xstrndup (name, length); v->length = length; hash_insert_at (&set->table, v, var_slot); v->value = xstrdup (value); if (flocp != 0) v->fileinfo = *flocp; else v->fileinfo.filenm = 0; v->origin = origin; v->recursive = recursive; v->special = 0; v->expanding = 0; v->exp_count = 0; v->per_target = 0; v->append = 0; v->private_var = 0; v->export = v_default; v->exportable = 1; if (*name != '_' && (*name < 'A' || *name > 'Z') && (*name < 'a' || *name > 'z')) v->exportable = 0; else { for (++name; *name != '\0'; ++name) if (*name != '_' && (*name < 'a' || *name > 'z') && (*name < 'A' || *name > 'Z') && !ISDIGIT(*name)) break; if (*name != '\0') v->exportable = 0; } return v; } /* Undefine variable named NAME in SET. LENGTH is the length of NAME, which does not need to be null-terminated. ORIGIN specifies the origin of the variable (makefile, command line or environment). */ static void free_variable_name_and_value (const void *item) { struct variable *v = (struct variable *) item; free (v->name); free (v->value); } void free_variable_set (struct variable_set_list *list) { hash_map (&list->set->table, free_variable_name_and_value); hash_free (&list->set->table, 1); free (list->set); free (list); } void undefine_variable_in_set (const char *name, unsigned int length, enum variable_origin origin, struct variable_set *set) { struct variable *v; struct variable **var_slot; struct variable var_key; if (set == NULL) set = &global_variable_set; var_key.name = (char *) name; var_key.length = length; var_slot = (struct variable **) hash_find_slot (&set->table, &var_key); if (env_overrides && origin == o_env) origin = o_env_override; v = *var_slot; if (! HASH_VACANT (v)) { if (env_overrides && v->origin == o_env) /* V came from in the environment. Since it was defined before the switches were parsed, it wasn't affected by -e. */ v->origin = o_env_override; /* If the definition is from a stronger source than this one, don't undefine it. */ if ((int) origin >= (int) v->origin) { hash_delete_at (&set->table, var_slot); free_variable_name_and_value (v); } } } /* If the variable passed in is "special", handle its special nature. Currently there are two such variables, both used for introspection: .VARIABLES expands to a list of all the variables defined in this instance of make. .TARGETS expands to a list of all the targets defined in this instance of make. Returns the variable reference passed in. */ #define EXPANSION_INCREMENT(_l) ((((_l) / 500) + 1) * 500) static struct variable * lookup_special_var (struct variable *var) { static unsigned long last_var_count = 0; /* This one actually turns out to be very hard, due to the way the parser records targets. The way it works is that target information is collected internally until make knows the target is completely specified. It unitl it sees that some new construct (a new target or variable) is defined that it knows the previous one is done. In short, this means that if you do this: all: TARGS := $(.TARGETS) then $(TARGS) won't contain "all", because it's not until after the variable is created that the previous target is completed. Changing this would be a major pain. I think a less complex way to do it would be to pre-define the target files as soon as the first line is parsed, then come back and do the rest of the definition as now. That would allow $(.TARGETS) to be correct without a major change to the way the parser works. if (streq (var->name, ".TARGETS")) var->value = build_target_list (var->value); else */ if (streq (var->name, ".VARIABLES") && global_variable_set.table.ht_fill != last_var_count) { unsigned long max = EXPANSION_INCREMENT (strlen (var->value)); unsigned long len; char *p; struct variable **vp = (struct variable **) global_variable_set.table.ht_vec; struct variable **end = &vp[global_variable_set.table.ht_size]; /* Make sure we have at least MAX bytes in the allocated buffer. */ var->value = xrealloc (var->value, max); /* Walk through the hash of variables, constructing a list of names. */ p = var->value; len = 0; for (; vp < end; ++vp) if (!HASH_VACANT (*vp)) { struct variable *v = *vp; int l = v->length; len += l + 1; if (len > max) { unsigned long off = p - var->value; max += EXPANSION_INCREMENT (l + 1); var->value = xrealloc (var->value, max); p = &var->value[off]; } memcpy (p, v->name, l); p += l; *(p++) = ' '; } *(p-1) = '\0'; /* Remember how many variables are in our current count. Since we never remove variables from the list, this is a reliable way to know whether the list is up to date or needs to be recomputed. */ last_var_count = global_variable_set.table.ht_fill; } return var; } /* Lookup a variable whose name is a string starting at NAME and with LENGTH chars. NAME need not be null-terminated. Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * lookup_variable (const char *name, unsigned int length) { const struct variable_set_list *setlist; struct variable var_key; int is_parent = 0; var_key.name = (char *) name; var_key.length = length; for (setlist = current_variable_set_list; setlist != 0; setlist = setlist->next) { const struct variable_set *set = setlist->set; struct variable *v; v = (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); if (v && (!is_parent || !v->private_var)) return v->special ? lookup_special_var (v) : v; is_parent |= setlist->next_is_parent; } #ifdef VMS /* since we don't read envp[] on startup, try to get the variable via getenv() here. */ { char *vname = alloca (length + 1); char *value; strncpy (vname, name, length); vname[length] = 0; value = getenv (vname); if (value != 0) { char *sptr; int scnt; sptr = value; scnt = 0; while ((sptr = strchr (sptr, '$'))) { scnt++; sptr++; } if (scnt > 0) { char *nvalue; char *nptr; nvalue = alloca (strlen (value) + scnt + 1); sptr = value; nptr = nvalue; while (*sptr) { if (*sptr == '$') { *nptr++ = '$'; *nptr++ = '$'; } else { *nptr++ = *sptr; } sptr++; } *nptr = '\0'; return define_variable (vname, length, nvalue, o_env, 1); } return define_variable (vname, length, value, o_env, 1); } } #endif /* VMS */ return 0; } /* Lookup a variable whose name is a string starting at NAME and with LENGTH chars in set SET. NAME need not be null-terminated. Returns address of the 'struct variable' containing all info on the variable, or nil if no such variable is defined. */ struct variable * lookup_variable_in_set (const char *name, unsigned int length, const struct variable_set *set) { struct variable var_key; var_key.name = (char *) name; var_key.length = length; return (struct variable *) hash_find_item ((struct hash_table *) &set->table, &var_key); } /* Initialize FILE's variable set list. If FILE already has a variable set list, the topmost variable set is left intact, but the the rest of the chain is replaced with FILE->parent's setlist. If FILE is a double-colon rule, then we will use the "root" double-colon target's variable set as the parent of FILE's variable set. If we're READING a makefile, don't do the pattern variable search now, since the pattern variable might not have been defined yet. */ void initialize_file_variables (struct file *file, int reading) { struct variable_set_list *l = file->variables; if (l == 0) { l = (struct variable_set_list *) xmalloc (sizeof (struct variable_set_list)); l->set = xmalloc (sizeof (struct variable_set)); hash_init (&l->set->table, PERFILE_VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); file->variables = l; } /* If this is a double-colon, then our "parent" is the "root" target for this double-colon rule. Since that rule has the same name, parent, etc. we can just use its variables as the "next" for ours. */ if (file->double_colon && file->double_colon != file) { initialize_file_variables (file->double_colon, reading); l->next = file->double_colon->variables; l->next_is_parent = 0; return; } if (file->parent == 0) l->next = &global_setlist; else { initialize_file_variables (file->parent, reading); l->next = file->parent->variables; } l->next_is_parent = 1; /* If we're not reading makefiles and we haven't looked yet, see if we can find pattern variables for this target. */ if (!reading && !file->pat_searched) { struct pattern_var *p; p = lookup_pattern_var (0, file->name); if (p != 0) { struct variable_set_list *global = current_variable_set_list; /* We found at least one. Set up a new variable set to accumulate all the pattern variables that match this target. */ file->pat_variables = create_new_variable_set (); current_variable_set_list = file->pat_variables; do { /* We found one, so insert it into the set. */ struct variable *v; if (p->variable.flavor == f_simple) { v = define_variable_loc ( p->variable.name, strlen (p->variable.name), p->variable.value, p->variable.origin, 0, &p->variable.fileinfo); v->flavor = f_simple; } else { v = do_variable_definition ( &p->variable.fileinfo, p->variable.name, p->variable.value, p->variable.origin, p->variable.flavor, 1); } /* Also mark it as a per-target and copy export status. */ v->per_target = p->variable.per_target; v->export = p->variable.export; v->private_var = p->variable.private_var; } while ((p = lookup_pattern_var (p, file->name)) != 0); current_variable_set_list = global; } file->pat_searched = 1; } /* If we have a pattern variable match, set it up. */ if (file->pat_variables != 0) { file->pat_variables->next = l->next; file->pat_variables->next_is_parent = l->next_is_parent; l->next = file->pat_variables; l->next_is_parent = 0; } } /* Pop the top set off the current variable set list, and free all its storage. */ struct variable_set_list * create_new_variable_set (void) { register struct variable_set_list *setlist; register struct variable_set *set; set = xmalloc (sizeof (struct variable_set)); hash_init (&set->table, SMALL_SCOPE_VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); setlist = (struct variable_set_list *) xmalloc (sizeof (struct variable_set_list)); setlist->set = set; setlist->next = current_variable_set_list; setlist->next_is_parent = 0; return setlist; } /* Create a new variable set and push it on the current setlist. If we're pushing a global scope (that is, the current scope is the global scope) then we need to "push" it the other way: file variable sets point directly to the global_setlist so we need to replace that with the new one. */ struct variable_set_list * push_new_variable_scope (void) { current_variable_set_list = create_new_variable_set (); if (current_variable_set_list->next == &global_setlist) { /* It was the global, so instead of new -> &global we want to replace &global with the new one and have &global -> new, with current still pointing to &global */ struct variable_set *set = current_variable_set_list->set; current_variable_set_list->set = global_setlist.set; global_setlist.set = set; current_variable_set_list->next = global_setlist.next; global_setlist.next = current_variable_set_list; current_variable_set_list = &global_setlist; } return (current_variable_set_list); } void pop_variable_scope (void) { struct variable_set_list *setlist; struct variable_set *set; /* Can't call this if there's no scope to pop! */ assert (current_variable_set_list->next != NULL); if (current_variable_set_list != &global_setlist) { /* We're not pointing to the global setlist, so pop this one. */ setlist = current_variable_set_list; set = setlist->set; current_variable_set_list = setlist->next; } else { /* This set is the one in the global_setlist, but there is another global set beyond that. We want to copy that set to global_setlist, then delete what used to be in global_setlist. */ setlist = global_setlist.next; set = global_setlist.set; global_setlist.set = setlist->set; global_setlist.next = setlist->next; global_setlist.next_is_parent = setlist->next_is_parent; } /* Free the one we no longer need. */ free (setlist); hash_map (&set->table, free_variable_name_and_value); hash_free (&set->table, 1); free (set); } /* Merge FROM_SET into TO_SET, freeing unused storage in FROM_SET. */ static void merge_variable_sets (struct variable_set *to_set, struct variable_set *from_set) { struct variable **from_var_slot = (struct variable **) from_set->table.ht_vec; struct variable **from_var_end = from_var_slot + from_set->table.ht_size; for ( ; from_var_slot < from_var_end; from_var_slot++) if (! HASH_VACANT (*from_var_slot)) { struct variable *from_var = *from_var_slot; struct variable **to_var_slot = (struct variable **) hash_find_slot (&to_set->table, *from_var_slot); if (HASH_VACANT (*to_var_slot)) hash_insert_at (&to_set->table, from_var, to_var_slot); else { /* GKM FIXME: delete in from_set->table */ free (from_var->value); free (from_var); } } } /* Merge SETLIST1 into SETLIST0, freeing unused storage in SETLIST1. */ void merge_variable_set_lists (struct variable_set_list **setlist0, struct variable_set_list *setlist1) { struct variable_set_list *to = *setlist0; struct variable_set_list *last0 = 0; /* If there's nothing to merge, stop now. */ if (!setlist1) return; /* This loop relies on the fact that all setlists terminate with the global setlist (before NULL). If that's not true, arguably we SHOULD die. */ if (to) while (setlist1 != &global_setlist && to != &global_setlist) { struct variable_set_list *from = setlist1; setlist1 = setlist1->next; merge_variable_sets (to->set, from->set); last0 = to; to = to->next; } if (setlist1 != &global_setlist) { if (last0 == 0) *setlist0 = setlist1; else last0->next = setlist1; } } /* Define the automatic variables, and record the addresses of their structures so we can change their values quickly. */ void define_automatic_variables (void) { extern const char* default_shell; struct variable *v; char buf[200]; sprintf (buf, "%u", makelevel); define_variable_cname (MAKELEVEL_NAME, buf, o_env, 0); sprintf (buf, "%s%s%s", version_string, (remote_description == 0 || remote_description[0] == '\0') ? "" : "-", (remote_description == 0 || remote_description[0] == '\0') ? "" : remote_description); define_variable_cname ("MAKE_VERSION", buf, o_default, 0); define_variable_cname ("MAKE_HOST", make_host, o_default, 0); #ifdef __MSDOS__ /* Allow to specify a special shell just for Make, and use $COMSPEC as the default $SHELL when appropriate. */ { static char shell_str[] = "SHELL"; const int shlen = sizeof (shell_str) - 1; struct variable *mshp = lookup_variable ("MAKESHELL", 9); struct variable *comp = lookup_variable ("COMSPEC", 7); /* $(MAKESHELL) overrides $(SHELL) even if -e is in effect. */ if (mshp) (void) define_variable (shell_str, shlen, mshp->value, o_env_override, 0); else if (comp) { /* $(COMSPEC) shouldn't override $(SHELL). */ struct variable *shp = lookup_variable (shell_str, shlen); if (!shp) (void) define_variable (shell_str, shlen, comp->value, o_env, 0); } } #elif defined(__EMX__) { static char shell_str[] = "SHELL"; const int shlen = sizeof (shell_str) - 1; struct variable *shell = lookup_variable (shell_str, shlen); struct variable *replace = lookup_variable ("MAKESHELL", 9); /* if $MAKESHELL is defined in the environment assume o_env_override */ if (replace && *replace->value && replace->origin == o_env) replace->origin = o_env_override; /* if $MAKESHELL is not defined use $SHELL but only if the variable did not come from the environment */ if (!replace || !*replace->value) if (shell && *shell->value && (shell->origin == o_env || shell->origin == o_env_override)) { /* overwrite whatever we got from the environment */ free (shell->value); shell->value = xstrdup (default_shell); shell->origin = o_default; } /* Some people do not like cmd to be used as the default if $SHELL is not defined in the Makefile. With -DNO_CMD_DEFAULT you can turn off this behaviour */ # ifndef NO_CMD_DEFAULT /* otherwise use $COMSPEC */ if (!replace || !*replace->value) replace = lookup_variable ("COMSPEC", 7); /* otherwise use $OS2_SHELL */ if (!replace || !*replace->value) replace = lookup_variable ("OS2_SHELL", 9); # else # warning NO_CMD_DEFAULT: GNU make will not use CMD.EXE as default shell # endif if (replace && *replace->value) /* overwrite $SHELL */ (void) define_variable (shell_str, shlen, replace->value, replace->origin, 0); else /* provide a definition if there is none */ (void) define_variable (shell_str, shlen, default_shell, o_default, 0); } #endif /* This won't override any definition, but it will provide one if there isn't one there. */ v = define_variable_cname ("SHELL", default_shell, o_default, 0); #ifdef __MSDOS__ v->export = v_export; /* Export always SHELL. */ #endif /* On MSDOS we do use SHELL from environment, since it isn't a standard environment variable on MSDOS, so whoever sets it, does that on purpose. On OS/2 we do not use SHELL from environment but we have already handled that problem above. */ #if !defined(__MSDOS__) && !defined(__EMX__) /* Don't let SHELL come from the environment. */ if (*v->value == '\0' || v->origin == o_env || v->origin == o_env_override) { free (v->value); v->origin = o_file; v->value = xstrdup (default_shell); } #endif /* Make sure MAKEFILES gets exported if it is set. */ v = define_variable_cname ("MAKEFILES", "", o_default, 0); v->export = v_ifset; /* Define the magic D and F variables in terms of the automatic variables they are variations of. */ #ifdef VMS define_variable_cname ("@D", "$(dir $@)", o_automatic, 1); define_variable_cname ("%D", "$(dir $%)", o_automatic, 1); define_variable_cname ("*D", "$(dir $*)", o_automatic, 1); define_variable_cname ("variables; hash_init (&table, VARIABLE_BUCKETS, variable_hash_1, variable_hash_2, variable_hash_cmp); /* Run through all the variable sets in the list, accumulating variables in TABLE. */ for (s = set_list; s != 0; s = s->next) { struct variable_set *set = s->set; v_slot = (struct variable **) set->table.ht_vec; v_end = v_slot + set->table.ht_size; for ( ; v_slot < v_end; v_slot++) if (! HASH_VACANT (*v_slot)) { struct variable **new_slot; struct variable *v = *v_slot; /* If this is a per-target variable and it hasn't been touched already then look up the global version and take its export value. */ if (v->per_target && v->export == v_default) { struct variable *gv; gv = lookup_variable_in_set (v->name, strlen (v->name), &global_variable_set); if (gv) v->export = gv->export; } switch (v->export) { case v_default: if (v->origin == o_default || v->origin == o_automatic) /* Only export default variables by explicit request. */ continue; /* The variable doesn't have a name that can be exported. */ if (! v->exportable) continue; if (! export_all_variables && v->origin != o_command && v->origin != o_env && v->origin != o_env_override) continue; break; case v_export: break; case v_noexport: { /* If this is the SHELL variable and it's not exported, then add the value from our original environment, if the original environment defined a value for SHELL. */ extern struct variable shell_var; if (streq (v->name, "SHELL") && shell_var.value) { v = &shell_var; break; } continue; } case v_ifset: if (v->origin == o_default) continue; break; } new_slot = (struct variable **) hash_find_slot (&table, v); if (HASH_VACANT (*new_slot)) hash_insert_at (&table, v, new_slot); } } makelevel_key.name = xstrdup (MAKELEVEL_NAME); makelevel_key.length = MAKELEVEL_LENGTH; hash_delete (&table, &makelevel_key); result = result_0 = xmalloc ((table.ht_fill + 2) * sizeof (char *)); v_slot = (struct variable **) table.ht_vec; v_end = v_slot + table.ht_size; for ( ; v_slot < v_end; v_slot++) if (! HASH_VACANT (*v_slot)) { struct variable *v = *v_slot; /* If V is recursively expanded and didn't come from the environment, expand its value. If it came from the environment, it should go back into the environment unchanged. */ if (v->recursive && v->origin != o_env && v->origin != o_env_override) { char *value = recursively_expand_for_file (v, file); #ifdef WINDOWS32 if (strcmp (v->name, "Path") == 0 || strcmp (v->name, "PATH") == 0) convert_Path_to_windows32 (value, ';'); #endif *result++ = xstrdup (concat (3, v->name, "=", value)); free (value); } else { #ifdef WINDOWS32 if (strcmp (v->name, "Path") == 0 || strcmp (v->name, "PATH") == 0) convert_Path_to_windows32 (v->value, ';'); #endif *result++ = xstrdup (concat (3, v->name, "=", v->value)); } } *result = xmalloc (100); sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1); *++result = 0; hash_free (&table, 0); return result_0; } static struct variable * set_special_var (struct variable *var) { if (streq (var->name, RECIPEPREFIX_NAME)) { /* The user is resetting the command introduction prefix. This has to happen immediately, so that subsequent rules are interpreted properly. */ cmd_prefix = var->value[0]=='\0' ? RECIPEPREFIX_DEFAULT : var->value[0]; } return var; } /* Given a string, shell-execute it and return a malloc'ed string of the * result. This removes only ONE newline (if any) at the end, for maximum * compatibility with the *BSD makes. If it fails, returns NULL. */ char * shell_result (const char *p) { char *buf; unsigned int len; char *args[2]; char *result; install_variable_buffer (&buf, &len); args[0] = (char *) p; args[1] = NULL; variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1); result = strdup (variable_buffer); restore_variable_buffer (buf, len); return result; } /* Given a variable, a value, and a flavor, define the variable. See the try_variable_definition() function for details on the parameters. */ struct variable * do_variable_definition (const gmk_floc *flocp, const char *varname, const char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var) { const char *p; char *alloc_value = NULL; struct variable *v; int append = 0; int conditional = 0; /* Calculate the variable's new value in VALUE. */ switch (flavor) { default: case f_bogus: /* Should not be possible. */ abort (); case f_simple: /* A simple variable definition "var := value". Expand the value. We have to allocate memory since otherwise it'll clobber the variable buffer, and we may still need that if we're looking at a target-specific variable. */ p = alloc_value = allocated_variable_expand (value); break; case f_shell: { /* A shell definition "var != value". Expand value, pass it to the shell, and store the result in recursively-expanded var. */ char *q = allocated_variable_expand (value); p = alloc_value = shell_result (q); free (q); flavor = f_recursive; break; } case f_conditional: /* A conditional variable definition "var ?= value". The value is set IFF the variable is not defined yet. */ v = lookup_variable (varname, strlen (varname)); if (v) return v->special ? set_special_var (v) : v; conditional = 1; flavor = f_recursive; /* FALLTHROUGH */ case f_recursive: /* A recursive variable definition "var = value". The value is used verbatim. */ p = value; break; case f_append: { /* If we have += but we're in a target variable context, we want to append only with other variables in the context of this target. */ if (target_var) { append = 1; v = lookup_variable_in_set (varname, strlen (varname), current_variable_set_list->set); /* Don't append from the global set if a previous non-appending target-specific variable definition exists. */ if (v && !v->append) append = 0; } else v = lookup_variable (varname, strlen (varname)); if (v == 0) { /* There was no old value. This becomes a normal recursive definition. */ p = value; flavor = f_recursive; } else { /* Paste the old and new values together in VALUE. */ unsigned int oldlen, vallen; const char *val; char *tp = NULL; val = value; if (v->recursive) /* The previous definition of the variable was recursive. The new value is the unexpanded old and new values. */ flavor = f_recursive; else /* The previous definition of the variable was simple. The new value comes from the old value, which was expanded when it was set; and from the expanded new value. Allocate memory for the expansion as we may still need the rest of the buffer if we're looking at a target-specific variable. */ val = tp = allocated_variable_expand (val); oldlen = strlen (v->value); vallen = strlen (val); p = alloc_value = xmalloc (oldlen + 1 + vallen + 1); memcpy (alloc_value, v->value, oldlen); alloc_value[oldlen] = ' '; memcpy (&alloc_value[oldlen + 1], val, vallen + 1); free (tp); } } } #ifdef __MSDOS__ /* Many Unix Makefiles include a line saying "SHELL=/bin/sh", but non-Unix systems don't conform to this default configuration (in fact, most of them don't even have '/bin'). On the other hand, $SHELL in the environment, if set, points to the real pathname of the shell. Therefore, we generally won't let lines like "SHELL=/bin/sh" from the Makefile override $SHELL from the environment. But first, we look for the basename of the shell in the directory where SHELL= points, and along the $PATH; if it is found in any of these places, we define $SHELL to be the actual pathname of the shell. Thus, if you have bash.exe installed as d:/unix/bash.exe, and d:/unix is on your $PATH, then SHELL=/usr/local/bin/bash will have the effect of defining SHELL to be "d:/unix/bash.exe". */ if ((origin == o_file || origin == o_override) && strcmp (varname, "SHELL") == 0) { PATH_VAR (shellpath); extern char * __dosexec_find_on_path (const char *, char *[], char *); /* See if we can find "/bin/sh.exe", "/bin/sh.com", etc. */ if (__dosexec_find_on_path (p, NULL, shellpath)) { char *tp; for (tp = shellpath; *tp; tp++) if (*tp == '\\') *tp = '/'; v = define_variable_loc (varname, strlen (varname), shellpath, origin, flavor == f_recursive, flocp); } else { const char *shellbase, *bslash; struct variable *pathv = lookup_variable ("PATH", 4); char *path_string; char *fake_env[2]; size_t pathlen = 0; shellbase = strrchr (p, '/'); bslash = strrchr (p, '\\'); if (!shellbase || bslash > shellbase) shellbase = bslash; if (!shellbase && p[1] == ':') shellbase = p + 1; if (shellbase) shellbase++; else shellbase = p; /* Search for the basename of the shell (with standard executable extensions) along the $PATH. */ if (pathv) pathlen = strlen (pathv->value); path_string = xmalloc (5 + pathlen + 2 + 1); /* On MSDOS, current directory is considered as part of $PATH. */ sprintf (path_string, "PATH=.;%s", pathv ? pathv->value : ""); fake_env[0] = path_string; fake_env[1] = 0; if (__dosexec_find_on_path (shellbase, fake_env, shellpath)) { char *tp; for (tp = shellpath; *tp; tp++) if (*tp == '\\') *tp = '/'; v = define_variable_loc (varname, strlen (varname), shellpath, origin, flavor == f_recursive, flocp); } else v = lookup_variable (varname, strlen (varname)); free (path_string); } } else #endif /* __MSDOS__ */ #ifdef WINDOWS32 if ((origin == o_file || origin == o_override || origin == o_command) && streq (varname, "SHELL")) { extern const char *default_shell; /* Call shell locator function. If it returns TRUE, then set no_default_sh_exe to indicate sh was found and set new value for SHELL variable. */ if (find_and_set_default_shell (p)) { v = define_variable_in_set (varname, strlen (varname), default_shell, origin, flavor == f_recursive, (target_var ? current_variable_set_list->set : NULL), flocp); no_default_sh_exe = 0; } else { char *tp = alloc_value; alloc_value = allocated_variable_expand (p); if (find_and_set_default_shell (alloc_value)) { v = define_variable_in_set (varname, strlen (varname), p, origin, flavor == f_recursive, (target_var ? current_variable_set_list->set : NULL), flocp); no_default_sh_exe = 0; } else v = lookup_variable (varname, strlen (varname)); free (tp); } } else #endif /* If we are defining variables inside an $(eval ...), we might have a different variable context pushed, not the global context (maybe we're inside a $(call ...) or something. Since this function is only ever invoked in places where we want to define globally visible variables, make sure we define this variable in the global set. */ v = define_variable_in_set (varname, strlen (varname), p, origin, flavor == f_recursive, (target_var ? current_variable_set_list->set : NULL), flocp); v->append = append; v->conditional = conditional; free (alloc_value); return v->special ? set_special_var (v) : v; } /* Parse P (a null-terminated string) as a variable definition. If it is not a variable definition, return NULL and the contents of *VAR are undefined, except NAME is set to the first non-space character or NIL. If it is a variable definition, return a pointer to the char after the assignment token and set the following fields (only) of *VAR: name : name of the variable (ALWAYS SET) (NOT NUL-TERMINATED!) length : length of the variable name value : value of the variable (nul-terminated) flavor : flavor of the variable Other values in *VAR are unchanged. */ char * parse_variable_definition (const char *p, struct variable *var) { int wspace = 0; const char *e = NULL; p = next_token (p); var->name = (char *)p; var->length = 0; while (1) { int c = *p++; /* If we find a comment or EOS, it's not a variable definition. */ if (STOP_SET (c, MAP_COMMENT|MAP_NUL)) return NULL; if (c == '$') { /* This begins a variable expansion reference. Make sure we don't treat chars inside the reference as assignment tokens. */ char closeparen; int count; c = *p++; if (c == '(') closeparen = ')'; else if (c == '{') closeparen = '}'; else /* '$$' or '$X'. Either way, nothing special to do here. */ continue; /* P now points past the opening paren or brace. Count parens or braces until it is matched. */ count = 0; for (; *p != '\0'; ++p) { if (*p == c) ++count; else if (*p == closeparen && --count < 0) { ++p; break; } } continue; } /* If we find whitespace skip it, and remember we found it. */ if (isblank ((unsigned char)c)) { wspace = 1; e = p - 1; p = next_token (p); c = *p; if (c == '\0') return NULL; ++p; } if (c == '=') { var->flavor = f_recursive; if (! e) e = p - 1; break; } /* Match assignment variants (:=, +=, ?=, !=) */ if (*p == '=') { switch (c) { case ':': var->flavor = f_simple; break; case '+': var->flavor = f_append; break; case '?': var->flavor = f_conditional; break; case '!': var->flavor = f_shell; break; default: /* If we skipped whitespace, non-assignments means no var. */ if (wspace) return NULL; /* Might be assignment, or might be $= or #=. Check. */ continue; } if (! e) e = p - 1; ++p; break; } /* Check for POSIX ::= syntax */ if (c == ':') { /* A colon other than :=/::= is not a variable defn. */ if (*p != ':' || p[1] != '=') return NULL; /* POSIX allows ::= to be the same as GNU make's := */ var->flavor = f_simple; if (! e) e = p - 1; p += 2; break; } /* If we skipped whitespace, non-assignments means no var. */ if (wspace) return NULL; } var->length = e - var->name; var->value = next_token (p); return (char *)p; } /* Try to interpret LINE (a null-terminated string) as a variable definition. If LINE was recognized as a variable definition, a pointer to its 'struct variable' is returned. If LINE is not a variable definition, NULL is returned. */ struct variable * assign_variable_definition (struct variable *v, const char *line) { char *name; if (!parse_variable_definition (line, v)) return NULL; /* Expand the name, so "$(foo)bar = baz" works. */ name = alloca (v->length + 1); memcpy (name, v->name, v->length); name[v->length] = '\0'; v->name = allocated_variable_expand (name); if (v->name[0] == '\0') O (fatal, &v->fileinfo, _("empty variable name")); return v; } /* Try to interpret LINE (a null-terminated string) as a variable definition. ORIGIN may be o_file, o_override, o_env, o_env_override, or o_command specifying that the variable definition comes from a makefile, an override directive, the environment with or without the -e switch, or the command line. See the comments for assign_variable_definition(). If LINE was recognized as a variable definition, a pointer to its 'struct variable' is returned. If LINE is not a variable definition, NULL is returned. */ struct variable * try_variable_definition (const gmk_floc *flocp, const char *line, enum variable_origin origin, int target_var) { struct variable v; struct variable *vp; if (flocp != 0) v.fileinfo = *flocp; else v.fileinfo.filenm = 0; if (!assign_variable_definition (&v, line)) return 0; vp = do_variable_definition (flocp, v.name, v.value, origin, v.flavor, target_var); free (v.name); return vp; } /* Print information for variable V, prefixing it with PREFIX. */ static void print_variable (const void *item, void *arg) { const struct variable *v = item; const char *prefix = arg; const char *origin; switch (v->origin) { case o_automatic: origin = _("automatic"); break; case o_default: origin = _("default"); break; case o_env: origin = _("environment"); break; case o_file: origin = _("makefile"); break; case o_env_override: origin = _("environment under -e"); break; case o_command: origin = _("command line"); break; case o_override: origin = _("'override' directive"); break; case o_invalid: default: abort (); } fputs ("# ", stdout); fputs (origin, stdout); if (v->private_var) fputs (" private", stdout); if (v->fileinfo.filenm) printf (_(" (from '%s', line %lu)"), v->fileinfo.filenm, v->fileinfo.lineno); putchar ('\n'); fputs (prefix, stdout); /* Is this a 'define'? */ if (v->recursive && strchr (v->value, '\n') != 0) printf ("define %s\n%s\nendef\n", v->name, v->value); else { char *p; printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); /* Check if the value is just whitespace. */ p = next_token (v->value); if (p != v->value && *p == '\0') /* All whitespace. */ printf ("$(subst ,,%s)", v->value); else if (v->recursive) fputs (v->value, stdout); else /* Double up dollar signs. */ for (p = v->value; *p != '\0'; ++p) { if (*p == '$') putchar ('$'); putchar (*p); } putchar ('\n'); } } /** Print information for variable V, prefixing it with PREFIX. */ void print_variable_info (const void *item, void *arg) { const variable_t *v = (variable_t *) item; const char *prefix = (char *) arg; const char *origin; if (o_invalid == v->origin) abort (); origin = origin2str(v->origin); if (prefix) { fputs ("# ", stdout); fputs (origin, stdout); if (v->fileinfo.filenm) printf (_(" (from `%s', line %lu)"), v->fileinfo.filenm, v->fileinfo.lineno); putchar ('\n'); fputs (prefix, stdout); } /* Is this a `define'? */ if (v->recursive && strchr (v->value, '\n') != 0) printf ("define %s\n%s\nendef\n", v->name, v->value); else { char *p; printf ("%s %s= ", v->name, v->recursive ? v->append ? "+" : "" : ":"); /* Check if the value is just whitespace. */ p = next_token (v->value); if (p != v->value && *p == '\0') /* All whitespace. */ printf ("$(subst ,,%s)", v->value); else if (v->recursive) fputs (v->value, stdout); else /* Double up dollar signs. */ for (p = v->value; *p != '\0'; ++p) { if (*p == '$') putchar ('$'); putchar (*p); } putchar ('\n'); } } static void print_auto_variable (const void *item, void *arg) { const struct variable *v = item; if (v->origin == o_automatic) print_variable (item, arg); } static void print_noauto_variable (const void *item, void *arg) { const struct variable *v = item; if (v->origin != o_automatic) print_variable (item, arg); } /* Print all the variables in SET. PREFIX is printed before the actual variable definitions (everything else is comments). */ void print_variable_set (struct variable_set *set, const char *prefix, int pauto) { hash_map_arg (&set->table, (pauto ? print_auto_variable : print_variable), (void *)prefix); fputs (_("# variable set hash-table stats:\n"), stdout); fputs ("# ", stdout); hash_print_stats (&set->table, stdout); putc ('\n', stdout); } /* Print the data base of variables. */ void print_variable_data_base (void) { puts (_("\n# Variables\n")); print_variable_set (&global_variable_set, "", 0); puts (_("\n# Pattern-specific Variable Values")); { struct pattern_var *p; int rules = 0; for (p = pattern_vars; p != 0; p = p->next) { ++rules; printf ("\n%s :\n", p->target); print_variable (&p->variable, (void *)"# "); } if (rules == 0) puts (_("\n# No pattern-specific variable values.")); else printf (_("\n# %d pattern-specific variable values"), rules); } } /* Print all the local variables of FILE. */ void print_file_variables (const file_t *p_target, bool b_hash_stats) { if (p_target->variables != 0) print_variable_set (p_target->variables->set, "# ", b_hash_stats); } void print_target_variables (const struct file *file) { if (file->variables != 0) { int l = strlen (file->name); char *t = alloca (l + 3); strcpy (t, file->name); t[l] = ':'; t[l+1] = ' '; t[l+2] = '\0'; hash_map_arg (&file->variables->set->table, print_noauto_variable, t); } } #ifdef WINDOWS32 void sync_Path_environment (void) { char *path = allocated_variable_expand ("$(PATH)"); static char *environ_path = NULL; if (!path) return; /* If done this before, free the previous entry before allocating new one. */ free (environ_path); /* Create something WINDOWS32 world can grok. */ convert_Path_to_windows32 (path, ';'); environ_path = xstrdup (concat (3, "PATH", "=", path)); putenv (environ_path); free (path); } #endif remake-4.1+dbg1.3~dfsg.1/variable.h000066400000000000000000000276541317072305000167470ustar00rootroot00000000000000/* Definitions for using variables in GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 VARIABLE_H #define VARIABLE_H #include "gnumake.h" #include "hash.h" /* Codes in a variable definition saying where the definition came from. Increasing numeric values signify less-overridable definitions. */ enum variable_origin { o_default, /* Variable from the default set. */ o_env, /* Variable from environment. */ o_file, /* Variable given in a makefile. */ o_env_override, /* Variable from environment, if -e. */ o_command, /* Variable given by user. */ o_override, /* Variable from an 'override' directive. */ o_automatic, /* Automatic variable -- cannot be set. */ o_debugger, /* Set inside debugger. */ o_invalid /* Core dump time. */ }; enum variable_flavor { f_bogus, /* Bogus (error) */ f_simple, /* Simple definition (:= or ::=) */ f_recursive, /* Recursive definition (=) */ f_append, /* Appending definition (+=) */ f_conditional, /* Conditional definition (?=) */ f_shell /* Shell assignment (!=) */ }; /* Structure that represents one variable definition. Each bucket of the hash table is a chain of these, chained through 'next'. */ #define EXP_COUNT_BITS 15 /* This gets all the bitfields into 32 bits */ #define EXP_COUNT_MAX ((1<1, allow this many self-referential expansions. */ enum variable_flavor flavor ENUM_BITFIELD (4); /* Variable flavor. */ enum variable_origin origin ENUM_BITFIELD (4); /* Variable origin. */ enum variable_export { v_export, /* Export this variable. */ v_noexport, /* Don't export this variable. */ v_ifset, /* Export it if it has a non-default value. */ v_default /* Decide in target_environment. */ } export ENUM_BITFIELD (2); }; /* Structure that represents a variable set. */ struct variable_set { struct hash_table table; /* Hash table of variables. */ }; /* Structure that represents a list of variable sets. */ struct variable_set_list { struct variable_set_list *next; /* Link in the chain. */ struct variable_set *set; /* Variable set. */ int next_is_parent; /* True if next is a parent target. */ }; /* Structure used for pattern-specific variables. */ struct pattern_var { struct pattern_var *next; const char *suffix; const char *target; unsigned int len; struct variable variable; }; extern char *variable_buffer; extern struct variable_set_list *current_variable_set_list; extern struct variable *default_goal_var; /* expand.c */ char *variable_buffer_output (char *ptr, const char *string, unsigned int length); char *variable_expand (const char *line); char *variable_expand_for_file (const char *line, struct file *file); char *allocated_variable_expand_for_file (const char *line, struct file *file); #define allocated_variable_expand(line) \ allocated_variable_expand_for_file (line, (struct file *) 0) char *expand_argument (const char *str, const char *end); char *variable_expand_string (char *line, const char *string, long length); void install_variable_buffer (char **bufp, unsigned int *lenp); void restore_variable_buffer (char *buf, unsigned int len); /* function.c */ int handle_function (char **op, const char **stringp); int pattern_matches (const char *pattern, const char *percent, const char *str); char *subst_expand (char *o, const char *text, const char *subst, const char *replace, unsigned int slen, unsigned int rlen, int by_word); char *patsubst_expand_pat (char *o, const char *text, const char *pattern, const char *replace, const char *pattern_percent, const char *replace_percent); char *patsubst_expand (char *o, const char *text, char *pattern, char *replace); char *func_shell_base (char *o, char **argv, int trim_newlines); /* expand.c */ char *recursively_expand_for_file (struct variable *v, struct file *file); #define recursively_expand(v) recursively_expand_for_file (v, NULL) /* variable.c */ struct variable_set_list *create_new_variable_set (void); /*! Return a string describing origin. */ const char *origin2str(variable_origin_t origin); void free_variable_set (struct variable_set_list *); /*! Create a new variable set, push it on the current setlist, and assign current_variable_set_list to it. */ struct variable_set_list *push_new_variable_scope (void); /*! Pop the top set off the current_variable_set_list, and free all its storage. If b_toplevel set we have the top-most global scope and some things don't get freed because they weren't malloc'd. */ void pop_variable_scope (void); /*! Define the automatic variables, and record the addresses of their structures so we can change their values quickly. */ void define_automatic_variables (void); /*! Initialize FILE's variable set list. If FILE already has a variable set list, the topmost variable set is left intact, but the the rest of the chain is replaced with FILE->parent's setlist. If FILE is a double-colon rule, then we will use the "root" double-colon target's variable set as the parent of FILE's variable set. If we're READing a makefile, don't do the pattern variable search now, since the pattern variable might not have been defined yet. */ void initialize_file_variables (struct file *file, int reading); /*! Print all the local variables of P_TARGET. Lines output have "# " prepended. If you want hash table statistics too, set b_hash_stats true. */ extern void print_file_variables(const file_t *p_target, bool b_hash_stats); /*! Print the data base of variables. */ extern void print_variable_data_base (void); /** Print information for variable V, prefixing it with PREFIX. */ extern void print_variable_info (const void *item, void *arg); void print_target_variables (const struct file *file); /*! Print all the variables in SET. PREFIX is printed before the actual variable definitions (everything else is comments). If you want hash table statistics too, set b_hash_stats true. */ void print_variable_set (struct variable_set *set, const char *prefix, int pauto); void merge_variable_set_lists (struct variable_set_list **to_list, struct variable_set_list *from_list); struct variable *do_variable_definition (const gmk_floc *flocp, const char *name, const char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var); char *parse_variable_definition (const char *line, struct variable *v); struct variable *assign_variable_definition (struct variable *v, const char *line); struct variable *try_variable_definition (const gmk_floc *flocp, const char *line, enum variable_origin origin, int target_var); void init_hash_global_variable_set (void); void hash_init_function_table (void); void define_new_function(const gmk_floc *flocp, const char *name, unsigned int min, unsigned int max, unsigned int flags, gmk_func_ptr func); struct variable *lookup_variable (const char *name, unsigned int length); struct variable *lookup_variable_in_set (const char *name, unsigned int length, const struct variable_set *set); struct variable *define_variable_in_set (const char *name, unsigned int length, const char *value, enum variable_origin origin, int recursive, struct variable_set *set, const gmk_floc *flocp); /* Define a variable in the current variable set. */ #define define_variable(n,l,v,o,r) \ define_variable_in_set((n),(l),(v),(o),(r),\ current_variable_set_list->set,NILF) /* Define a variable with a constant name in the current variable set. */ #define define_variable_cname(n,v,o,r) \ define_variable_in_set((n),(sizeof (n) - 1),(v),(o),(r),\ current_variable_set_list->set,NILF) /* Define a variable with a location in the current variable set. */ #define define_variable_loc(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),\ current_variable_set_list->set,(f)) /* Define a variable with a location in the global variable set. */ #define define_variable_global(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),NULL,(f)) /* Define a variable in FILE's variable set. */ #define define_variable_for_file(n,l,v,o,r,f) \ define_variable_in_set((n),(l),(v),(o),(r),(f)->variables->set,NILF) void undefine_variable_in_set (const char *name, unsigned int length, enum variable_origin origin, struct variable_set *set); /* Remove variable from the current variable set. */ #define undefine_variable_global(n,l,o) \ undefine_variable_in_set((n),(l),(o),NULL) /* Warn that NAME is an undefined variable. */ #define warn_undefined(n,l) do{\ if (warn_undefined_variables_flag) \ error (reading_file, (l), \ _("warning: undefined variable '%.*s'"), \ (int)(l), (n)); \ }while(0) char **target_environment (struct file *file); struct pattern_var *create_pattern_var (const char *target, const char *suffix); extern int export_all_variables; #define MAKELEVEL_NAME "MAKELEVEL" #define MAKELEVEL_LENGTH (CSTRLEN (MAKELEVEL_NAME)) #endif /*VARIABLE_H*/ remake-4.1+dbg1.3~dfsg.1/version.c000066400000000000000000000025501317072305000166260ustar00rootroot00000000000000/* Record version and build host architecture for GNU make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 . */ /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because makeint.h was found in $srcdir). */ #include #ifndef MAKE_HOST # define MAKE_HOST "unknown" #endif const char *version_string = VERSION; const char *make_host = MAKE_HOST; #ifndef NULL #define NULL 0 #endif #ifdef WINDOWS32 /* On MS-Windows, we chop off the .exe suffix in 'main', so this cannot be 'const'. */ char *program = NULL; #else const char *program = NULL; #endif /* Local variables: version-control: never End: */ remake-4.1+dbg1.3~dfsg.1/vpath.c000066400000000000000000000441271317072305000162710ustar00rootroot00000000000000/* Implementation of pattern-matching file search paths for GNU Make. Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include "filedef.h" #include "variable.h" #ifdef WINDOWS32 #include "pathstuff.h" #endif /* Structure used to represent a selective VPATH searchpath. */ struct vpath { struct vpath *next; /* Pointer to next struct in the linked list. */ const char *pattern;/* The pattern to match. */ const char *percent;/* Pointer into 'pattern' where the '%' is. */ unsigned int patlen;/* Length of the pattern. */ const char **searchpath; /* Null-terminated list of directories. */ unsigned int maxlen;/* Maximum length of any entry in the list. */ }; /* Linked-list of all selective VPATHs. */ static struct vpath *vpaths; /* Structure for the general VPATH given in the variable. */ static struct vpath *general_vpath; /* Structure for GPATH given in the variable. */ static struct vpath *gpaths; /* Reverse the chain of selective VPATH lists so they will be searched in the order given in the makefiles and construct the list from the VPATH variable. */ void build_vpath_lists () { register struct vpath *new = 0; register struct vpath *old, *nexto; register char *p; /* Reverse the chain. */ for (old = vpaths; old != 0; old = nexto) { nexto = old->next; old->next = new; new = old; } vpaths = new; /* If there is a VPATH variable with a nonnull value, construct the general VPATH list from it. We use variable_expand rather than just calling lookup_variable so that it will be recursively expanded. */ { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; p = variable_expand ("$(strip $(VPATH))"); warn_undefined_variables_flag = save; } if (*p != '\0') { /* Save the list of vpaths. */ struct vpath *save_vpaths = vpaths; char gp[] = "%"; /* Empty 'vpaths' so the new one will have no next, and 'vpaths' will still be nil if P contains no existing directories. */ vpaths = 0; /* Parse P. */ construct_vpath_list (gp, p); /* Store the created path as the general path, and restore the old list of vpaths. */ general_vpath = vpaths; vpaths = save_vpaths; } /* If there is a GPATH variable with a nonnull value, construct the GPATH list from it. We use variable_expand rather than just calling lookup_variable so that it will be recursively expanded. */ { /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ int save = warn_undefined_variables_flag; warn_undefined_variables_flag = 0; p = variable_expand ("$(strip $(GPATH))"); warn_undefined_variables_flag = save; } if (*p != '\0') { /* Save the list of vpaths. */ struct vpath *save_vpaths = vpaths; char gp[] = "%"; /* Empty 'vpaths' so the new one will have no next, and 'vpaths' will still be nil if P contains no existing directories. */ vpaths = 0; /* Parse P. */ construct_vpath_list (gp, p); /* Store the created path as the GPATH, and restore the old list of vpaths. */ gpaths = vpaths; vpaths = save_vpaths; } } /* Construct the VPATH listing for the PATTERN and DIRPATH given. This function is called to generate selective VPATH lists and also for the general VPATH list (which is in fact just a selective VPATH that is applied to everything). The returned pointer is either put in the linked list of all selective VPATH lists or in the GENERAL_VPATH variable. If DIRPATH is nil, remove all previous listings with the same pattern. If PATTERN is nil, remove all VPATH listings. Existing and readable directories that are not "." given in the DIRPATH separated by the path element separator (defined in makeint.h) are loaded into the directory hash table if they are not there already and put in the VPATH searchpath for the given pattern with trailing slashes stripped off if present (and if the directory is not the root, "/"). The length of the longest entry in the list is put in the structure as well. The new entry will be at the head of the VPATHS chain. */ void construct_vpath_list (char *pattern, char *dirpath) { unsigned int elem; char *p; const char **vpath; unsigned int maxvpath; unsigned int maxelem; const char *percent = NULL; if (pattern != 0) percent = find_percent (pattern); if (dirpath == 0) { /* Remove matching listings. */ struct vpath *path, *lastpath; lastpath = 0; path = vpaths; while (path != 0) { struct vpath *next = path->next; if (pattern == 0 || (((percent == 0 && path->percent == 0) || (percent - pattern == path->percent - path->pattern)) && streq (pattern, path->pattern))) { /* Remove it from the linked list. */ if (lastpath == 0) vpaths = path->next; else lastpath->next = next; /* Free its unused storage. */ /* MSVC erroneously warns without a cast here. */ free ((void *)path->searchpath); free (path); } else lastpath = path; path = next; } return; } #ifdef WINDOWS32 convert_vpath_to_windows32 (dirpath, ';'); #endif /* Skip over any initial separators and blanks. */ while (*dirpath == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*dirpath)) ++dirpath; /* Figure out the maximum number of VPATH entries and put it in MAXELEM. We start with 2, one before the first separator and one nil (the list terminator) and increment our estimated number for each separator or blank we find. */ maxelem = 2; p = dirpath; while (*p != '\0') if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) ++maxelem; vpath = xmalloc (maxelem * sizeof (const char *)); maxvpath = 0; elem = 0; p = dirpath; while (*p != '\0') { char *v; unsigned int len; /* Find the end of this entry. */ v = p; while (*p != '\0' #if defined(HAVE_DOS_PATHS) && (PATH_SEPARATOR_CHAR == ':') /* Platforms whose PATH_SEPARATOR_CHAR is ':' and which also define HAVE_DOS_PATHS would like us to recognize colons after the drive letter in the likes of "D:/foo/bar:C:/xyzzy". */ && (*p != PATH_SEPARATOR_CHAR || (p == v + 1 && (p[1] == '/' || p[1] == '\\'))) #else && *p != PATH_SEPARATOR_CHAR #endif && !isblank ((unsigned char)*p)) ++p; len = p - v; /* Make sure there's no trailing slash, but still allow "/" as a directory. */ #if defined(__MSDOS__) || defined(__EMX__) || defined(HAVE_DOS_PATHS) /* We need also to leave alone a trailing slash in "d:/". */ if (len > 3 || (len > 1 && v[1] != ':')) #endif if (len > 1 && p[-1] == '/') --len; /* Put the directory on the vpath list. */ if (len > 1 || *v != '.') { vpath[elem++] = dir_name (strcache_add_len (v, len)); if (len > maxvpath) maxvpath = len; } /* Skip over separators and blanks between entries. */ while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) ++p; } if (elem > 0) { struct vpath *path; /* ELEM is now incremented one element past the last entry, to where the nil-pointer terminator goes. Usually this is maxelem - 1. If not, shrink down. */ if (elem < (maxelem - 1)) vpath = xrealloc (vpath, (elem+1) * sizeof (const char *)); /* Put the nil-pointer terminator on the end of the VPATH list. */ vpath[elem] = NULL; /* Construct the vpath structure and put it into the linked list. */ path = xmalloc (sizeof (struct vpath)); path->searchpath = vpath; path->maxlen = maxvpath; path->next = vpaths; vpaths = path; /* Set up the members. */ path->pattern = strcache_add (pattern); path->patlen = strlen (pattern); path->percent = percent ? path->pattern + (percent - pattern) : 0; } else /* There were no entries, so free whatever space we allocated. */ /* MSVC erroneously warns without a cast here. */ free ((void *)vpath); } /* Search the GPATH list for a pathname string that matches the one passed in. If it is found, return 1. Otherwise we return 0. */ int gpath_search (const char *file, unsigned int len) { if (gpaths && (len <= gpaths->maxlen)) { const char **gp; for (gp = gpaths->searchpath; *gp != NULL; ++gp) if (strneq (*gp, file, len) && (*gp)[len] == '\0') return 1; } return 0; } /* Search the given VPATH list for a directory where the name pointed to by FILE exists. If it is found, we return a cached name of the existing file and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no stat call was done). Also set the matching directory index in PATH_INDEX if it is not NULL. Otherwise we return NULL. */ static const char * selective_vpath_search (struct vpath *path, const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* path_index) { int not_target; char *name; const char *n; const char *filename; const char **vpath = path->searchpath; unsigned int maxvpath = path->maxlen; unsigned int i; unsigned int flen, name_dplen; int exists = 0; /* Find out if *FILE is a target. If and only if it is NOT a target, we will accept prospective files that don't exist but are mentioned in a makefile. */ { struct file *f = lookup_file (file); not_target = f == 0 || !f->is_target; } flen = strlen (file); /* Split *FILE into a directory prefix and a name-within-directory. NAME_DPLEN gets the length of the prefix; FILENAME gets the pointer to the name-within-directory and FLEN is its length. */ n = strrchr (file, '/'); #ifdef HAVE_DOS_PATHS /* We need the rightmost slash or backslash. */ { const char *bslash = strrchr (file, '\\'); if (!n || bslash > n) n = bslash; } #endif name_dplen = n != 0 ? n - file : 0; filename = name_dplen > 0 ? n + 1 : file; if (name_dplen > 0) flen -= name_dplen + 1; /* Get enough space for the biggest VPATH entry, a slash, the directory prefix that came with FILE, another slash (although this one may not always be necessary), the filename, and a null terminator. */ name = alloca (maxvpath + 1 + name_dplen + 1 + flen + 1); /* Try each VPATH entry. */ for (i = 0; vpath[i] != 0; ++i) { int exists_in_cache = 0; char *p = name; unsigned int vlen = strlen (vpath[i]); /* Put the next VPATH entry into NAME at P and increment P past it. */ memcpy (p, vpath[i], vlen); p += vlen; /* Add the directory prefix already in *FILE. */ if (name_dplen > 0) { #ifndef VMS *p++ = '/'; #endif memcpy (p, file, name_dplen); p += name_dplen; } #ifdef HAVE_DOS_PATHS /* Cause the next if to treat backslash and slash alike. */ if (p != name && p[-1] == '\\' ) p[-1] = '/'; #endif /* Now add the name-within-directory at the end of NAME. */ #ifndef VMS if (p != name && p[-1] != '/') { *p = '/'; memcpy (p + 1, filename, flen + 1); } else #endif memcpy (p, filename, flen + 1); /* Check if the file is mentioned in a makefile. If *FILE is not a target, that is enough for us to decide this file exists. If *FILE is a target, then the file must be mentioned in the makefile also as a target to be chosen. The restriction that *FILE must not be a target for a makefile-mentioned file to be chosen was added by an inadequately commented change in July 1990; I am not sure off hand what problem it fixes. In December 1993 I loosened this restriction to allow a file to be chosen if it is mentioned as a target in a makefile. This seem logical. Special handling for -W / -o: make sure we preserve the special values here. Actually this whole thing is a little bogus: I think we should ditch the name/hname thing and look into the renamed capability that already exists for files: that is, have a new struct file* entry for the VPATH-found file, and set the renamed field if we use it. */ { struct file *f = lookup_file (name); if (f != 0) { exists = not_target || f->is_target; if (exists && mtime_ptr && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME)) { *mtime_ptr = f->last_mtime; mtime_ptr = 0; } } } if (!exists) { /* That file wasn't mentioned in the makefile. See if it actually exists. */ #ifdef VMS exists_in_cache = exists = dir_file_exists_p (vpath[i], filename); #else /* Clobber a null into the name at the last slash. Now NAME is the name of the directory to look in. */ *p = '\0'; /* We know the directory is in the hash table now because either construct_vpath_list or the code just above put it there. Does the file we seek exist in it? */ exists_in_cache = exists = dir_file_exists_p (name, filename); #endif } if (exists) { /* The file is in the directory cache. Now check that it actually exists in the filesystem. The cache may be out of date. When vpath thinks a file exists, but stat fails for it, confusion results in the higher levels. */ struct stat st; #ifndef VMS /* Put the slash back in NAME. */ *p = '/'; #endif if (exists_in_cache) /* Makefile-mentioned file need not exist. */ { int e; EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */ if (e != 0) { exists = 0; continue; } /* Store the modtime into *MTIME_PTR for the caller. */ if (mtime_ptr != 0) { *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st); mtime_ptr = 0; } } /* We have found a file. If we get here and mtime_ptr hasn't been set, record UNKNOWN_MTIME to indicate this. */ if (mtime_ptr != 0) *mtime_ptr = UNKNOWN_MTIME; /* Store the name we found and return it. */ if (path_index) *path_index = i; return strcache_add_len (name, (p + 1 - name) + flen); } } return 0; } /* Search the VPATH list whose pattern matches FILE for a directory where FILE exists. If it is found, return the cached name of an existing file, and set *MTIME_PTR (if MTIME_PTR is not NULL) to its modtime (or zero if no stat call was done). Also set the matching directory index in VPATH_INDEX and PATH_INDEX if they are not NULL. Otherwise we return 0. */ const char * vpath_search (const char *file, FILE_TIMESTAMP *mtime_ptr, unsigned int* vpath_index, unsigned int* path_index) { struct vpath *v; /* If there are no VPATH entries or FILENAME starts at the root, there is nothing we can do. */ if (file[0] == '/' #ifdef HAVE_DOS_PATHS || file[0] == '\\' || file[1] == ':' #endif || (vpaths == 0 && general_vpath == 0)) return 0; if (vpath_index) { *vpath_index = 0; *path_index = 0; } for (v = vpaths; v != 0; v = v->next) { if (pattern_matches (v->pattern, v->percent, file)) { const char *p = selective_vpath_search ( v, file, mtime_ptr, path_index); if (p) return p; } if (vpath_index) ++*vpath_index; } if (general_vpath != 0) { const char *p = selective_vpath_search ( general_vpath, file, mtime_ptr, path_index); if (p) return p; } return 0; } /* Print the data base of VPATH search paths. */ void print_vpath_data_base (void) { unsigned int nvpaths; struct vpath *v; puts (_("\n# VPATH Search Paths\n")); nvpaths = 0; for (v = vpaths; v != 0; v = v->next) { register unsigned int i; ++nvpaths; printf ("vpath %s ", v->pattern); for (i = 0; v->searchpath[i] != 0; ++i) printf ("%s%c", v->searchpath[i], v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); } if (vpaths == 0) puts (_("# No 'vpath' search paths.")); else printf (_("\n# %u 'vpath' search paths.\n"), nvpaths); if (general_vpath == 0) puts (_("\n# No general ('VPATH' variable) search path.")); else { const char **path = general_vpath->searchpath; unsigned int i; fputs (_("\n# General ('VPATH' variable) search path:\n# "), stdout); for (i = 0; path[i] != 0; ++i) printf ("%s%c", path[i], path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); } } remake-4.1+dbg1.3~dfsg.1/vpath.h000066400000000000000000000001411317072305000162620ustar00rootroot00000000000000#ifndef REMAKE_VPATH_H #define REMAKE_VPATH_H extern void print_vpath_data_base (void); #endif remake-4.1+dbg1.3~dfsg.1/w32/000077500000000000000000000000001317072305000154065ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/w32/.cvsignore000066400000000000000000000000331317072305000174020ustar00rootroot00000000000000Makefile Makefile.in .deps remake-4.1+dbg1.3~dfsg.1/w32/.gitignore000066400000000000000000000000331317072305000173720ustar00rootroot00000000000000/*~ /Makefile /Makefile.in remake-4.1+dbg1.3~dfsg.1/w32/Makefile.am000066400000000000000000000017741317072305000174530ustar00rootroot00000000000000# Makefile.am to create libw32.a for mingw32 host. # Copyright (C) 1997-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . AUTOMAKE_OPTIONS = subdir-objects noinst_LIBRARIES = libw32.a libw32_a_SOURCES = subproc/misc.c subproc/sub_proc.c subproc/w32err.c \ compat/posixfcn.c pathstuff.c libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) remake-4.1+dbg1.3~dfsg.1/w32/compat/000077500000000000000000000000001317072305000166715ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/w32/compat/dirent.c000066400000000000000000000125631317072305000203310ustar00rootroot00000000000000/* Directory entry code for Window platforms. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 #include #include #include #include #include "dirent.h" DIR* opendir(const char* pDirName) { struct stat sb; DIR* pDir; char* pEndDirName; int nBufferLen; /* sanity checks */ if (!pDirName) { errno = EINVAL; return NULL; } if (stat(pDirName, &sb) != 0) { errno = ENOENT; return NULL; } if ((sb.st_mode & S_IFMT) != S_IFDIR) { errno = ENOTDIR; return NULL; } /* allocate a DIR structure to return */ pDir = (DIR *) malloc(sizeof (DIR)); if (!pDir) return NULL; /* input directory name length */ nBufferLen = strlen(pDirName); /* copy input directory name to DIR buffer */ strcpy(pDir->dir_pDirectoryName, pDirName); /* point to end of the copied directory name */ pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1]; /* if directory name did not end in '/' or '\', add '/' */ if ((*pEndDirName != '/') && (*pEndDirName != '\\')) { pEndDirName++; *pEndDirName = '/'; } /* now append the wildcard character to the buffer */ pEndDirName++; *pEndDirName = '*'; pEndDirName++; *pEndDirName = '\0'; /* other values defaulted */ pDir->dir_nNumFiles = 0; pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_ulCookie = __DIRENT_COOKIE; return pDir; } void closedir(DIR *pDir) { /* got a valid pointer? */ if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) FindClose(pDir->dir_hDirHandle); free(pDir); return; } struct dirent * readdir(DIR* pDir) { WIN32_FIND_DATA wfdFindData; if (!pDir) { errno = EINVAL; return NULL; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return NULL; } if (pDir->dir_nNumFiles == 0) { pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData); if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE) return NULL; } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData)) return NULL; /* bump count for next call to readdir() or telldir() */ pDir->dir_nNumFiles++; /* fill in struct dirent values */ pDir->dir_sdReturn.d_ino = (ino_t)-1; strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); return &pDir->dir_sdReturn; } void rewinddir(DIR* pDir) { if (!pDir) { errno = EINVAL; return; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return; } /* close the WINDOWS32 directory handle */ if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) if (!FindClose(pDir->dir_hDirHandle)) errno = EBADF; /* reset members which control readdir() */ pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; pDir->dir_nNumFiles = 0; return; } int telldir(DIR* pDir) { if (!pDir) { errno = EINVAL; return -1; } /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) { errno = EINVAL; return -1; } /* return number of times readdir() called */ return pDir->dir_nNumFiles; } void seekdir(DIR* pDir, long nPosition) { if (!pDir) return; /* sanity check that this is a DIR pointer */ if (pDir->dir_ulCookie != __DIRENT_COOKIE) return; /* go back to beginning of directory */ rewinddir(pDir); /* loop until we have found position we care about */ for (--nPosition; nPosition && readdir(pDir); nPosition--); /* flag invalid nPosition value */ if (nPosition) errno = EINVAL; return; } remake-4.1+dbg1.3~dfsg.1/w32/compat/posixfcn.c000066400000000000000000000334761317072305000207030ustar00rootroot00000000000000/* Replacements for Posix functions and Posix functionality for MS-Windows. Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 #include #include #include #include "dlfcn.h" #include "makeint.h" #include "job.h" #ifndef NO_OUTPUT_SYNC /* Support for OUTPUT_SYNC and related functionality. */ /* Emulation of fcntl that supports only F_GETFD and F_SETLKW. */ int fcntl (intptr_t fd, int cmd, ...) { va_list ap; va_start (ap, cmd); switch (cmd) { case F_GETFD: va_end (ap); /* Could have used GetHandleInformation, but that isn't supported on Windows 9X. */ if (_get_osfhandle (fd) == -1) return -1; return 0; case F_SETLKW: { void *buf = va_arg (ap, void *); struct flock *fl = (struct flock *)buf; HANDLE hmutex = (HANDLE)fd; static struct flock last_fl; short last_type = last_fl.l_type; va_end (ap); if (hmutex == INVALID_HANDLE_VALUE || !hmutex) return -1; last_fl = *fl; switch (fl->l_type) { case F_WRLCK: { DWORD result; if (last_type == F_WRLCK) { /* Don't call WaitForSingleObject if we already own the mutex, because doing so will require us to call ReleaseMutex an equal number of times, before the mutex is actually released. */ return 0; } result = WaitForSingleObject (hmutex, INFINITE); switch (result) { case WAIT_OBJECT_0: /* We don't care if the mutex owner crashed or exited. */ case WAIT_ABANDONED: return 0; case WAIT_FAILED: case WAIT_TIMEOUT: /* cannot happen, really */ { DWORD err = GetLastError (); /* Invalidate the last command. */ memset (&last_fl, 0, sizeof (last_fl)); switch (err) { case ERROR_INVALID_HANDLE: case ERROR_INVALID_FUNCTION: errno = EINVAL; return -1; default: errno = EDEADLOCK; return -1; } } } } case F_UNLCK: { /* FIXME: Perhaps we should call ReleaseMutex repatedly until it errors out, to make sure the mutext is released even if we somehow managed to to take ownership multiple times? */ BOOL status = ReleaseMutex (hmutex); if (status) return 0; else { DWORD err = GetLastError (); if (err == ERROR_NOT_OWNER) errno = EPERM; else { memset (&last_fl, 0, sizeof (last_fl)); errno = EINVAL; } return -1; } } default: errno = ENOSYS; return -1; } } default: errno = ENOSYS; va_end (ap); return -1; } } static intptr_t mutex_handle = -1; /* Record in a static variable the mutex handle we were requested to use. That nameless mutex was created by the top-level Make, and its handle was passed to us via inheritance. The value of that handle is passed via the command-line arguments, so that we know which handle to use. */ void record_sync_mutex (const char *str) { char *endp; intptr_t hmutex = strtol (str, &endp, 16); if (*endp == '\0') mutex_handle = hmutex; else { mutex_handle = -1; errno = EINVAL; } } /* Create a new mutex or reuse one created by our parent. */ intptr_t create_mutex (void) { SECURITY_ATTRIBUTES secattr; intptr_t hmutex = -1; /* If we have a mutex handle passed from the parent Make, just use that. */ if (mutex_handle > 0) return mutex_handle; /* We are the top-level Make, and we want the handle to be inherited by our child processes. */ secattr.nLength = sizeof (secattr); secattr.lpSecurityDescriptor = NULL; /* use default security descriptor */ secattr.bInheritHandle = TRUE; hmutex = (intptr_t)CreateMutex (&secattr, FALSE, NULL); if (!hmutex) { DWORD err = GetLastError (); fprintf (stderr, "CreateMutex: error %lu\n", err); errno = ENOLCK; hmutex = -1; } mutex_handle = hmutex; return hmutex; } /* Return non-zero if F1 and F2 are 2 streams representing the same file or pipe or device. */ int same_stream (FILE *f1, FILE *f2) { HANDLE fh1 = (HANDLE)_get_osfhandle (fileno (f1)); HANDLE fh2 = (HANDLE)_get_osfhandle (fileno (f2)); /* Invalid file descriptors get treated as different streams. */ if (fh1 && fh1 != INVALID_HANDLE_VALUE && fh2 && fh2 != INVALID_HANDLE_VALUE) { if (fh1 == fh2) return 1; else { DWORD ftyp1 = GetFileType (fh1), ftyp2 = GetFileType (fh2); if (ftyp1 != ftyp2 || ftyp1 == FILE_TYPE_UNKNOWN || ftyp2 == FILE_TYPE_UNKNOWN) return 0; else if (ftyp1 == FILE_TYPE_CHAR) { /* For character devices, check if they both refer to a console. This loses if both handles refer to the null device (FIXME!), but in that case we don't care in the context of Make. */ DWORD conmode1, conmode2; /* Each process on Windows can have at most 1 console, so if both handles are for the console device, they are the same. We also compare the console mode to distinguish between stdin and stdout/stderr. */ if (GetConsoleMode (fh1, &conmode1) && GetConsoleMode (fh2, &conmode2) && conmode1 == conmode2) return 1; } else { /* For disk files and pipes, compare their unique attributes. */ BY_HANDLE_FILE_INFORMATION bhfi1, bhfi2; /* Pipes get zero in the volume serial number, but do appear to have meaningful information in file index attributes. We test file attributes as well, for a good measure. */ if (GetFileInformationByHandle (fh1, &bhfi1) && GetFileInformationByHandle (fh2, &bhfi2)) return (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber && bhfi1.nFileIndexLow == bhfi2.nFileIndexLow && bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh && bhfi1.dwFileAttributes == bhfi2.dwFileAttributes); } } } return 0; } /* A replacement for tmpfile, since the MSVCRT implementation creates the file in the root directory of the current drive, which might not be writable by our user. Most of the code borrowed from create_batch_file, see job.c. */ FILE * tmpfile (void) { char temp_path[MAXPATHLEN]; unsigned path_size = GetTempPath (sizeof temp_path, temp_path); int path_is_dot = 0; /* The following variable is static so we won't try to reuse a name that was generated a little while ago, because that file might not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below, which tells the OS it doesn't need to flush the cache to disk. If the file is not yet on disk, we might think the name is available, while it really isn't. This happens in parallel builds, where Make doesn't wait for one job to finish before it launches the next one. */ static unsigned uniq = 0; static int second_loop = 0; const char base[] = "gmake_tmpf"; const unsigned sizemax = sizeof base - 1 + 4 + 10 + 10; unsigned pid = GetCurrentProcessId (); if (path_size == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } ++uniq; if (uniq >= 0x10000 && !second_loop) { /* If we already had 64K batch files in this process, make a second loop through the numbers, looking for free slots, i.e. files that were deleted in the meantime. */ second_loop = 1; uniq = 1; } while (path_size > 0 && path_size + sizemax < sizeof temp_path && !(uniq >= 0x10000 && second_loop)) { HANDLE h; sprintf (temp_path + path_size, "%s%s%u-%x.tmp", temp_path[path_size - 1] == '\\' ? "" : "\\", base, pid, uniq); h = CreateFile (temp_path, /* file name */ GENERIC_READ | GENERIC_WRITE | DELETE, /* desired access */ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ NULL, /* default security attributes */ CREATE_NEW, /* creation disposition */ FILE_ATTRIBUTE_NORMAL | /* flags and attributes */ FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); /* no template file */ if (h == INVALID_HANDLE_VALUE) { const DWORD er = GetLastError (); if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS) { ++uniq; if (uniq == 0x10000 && !second_loop) { second_loop = 1; uniq = 1; } } /* The temporary path is not guaranteed to exist, or might not be writable by user. Use the current directory as fallback. */ else if (path_is_dot == 0) { path_size = GetCurrentDirectory (sizeof temp_path, temp_path); path_is_dot = 1; } else { errno = EACCES; break; } } else { int fd = _open_osfhandle ((intptr_t)h, 0); return _fdopen (fd, "w+b"); } } if (uniq >= 0x10000) errno = EEXIST; return NULL; } #endif /* !NO_OUTPUT_SYNC */ #if MAKE_LOAD /* Support for dynamic loading of objects. */ static DWORD last_err; void * dlopen (const char *file, int mode) { char dllfn[MAX_PATH], *p; HANDLE dllhandle; if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0) { errno = EINVAL; last_err = ERROR_INVALID_PARAMETER; return NULL; } if (!file) dllhandle = GetModuleHandle (NULL); else { /* MSDN says to be sure to use backslashes in the DLL file name. */ strcpy (dllfn, file); for (p = dllfn; *p; p++) if (*p == '/') *p = '\\'; dllhandle = LoadLibrary (dllfn); } if (!dllhandle) last_err = GetLastError (); return dllhandle; } char * dlerror (void) { static char errbuf[1024]; DWORD ret; if (!last_err) return NULL; ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_err, 0, errbuf, sizeof (errbuf), NULL); while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r')) --ret; errbuf[ret] = '\0'; if (!ret) sprintf (errbuf, "Error code %lu", last_err); last_err = 0; return errbuf; } void * dlsym (void *handle, const char *name) { FARPROC addr = NULL; if (!handle || handle == INVALID_HANDLE_VALUE) { last_err = ERROR_INVALID_PARAMETER; return NULL; } addr = GetProcAddress (handle, name); if (!addr) last_err = GetLastError (); return (void *)addr; } int dlclose (void *handle) { if (!handle || handle == INVALID_HANDLE_VALUE) return -1; if (!FreeLibrary (handle)) return -1; return 0; } #endif /* MAKE_LOAD */ /* MS runtime's isatty returns non-zero for any character device, including the null device, which is not what we want. */ int isatty (int fd) { HANDLE fh = (HANDLE) _get_osfhandle (fd); DWORD con_mode; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return 0; } if (GetConsoleMode (fh, &con_mode)) return 1; errno = ENOTTY; return 0; } char * ttyname (int fd) { /* This "knows" that Make only asks about stdout and stderr. A more sophisticated implementation should test whether FD is open for input or output. We can do that by looking at the mode returned by GetConsoleMode. */ return "CONOUT$"; } remake-4.1+dbg1.3~dfsg.1/w32/include/000077500000000000000000000000001317072305000170315ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/w32/include/dirent.h000066400000000000000000000027661317072305000205020ustar00rootroot00000000000000/* Windows version of dirent.h Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _DIRENT_H #define _DIRENT_H #ifdef __MINGW32__ # include # include_next #else #include #include #include #include #ifndef NAME_MAX #define NAME_MAX 255 #endif #define __DIRENT_COOKIE 0xfefeabab struct dirent { ino_t d_ino; /* unused - no equivalent on WINDOWS32 */ char d_name[NAME_MAX+1]; }; typedef struct dir_struct { ULONG dir_ulCookie; HANDLE dir_hDirHandle; DWORD dir_nNumFiles; char dir_pDirectoryName[NAME_MAX+1]; struct dirent dir_sdReturn; } DIR; DIR *opendir(const char *); struct dirent *readdir(DIR *); void rewinddir(DIR *); void closedir(DIR *); int telldir(DIR *); void seekdir(DIR *, long); #endif /* !__MINGW32__ */ #endif remake-4.1+dbg1.3~dfsg.1/w32/include/dlfcn.h000066400000000000000000000017601317072305000202740ustar00rootroot00000000000000/* dlfcn.h replacement for MS-Windows build. Copyright (C) 2013-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 DLFCN_H #define DLFCN_H #define RTLD_LAZY 1 #define RTLD_NOW 2 #define RTLD_GLOBAL 4 extern void *dlopen (const char *, int); extern void *dlsym (void *, const char *); extern char *dlerror (void); extern int dlclose (void *); #endif /* DLFCN_H */ remake-4.1+dbg1.3~dfsg.1/w32/include/pathstuff.h000066400000000000000000000017441317072305000212140ustar00rootroot00000000000000/* Definitions for Windows path manipulation. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _PATHSTUFF_H #define _PATHSTUFF_H char *convert_Path_to_windows32(char *Path, char to_delim); char *convert_vpath_to_windows32(char *Path, char to_delim); char *w32ify(const char *file, int resolve); char *getcwd_fs(char *buf, int len); #endif remake-4.1+dbg1.3~dfsg.1/w32/include/sub_proc.h000066400000000000000000000053321317072305000210210ustar00rootroot00000000000000/* Definitions for Windows process invocation. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 SUB_PROC_H #define SUB_PROC_H /* * Component Name: * * $Date$ * * $Source$ * * $Id$ */ #define EXTERN_DECL(entry, args) extern entry args #define VOID_DECL void EXTERN_DECL(HANDLE process_init, (VOID_DECL)); EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)); EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user)); EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, int stdin_data_len)); EXTERN_DECL(long process_file_io, (HANDLE proc)); EXTERN_DECL(void process_cleanup, (HANDLE proc)); EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus)); EXTERN_DECL(void process_register, (HANDLE proc)); EXTERN_DECL(HANDLE process_easy, (char** argv, char** env, int outfd, int errfd)); EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal)); EXTERN_DECL(int process_used_slots, (VOID_DECL)); /* support routines */ EXTERN_DECL(long process_errno, (HANDLE proc)); EXTERN_DECL(long process_last_err, (HANDLE proc)); EXTERN_DECL(long process_exit_code, (HANDLE proc)); EXTERN_DECL(long process_signal, (HANDLE proc)); EXTERN_DECL(char * process_outbuf, (HANDLE proc)); EXTERN_DECL(char * process_errbuf, (HANDLE proc)); EXTERN_DECL(int process_outcnt, (HANDLE proc)); EXTERN_DECL(int process_errcnt, (HANDLE proc)); EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3])); EXTERN_DECL(void process_noinherit, (int fildes)); /* jobserver routines */ EXTERN_DECL(int open_jobserver_semaphore, (const char* name)); EXTERN_DECL(int create_jobserver_semaphore, (int tokens)); EXTERN_DECL(void free_jobserver_semaphore, (VOID_DECL)); EXTERN_DECL(int acquire_jobserver_semaphore, (VOID_DECL)); EXTERN_DECL(int release_jobserver_semaphore, (VOID_DECL)); EXTERN_DECL(int has_jobserver_semaphore, (VOID_DECL)); EXTERN_DECL(char* get_jobserver_semaphore_name, (VOID_DECL)); EXTERN_DECL(int wait_for_semaphore_or_child_process, (VOID_DECL)); #endif remake-4.1+dbg1.3~dfsg.1/w32/include/w32err.h000066400000000000000000000016631317072305000203340ustar00rootroot00000000000000/* Definitions for Windows error handling. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _W32ERR_H_ #define _W32ERR_H_ #ifndef EXTERN_DECL #define EXTERN_DECL(entry, args) entry args #endif EXTERN_DECL(const char * map_windows32_error_to_string, (DWORD error)); #endif /* !_W32ERR_H */ remake-4.1+dbg1.3~dfsg.1/w32/pathstuff.c000066400000000000000000000203271317072305000175620ustar00rootroot00000000000000/* Path conversion for Windows pathnames. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 "makeint.h" #include #include #include "pathstuff.h" /* * Convert delimiter separated vpath to Canonical format. */ char * convert_vpath_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ /* * Convert all spaces to delimiters. Note that pathnames which * contain blanks get trounced here. Use 8.3 format as a workaround. */ for (etok = Path; etok && *etok; etok++) if (isblank ((unsigned char) *etok)) *etok = to_delim; return (convert_Path_to_windows32(Path, to_delim)); } /* * Convert delimiter separated path to Canonical format. */ char * convert_Path_to_windows32(char *Path, char to_delim) { char *etok; /* token separator for old Path */ char *p; /* points to element of old Path */ /* is this a multi-element Path ? */ /* FIXME: Perhaps use ":;\"" in strpbrk to convert all quotes to delimiters as well, as a way to handle quoted directories in PATH? */ for (p = Path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { etok[-1] = to_delim; etok[0] = to_delim; p = ++etok; continue; /* ignore empty bucket */ } else if (!isalpha ((unsigned char) *p)) { /* found one to count, handle things like '.' */ *etok = to_delim; p = ++etok; } else if ((*etok == ':') && (etok = strpbrk(etok+1, ":;"))) { /* found one to count, handle drive letter */ *etok = to_delim; p = ++etok; } else /* all finished, force abort */ p += strlen(p); } else if (*p == '"') { /* a quoted directory */ for (p++; *p && *p != '"'; p++) /* skip quoted part */ ; etok = strpbrk(p, ":;"); /* find next delimiter */ if (etok) { *etok = to_delim; p = ++etok; } else p += strlen(p); } else { /* found another one, no drive letter */ *etok = to_delim; p = ++etok; } return Path; } /* * Convert to forward slashes. Resolve to full pathname optionally */ char * w32ify(const char *filename, int resolve) { static char w32_path[FILENAME_MAX]; char *p; if (resolve) _fullpath(w32_path, filename, sizeof (w32_path)); else strncpy(w32_path, filename, sizeof (w32_path)); for (p = w32_path; p && *p; p++) if (*p == '\\') *p = '/'; return w32_path; } char * getcwd_fs(char* buf, int len) { char *p = getcwd(buf, len); if (p) { char *q = w32ify(buf, 0); strncpy(buf, q, len); } return p; } #ifdef unused /* * Convert delimiter separated pathnames (e.g. PATH) or single file pathname * (e.g. c:/foo, c:\bar) to NutC format. If we are handed a string that * _NutPathToNutc() fails to convert, just return the path we were handed * and assume the caller will know what to do with it (It was probably * a mistake to try and convert it anyway due to some of the bizarre things * that might look like pathnames in makefiles). */ char * convert_path_to_nutc(char *path) { int count; /* count of path elements */ char *nutc_path; /* new NutC path */ int nutc_path_len; /* length of buffer to allocate for new path */ char *pathp; /* pointer to nutc_path used to build it */ char *etok; /* token separator for old path */ char *p; /* points to element of old path */ char sep; /* what flavor of separator used in old path */ char *rval; /* is this a multi-element path ? */ for (p = path, etok = strpbrk(p, ":;"), count = 0; etok; etok = strpbrk(p, ":;")) if ((etok - p) == 1) { if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; /* ignore empty bucket */ } else if (etok = strpbrk(etok+1, ":;")) /* found one to count, handle drive letter */ p = ++etok, count++; else /* all finished, force abort */ p += strlen(p); } else /* found another one, no drive letter */ p = ++etok, count++; if (count) { count++; /* x1;x2;x3 <- need to count x3 */ /* * Hazard a guess on how big the buffer needs to be. * We have to convert things like c:/foo to /c=/foo. */ nutc_path_len = strlen(path) + (count*2) + 1; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; /* * Loop through PATH and convert one elemnt of the path at at * a time. Single file pathnames will fail this and fall * to the logic below loop. */ for (p = path, etok = strpbrk(p, ":;"); etok; etok = strpbrk(p, ":;")) { /* don't trip up on device specifiers or empty path slots */ if ((etok - p) == 1) if (*(etok - 1) == ';' || *(etok - 1) == ':') { p = ++etok; continue; } else if ((etok = strpbrk(etok+1, ":;")) == NULL) break; /* thing found was a WINDOWS32 pathname */ /* save separator */ sep = *etok; /* terminate the current path element -- temporarily */ *etok = '\0'; #ifdef __NUTC__ /* convert to NutC format */ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif pathp += strlen(pathp); *pathp++ = ':'; /* use Unix style path separtor for new path */ *pathp = '\0'; /* make sure we are null terminaed */ /* restore path separator */ *etok = sep; /* point p to first char of next path element */ p = ++etok; } } else { nutc_path_len = strlen(path) + 3; nutc_path = xmalloc(nutc_path_len); pathp = nutc_path; *pathp = '\0'; p = path; } /* * OK, here we handle the last element in PATH (e.g. c of a;b;c) * or the path was a single filename and will be converted * here. Note, testing p here assures that we don't trip up * on paths like a;b; which have trailing delimiter followed by * nothing. */ if (*p != '\0') { #ifdef __NUTC__ if (_NutPathToNutc(p, pathp, 0) == FALSE) { free(nutc_path); rval = savestring(path, strlen(path)); return rval; } #else *pathp++ = '/'; *pathp++ = p[0]; *pathp++ = '='; *pathp++ = '/'; strcpy(pathp, &p[2]); #endif } else *(pathp-1) = '\0'; /* we're already done, don't leave trailing : */ rval = savestring(nutc_path, strlen(nutc_path)); free(nutc_path); return rval; } #endif remake-4.1+dbg1.3~dfsg.1/w32/subproc/000077500000000000000000000000001317072305000170635ustar00rootroot00000000000000remake-4.1+dbg1.3~dfsg.1/w32/subproc/NMakefile000066400000000000000000000035321317072305000206440ustar00rootroot00000000000000# NOTE: If you have no 'make' program at all to process this makefile, run # 'build.bat' instead. # # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is part of GNU Make. # # GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU 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 . # # NMakefile for GNU Make (subproc library) # LIB = lib CC = cl MAKE = nmake OUTDIR=. MAKEFILE=NMakefile CFLAGS_any = /nologo /MT /W4 /GX /Z7 /YX /D WIN32 /D WINDOWS32 /D _WINDOWS -I. -I../include -I../../ CFLAGS_debug = $(CFLAGS_any) /Od /D _DEBUG /FR.\WinDebug\ /Fp.\WinDebug\subproc.pch /Fo.\WinDebug/ CFLAGS_release = $(CFLAGS_any) /O2 /FR.\WinRel\ /Fp.\WinRel\subproc.pch /Fo.\WinRel/ all: Release Debug Release: $(MAKE) /f $(MAKEFILE) OUTDIR=WinRel CFLAGS="$(CFLAGS_release)" WinRel/subproc.lib Debug: $(MAKE) /f $(MAKEFILE) OUTDIR=WinDebug CFLAGS="$(CFLAGS_debug)" WinDebug/subproc.lib clean: rmdir /s /q WinRel WinDebug erase *.pdb $(OUTDIR): if not exist .\$@\nul mkdir .\$@ OBJS = $(OUTDIR)/misc.obj $(OUTDIR)/w32err.obj $(OUTDIR)/sub_proc.obj $(OUTDIR)/subproc.lib: $(OUTDIR) $(OBJS) $(LIB) -out:$@ @<< $(OBJS) << .c{$(OUTDIR)}.obj: $(CC) $(CFLAGS) /c $< $(OUTDIR)/misc.obj: misc.c proc.h $(OUTDIR)/sub_proc.obj: sub_proc.c ../include/sub_proc.h ../include/w32err.h proc.h $(OUTDIR)/w32err.obj: w32err.c ../include/w32err.h remake-4.1+dbg1.3~dfsg.1/w32/subproc/build.bat000066400000000000000000000050401317072305000206510ustar00rootroot00000000000000@if "%COMPILER%" == "gcc" GoTo GCCBuild if not exist .\WinDebug\nul mkdir .\WinDebug cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c misc.c cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c sub_proc.c cl.exe /nologo /MT /W4 /GX /Z7 /YX /Od /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D _DEBUG /D _WINDOWS /FR.\WinDebug/ /Fp.\WinDebug/subproc.pch /Fo.\WinDebug/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinDebug\subproc.lib .\WinDebug/misc.obj .\WinDebug/sub_proc.obj .\WinDebug/w32err.obj if not exist .\WinRel\nul mkdir .\WinRel cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c misc.c cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c sub_proc.c cl.exe /nologo /MT /W4 /GX /YX /O2 /I .. /I . /I ../include /I ../.. /D WIN32 /D WINDOWS32 /D NDEBUG /D _WINDOWS /FR.\WinRel/ /Fp.\WinRel/subproc.pch /Fo.\WinRel/ /c w32err.c lib.exe /NOLOGO /OUT:.\WinRel\subproc.lib .\WinRel/misc.obj .\WinRel/sub_proc.obj .\WinRel/w32err.obj GoTo BuildEnd :GCCBuild gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c misc.c -o ../../w32_misc.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c sub_proc.c -o ../../sub_proc.o gcc -mthreads -Wall -gdwarf-2 -g3 %OPT% -I.. -I. -I../include -I../.. -DWINDOWS32 -c w32err.c -o ../../w32err.o :BuildEnd @echo off rem Copyright (C) 1996-2014 Free Software Foundation, Inc. rem This file is part of GNU Make. rem rem GNU Make is free software; you can redistribute it and/or modify it under rem the terms of the GNU General Public License as published by the Free rem Software Foundation; either version 3 of the License, or (at your option) rem any later version. rem rem GNU Make is distributed in the hope that it will be useful, but WITHOUT rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for. rem more details. rem rem You should have received a copy of the GNU General Public License along rem with this program. If not, see . remake-4.1+dbg1.3~dfsg.1/w32/subproc/misc.c000066400000000000000000000045341317072305000201700ustar00rootroot00000000000000/* Process handling for Windows Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 #include #include #include #include "proc.h" /* * Description: Convert a NULL string terminated UNIX environment block to * an environment block suitable for a windows32 system call * * Returns: TRUE= success, FALSE=fail * * Notes/Dependencies: the environment block is sorted in case-insensitive * order, is double-null terminated, and is a char *, not a char ** */ int _cdecl compare(const void *a1, const void *a2) { return _stricoll(*((char**)a1),*((char**)a2)); } bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed) { char **tmp; int size_needed; int arrcnt; char *ptr; arrcnt = 0; while (arr[arrcnt]) { arrcnt++; } tmp = (char**) calloc(arrcnt + 1, sizeof(char *)); if (!tmp) { return FALSE; } arrcnt = 0; size_needed = *envsize_needed = 0; while (arr[arrcnt]) { tmp[arrcnt] = arr[arrcnt]; size_needed += strlen(arr[arrcnt]) + 1; arrcnt++; } size_needed++; *envsize_needed = size_needed; qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare); ptr = *envblk_out = calloc(size_needed, 1); if (!ptr) { free(tmp); return FALSE; } arrcnt = 0; while (tmp[arrcnt]) { strcpy(ptr, tmp[arrcnt]); ptr += strlen(tmp[arrcnt]) + 1; arrcnt++; } free(tmp); return TRUE; } remake-4.1+dbg1.3~dfsg.1/w32/subproc/proc.h000066400000000000000000000017211317072305000202000ustar00rootroot00000000000000/* Definitions for Windows Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 _PROC_H #define _PROC_H typedef int bool_t; #define E_SCALL 101 #define E_IO 102 #define E_NO_MEM 103 #define E_FORK 104 extern bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed); #endif remake-4.1+dbg1.3~dfsg.1/w32/subproc/sub_proc.c000066400000000000000000001442771317072305000210620ustar00rootroot00000000000000/* Process handling for Windows. Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 #include #include /* for _get_osfhandle */ #ifdef _MSC_VER # include /* for intptr_t */ #else # include #endif #include #include /* for msvc _beginthreadex, _endthreadex */ #include #include #include "makeint.h" #include "filedef.h" #include "variable.h" #include "sub_proc.h" #include "proc.h" #include "w32err.h" #include "debug.h" static char *make_command_line(char *shell_name, char *exec_path, char **argv); typedef struct sub_process_t { intptr_t sv_stdin[2]; intptr_t sv_stdout[2]; intptr_t sv_stderr[2]; int using_pipes; char *inp; DWORD incnt; char * volatile outp; volatile DWORD outcnt; char * volatile errp; volatile DWORD errcnt; pid_t pid; int exit_code; int signal; long last_err; long lerrno; } sub_process; /* keep track of children so we can implement a waitpid-like routine */ static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS]; static int proc_index = 0; static int fake_exits_pending = 0; /* Windows jobserver implementation variables */ static char jobserver_semaphore_name[MAX_PATH + 1]; static HANDLE jobserver_semaphore = NULL; /* Open existing jobserver semaphore */ int open_jobserver_semaphore(const char* name) { jobserver_semaphore = OpenSemaphore( SEMAPHORE_ALL_ACCESS, // Semaphore access setting FALSE, // Child processes DON'T inherit name); // Semaphore name if (jobserver_semaphore == NULL) return 0; return 1; } /* Create new jobserver semaphore */ int create_jobserver_semaphore(int tokens) { sprintf(jobserver_semaphore_name, "gmake_semaphore_%d", _getpid()); jobserver_semaphore = CreateSemaphore( NULL, // Use default security descriptor tokens, // Initial count tokens, // Maximum count jobserver_semaphore_name); // Semaphore name if (jobserver_semaphore == NULL) return 0; return 1; } /* Close jobserver semaphore */ void free_jobserver_semaphore() { if (jobserver_semaphore != NULL) { CloseHandle(jobserver_semaphore); jobserver_semaphore = NULL; } } /* Decrement semaphore count */ int acquire_jobserver_semaphore() { DWORD dwEvent = WaitForSingleObject( jobserver_semaphore, // Handle to semaphore 0); // DON'T wait on semaphore return (dwEvent == WAIT_OBJECT_0); } /* Increment semaphore count */ int release_jobserver_semaphore() { BOOL bResult = ReleaseSemaphore( jobserver_semaphore, // handle to semaphore 1, // increase count by one NULL); // not interested in previous count return (bResult); } int has_jobserver_semaphore() { return (jobserver_semaphore != NULL); } char* get_jobserver_semaphore_name() { return (jobserver_semaphore_name); } /* Wait for either the jobserver semaphore to become signalled or one of our * child processes to terminate. */ int wait_for_semaphore_or_child_process() { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; DWORD dwHandleCount = 1; DWORD dwEvent; int i; /* Add jobserver semaphore to first slot. */ handles[0] = jobserver_semaphore; /* Build array of handles to wait for */ for (i = 0; i < proc_index; i++) { /* Don't wait on child processes that have already finished */ if (fake_exits_pending && proc_array[i]->exit_code) continue; handles[dwHandleCount++] = (HANDLE) proc_array[i]->pid; } dwEvent = WaitForMultipleObjects( dwHandleCount, // number of objects in array handles, // array of objects FALSE, // wait for any object INFINITE); // wait until object is signalled switch(dwEvent) { case WAIT_FAILED: return -1; case WAIT_OBJECT_0: /* Indicate that the semaphore was signalled */ return 1; default: /* Assume that one or more of the child processes terminated. */ return 0; } } /* * When a process has been waited for, adjust the wait state * array so that we don't wait for it again */ static void process_adjust_wait_state(sub_process* pproc) { int i; if (!proc_index) return; for (i = 0; i < proc_index; i++) if (proc_array[i]->pid == pproc->pid) break; if (i < proc_index) { proc_index--; if (i != proc_index) memmove(&proc_array[i], &proc_array[i+1], (proc_index-i) * sizeof(sub_process*)); proc_array[proc_index] = NULL; } } /* * Waits for any of the registered child processes to finish. */ static sub_process * process_wait_for_any_private(int block, DWORD* pdwWaitStatus) { HANDLE handles[MAXIMUM_WAIT_OBJECTS]; DWORD retval, which; int i; if (!proc_index) return NULL; /* build array of handles to wait for */ for (i = 0; i < proc_index; i++) { handles[i] = (HANDLE) proc_array[i]->pid; if (fake_exits_pending && proc_array[i]->exit_code) break; } /* wait for someone to exit */ if (!fake_exits_pending) { retval = WaitForMultipleObjects(proc_index, handles, FALSE, (block ? INFINITE : 0)); which = retval - WAIT_OBJECT_0; } else { fake_exits_pending--; retval = !WAIT_FAILED; which = i; } /* If the pointer is not NULL, set the wait status result variable. */ if (pdwWaitStatus) *pdwWaitStatus = retval; /* return pointer to process */ if ((retval == WAIT_TIMEOUT) || (retval == WAIT_FAILED)) { return NULL; } else { sub_process* pproc = proc_array[which]; process_adjust_wait_state(pproc); return pproc; } } /* * Terminate a process. */ BOOL process_kill(HANDLE proc, int signal) { sub_process* pproc = (sub_process*) proc; pproc->signal = signal; return (TerminateProcess((HANDLE) pproc->pid, signal)); } /* * Use this function to register processes you wish to wait for by * calling process_file_io(NULL) or process_wait_any(). This must be done * because it is possible for callers of this library to reuse the same * handle for multiple processes launches :-( */ void process_register(HANDLE proc) { if (proc_index < MAXIMUM_WAIT_OBJECTS) proc_array[proc_index++] = (sub_process *) proc; } /* * Return the number of processes that we are still waiting for. */ int process_used_slots(void) { return proc_index; } /* * Public function which works kind of like waitpid(). Wait for any * of the children to die and return results. To call this function, * you must do 1 of things: * * x = process_easy(...); * * or * * x = process_init_fd(); * process_register(x); * * or * * x = process_init(); * process_register(x); * * You must NOT then call process_pipe_io() because this function is * not capable of handling automatic notification of any child * death. */ HANDLE process_wait_for_any(int block, DWORD* pdwWaitStatus) { sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus); if (!pproc) return NULL; else { /* * Ouch! can't tell caller if this fails directly. Caller * will have to use process_last_err() */ (void) process_file_io(pproc); return ((HANDLE) pproc); } } long process_signal(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return 0; return (((sub_process *)proc)->signal); } long process_last_err(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; return (((sub_process *)proc)->last_err); } long process_exit_code(HANDLE proc) { if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE; return (((sub_process *)proc)->exit_code); } void process_noinherit(int fd) { HANDLE fh = (HANDLE)_get_osfhandle(fd); if (fh && fh != INVALID_HANDLE_VALUE) SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0); } /* 2006-02: All the following functions are currently unused. All of them would crash gmake if called with argument INVALID_HANDLE_VALUE. Hence whoever wants to use one of this functions must invent and implement a reasonable error handling for this function. char * process_outbuf(HANDLE proc) { return (((sub_process *)proc)->outp); } char * process_errbuf(HANDLE proc) { return (((sub_process *)proc)->errp); } int process_outcnt(HANDLE proc) { return (((sub_process *)proc)->outcnt); } int process_errcnt(HANDLE proc) { return (((sub_process *)proc)->errcnt); } void process_pipes(HANDLE proc, int pipes[3]) { pipes[0] = ((sub_process *)proc)->sv_stdin[0]; pipes[1] = ((sub_process *)proc)->sv_stdout[0]; pipes[2] = ((sub_process *)proc)->sv_stderr[0]; return; } */ HANDLE process_init() { sub_process *pproc; /* * open file descriptors for attaching stdin/stdout/sterr */ HANDLE stdin_pipes[2]; HANDLE stdout_pipes[2]; HANDLE stderr_pipes[2]; SECURITY_ATTRIBUTES inherit; BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; pproc = malloc(sizeof(*pproc)); memset(pproc, 0, sizeof(*pproc)); /* We can't use NULL for lpSecurityDescriptor because that uses the default security descriptor of the calling process. Instead we use a security descriptor with no DACL. This allows nonrestricted access to the associated objects. */ if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd), SECURITY_DESCRIPTOR_REVISION)) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } inherit.nLength = sizeof(inherit); inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd); inherit.bInheritHandle = TRUE; // By convention, parent gets pipe[0], and child gets pipe[1] // This means the READ side of stdin pipe goes into pipe[1] // and the WRITE side of the stdout and stderr pipes go into pipe[1] if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE || CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE || CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } // // Mark the parent sides of the pipes as non-inheritable // if (SetHandleInformation(stdin_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stdout_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE || SetHandleInformation(stderr_pipes[0], HANDLE_FLAG_INHERIT, 0) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; return((HANDLE)pproc); } pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; pproc->using_pipes = 1; pproc->lerrno = 0; return((HANDLE)pproc); } HANDLE process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) { sub_process *pproc; pproc = malloc(sizeof(*pproc)); if (pproc) { memset(pproc, 0, sizeof(*pproc)); /* * Just pass the provided file handles to the 'child * side' of the pipe, bypassing pipes altogether. */ pproc->sv_stdin[1] = (intptr_t) stdinh; pproc->sv_stdout[1] = (intptr_t) stdouth; pproc->sv_stderr[1] = (intptr_t) stderrh; pproc->last_err = pproc->lerrno = 0; } return((HANDLE)pproc); } static HANDLE find_file(const char *exec_path, const char *path_var, char *full_fname, DWORD full_len) { HANDLE exec_handle; char *fname; char *ext; DWORD req_len; int i; static const char *extensions[] = /* Should .com come before no-extension case? */ { ".exe", ".cmd", ".bat", "", ".com", NULL }; fname = xmalloc(strlen(exec_path) + 5); strcpy(fname, exec_path); ext = fname + strlen(fname); for (i = 0; extensions[i]; i++) { strcpy(ext, extensions[i]); if (((req_len = SearchPath (path_var, fname, NULL, full_len, full_fname, NULL)) > 0 /* For compatibility with previous code, which used OpenFile, and with Windows operation in general, also look in various default locations, such as Windows directory and Windows System directory. Warning: this also searches PATH in the Make's environment, which might not be what the Makefile wants, but it seems to be OK as a fallback, after the previous SearchPath failed to find on child's PATH. */ || (req_len = SearchPath (NULL, fname, NULL, full_len, full_fname, NULL)) > 0) && req_len <= full_len && (exec_handle = CreateFile(full_fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { free(fname); return(exec_handle); } } free(fname); return INVALID_HANDLE_VALUE; } /* * Return non-zero of FNAME specifies a batch file and its name * includes embedded whitespace. */ static int batch_file_with_spaces(const char *fname) { size_t fnlen = strlen(fname); return (fnlen > 4 && (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0 || _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0) /* The set of characters in the 2nd arg to strpbrk should be the same one used by make_command_line below to decide whether an argv[] element needs quoting. */ && strpbrk(fname, " \t") != NULL); } /* * Description: Create the child process to be helped * * Returns: success <=> 0 * * Notes/Dependencies: */ long process_begin( HANDLE proc, char **argv, char **envp, char *exec_path, char *as_user) { sub_process *pproc = (sub_process *)proc; char *shell_name = 0; int file_not_found=0; HANDLE exec_handle; char exec_fname[MAX_PATH]; const char *path_var = NULL; char **ep; char buf[MAX_PATH]; DWORD bytes_returned; DWORD flags; char *command_line; STARTUPINFO startInfo; PROCESS_INFORMATION procInfo; char *envblk=NULL; int envsize_needed = 0; int pass_null_exec_path = 0; /* * Shell script detection... if the exec_path starts with #! then * we want to exec shell-script-name exec-path, not just exec-path * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not * hard-code the path to the shell or perl or whatever: Instead, we * assume it's in the path somewhere (generally, the NT tools * bin directory) */ /* Use the Makefile's value of PATH to look for the program to execute, because it could be different from Make's PATH (e.g., if the target sets its own value. */ if (envp) for (ep = envp; *ep; ep++) { if (strncmp (*ep, "PATH=", 5) == 0 || strncmp (*ep, "Path=", 5) == 0) { path_var = *ep + 5; break; } } exec_handle = find_file(exec_path, path_var, exec_fname, sizeof(exec_fname)); /* * If we couldn't open the file, just assume that Windows will be * somehow able to find and execute it. If the first character * of the command is '/', assume they set SHELL to a Unixy shell * that have some magic mounts known only to it, and run the whole * command via $SHELL -c "COMMAND" instead. */ if (exec_handle == INVALID_HANDLE_VALUE) { if (exec_path[0] == '/') { char *new_argv0; char **argvi = argv; int arglen = 0; strcpy(buf, variable_expand ("$(SHELL)")); shell_name = &buf[0]; strcpy(exec_fname, "-c"); /* Construct a single command string in argv[0]. */ while (*argvi) { arglen += strlen(*argvi) + 1; argvi++; } new_argv0 = xmalloc(arglen + 1); new_argv0[0] = '\0'; for (argvi = argv; *argvi; argvi++) { strcat(new_argv0, *argvi); strcat(new_argv0, " "); } /* Remove the extra blank at the end. */ new_argv0[arglen-1] = '\0'; free(argv[0]); argv[0] = new_argv0; argv[1] = NULL; } else file_not_found++; } else { /* Attempt to read the first line of the file */ if (ReadFile( exec_handle, buf, sizeof(buf) - 1, /* leave room for trailing NULL */ &bytes_returned, 0) == FALSE || bytes_returned < 2) { pproc->last_err = GetLastError(); pproc->lerrno = E_IO; CloseHandle(exec_handle); return(-1); } if (buf[0] == '#' && buf[1] == '!') { /* * This is a shell script... Change the command line from * exec_path args to shell_name exec_path args */ char *p; /* Make sure buf is NULL terminated */ buf[bytes_returned] = 0; /* * Depending on the file system type, etc. the first line * of the shell script may end with newline or newline-carriage-return * Whatever it ends with, cut it off. */ p= strchr(buf, '\n'); if (p) *p = 0; p = strchr(buf, '\r'); if (p) *p = 0; /* * Find base name of shell */ shell_name = strrchr( buf, '/'); if (shell_name) { shell_name++; } else { shell_name = &buf[2];/* skipping "#!" */ } } CloseHandle(exec_handle); } flags = 0; if (file_not_found) command_line = make_command_line( shell_name, exec_path, argv); else { /* If exec_fname includes whitespace, CreateProcess behaves erratically and unreliably, and often fails if argv[0] also includes whitespace (and thus will be quoted by make_command_line below). So in that case, we don't pass exec_fname as the 1st arg to CreateProcess, but instead replace argv[0] with exec_fname (to keep its leading directories and extension as found by find_file), and pass NULL to CreateProcess as its 1st arg. This works around the bugs in CreateProcess, which are probably caused by its passing the command to cmd.exe with some incorrect quoting. */ if (!shell_name && batch_file_with_spaces(exec_fname) && _stricmp(exec_path, argv[0]) == 0) { pass_null_exec_path = 1; free (argv[0]); argv[0] = xstrdup(exec_fname); } command_line = make_command_line( shell_name, exec_fname, argv); } if ( command_line == NULL ) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; return(-1); } if (envp) { if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) { pproc->last_err = 0; pproc->lerrno = E_NO_MEM; free( command_line ); if (pproc->last_err == ERROR_INVALID_PARAMETER && envsize_needed > 32*1024) { fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n", envsize_needed); } return(-1); } } if (shell_name || file_not_found || pass_null_exec_path) { exec_path = 0; /* Search for the program in %Path% */ } else { exec_path = exec_fname; } /* * Set up inherited stdin, stdout, stderr for child */ GetStartupInfo(&startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES; startInfo.lpReserved = 0; startInfo.cbReserved2 = 0; startInfo.lpReserved2 = 0; startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; if (as_user) { free(envblk); return -1; } else { DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", exec_path ? exec_path : "NULL", command_line ? command_line : "NULL")); if (CreateProcess( exec_path, command_line, NULL, 0, /* default security attributes for thread */ TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ flags, envblk, 0, /* default starting directory */ &startInfo, &procInfo) == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_FORK; fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", exec_path ? exec_path : "NULL", command_line); free(envblk); free( command_line ); return(-1); } } pproc->pid = (pid_t)procInfo.hProcess; /* Close the thread handle -- we'll just watch the process */ CloseHandle(procInfo.hThread); /* Close the halves of the pipes we don't need */ if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdin[1]); if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdout[1]); if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stderr[1]); pproc->sv_stdin[1] = 0; pproc->sv_stdout[1] = 0; pproc->sv_stderr[1] = 0; free( command_line ); free(envblk); pproc->lerrno=0; return 0; } #if 0 /* unused */ static DWORD proc_stdin_thread(sub_process *pproc) { DWORD in_done; for (;;) { if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt, &in_done, NULL) == FALSE) _endthreadex(0); // This if should never be true for anonymous pipes, but gives // us a chance to change I/O mechanisms later if (in_done < pproc->incnt) { pproc->incnt -= in_done; pproc->inp += in_done; } else { _endthreadex(0); } } return 0; // for compiler warnings only.. not reached } static DWORD proc_stdout_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->outp = malloc(bufsize); if (pproc->outp == NULL) _endthreadex(0); pproc->outcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) == FALSE) { /* map_windows32_error_to_string(GetLastError());*/ _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->outcnt + nread > bufsize) { bufsize += nread + 512; pproc->outp = realloc(pproc->outp, bufsize); if (pproc->outp == NULL) { pproc->outcnt = 0; _endthreadex(0); } } pproc->outp[pproc->outcnt++] = c; } return 0; } static DWORD proc_stderr_thread(sub_process *pproc) { DWORD bufsize = 1024; char c; DWORD nread; pproc->errp = malloc(bufsize); if (pproc->errp == NULL) _endthreadex(0); pproc->errcnt = 0; for (;;) { if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) { map_windows32_error_to_string(GetLastError()); _endthreadex(0); } if (nread == 0) _endthreadex(0); if (pproc->errcnt + nread > bufsize) { bufsize += nread + 512; pproc->errp = realloc(pproc->errp, bufsize); if (pproc->errp == NULL) { pproc->errcnt = 0; _endthreadex(0); } } pproc->errp[pproc->errcnt++] = c; } return 0; } /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_pipe_io( HANDLE proc, char *stdin_data, int stdin_data_len) { sub_process *pproc = (sub_process *)proc; bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE; HANDLE childhand = (HANDLE) pproc->pid; HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL; unsigned int dwStdin, dwStdout, dwStderr; HANDLE wait_list[4]; DWORD wait_count; DWORD wait_return; HANDLE ready_hand; bool_t child_dead = FALSE; BOOL GetExitCodeResult; /* * Create stdin thread, if needed */ pproc->inp = stdin_data; pproc->incnt = stdin_data_len; if (!pproc->inp) { stdin_eof = TRUE; CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } else { tStdin = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdin_thread, pproc, 0, &dwStdin); if (tStdin == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } } /* * Assume child will produce stdout and stderr */ tStdout = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0, &dwStdout); tStderr = (HANDLE) _beginthreadex( 0, 1024, (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0, &dwStderr); if (tStdout == 0 || tStderr == 0) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } /* * Wait for all I/O to finish and for the child process to exit */ while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) { wait_count = 0; if (!stdin_eof) { wait_list[wait_count++] = tStdin; } if (!stdout_eof) { wait_list[wait_count++] = tStdout; } if (!stderr_eof) { wait_list[wait_count++] = tStderr; } if (!child_dead) { wait_list[wait_count++] = childhand; } wait_return = WaitForMultipleObjects(wait_count, wait_list, FALSE, /* don't wait for all: one ready will do */ child_dead? 1000 :INFINITE); /* after the child dies, subthreads have one second to collect all remaining output */ if (wait_return == WAIT_FAILED) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } ready_hand = wait_list[wait_return - WAIT_OBJECT_0]; if (ready_hand == tStdin) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; CloseHandle(tStdin); tStdin = 0; stdin_eof = TRUE; } else if (ready_hand == tStdout) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; CloseHandle(tStdout); tStdout = 0; stdout_eof = TRUE; } else if (ready_hand == tStderr) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; CloseHandle(tStderr); tStderr = 0; stderr_eof = TRUE; } else if (ready_hand == childhand) { DWORD ierr; GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done; } child_dead = TRUE; } else { /* ?? Got back a handle we didn't query ?? */ pproc->last_err = 0; pproc->lerrno = E_FAIL; goto done; } } done: if (tStdin != 0) CloseHandle(tStdin); if (tStdout != 0) CloseHandle(tStdout); if (tStderr != 0) CloseHandle(tStderr); if (pproc->lerrno) return(-1); else return(0); } #endif /* unused */ /* * Purpose: collects output from child process and returns results * * Description: * * Returns: * * Notes/Dependencies: */ long process_file_io( HANDLE proc) { sub_process *pproc; HANDLE childhand; DWORD wait_return; BOOL GetExitCodeResult; DWORD ierr; if (proc == NULL) pproc = process_wait_for_any_private(1, 0); else pproc = (sub_process *)proc; /* some sort of internal error */ if (!pproc) return -1; childhand = (HANDLE) pproc->pid; /* * This function is poorly named, and could also be used just to wait * for child death if you're doing your own pipe I/O. If that is * the case, close the pipe handles here. */ if (pproc->sv_stdin[0]) { CloseHandle((HANDLE)pproc->sv_stdin[0]); pproc->sv_stdin[0] = 0; } if (pproc->sv_stdout[0]) { CloseHandle((HANDLE)pproc->sv_stdout[0]); pproc->sv_stdout[0] = 0; } if (pproc->sv_stderr[0]) { CloseHandle((HANDLE)pproc->sv_stderr[0]); pproc->sv_stderr[0] = 0; } /* * Wait for the child process to exit */ wait_return = WaitForSingleObject(childhand, INFINITE); if (wait_return != WAIT_OBJECT_0) { /* map_windows32_error_to_string(GetLastError());*/ pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; goto done2; } GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); if (ierr == CONTROL_C_EXIT) { pproc->signal = SIGINT; } else { pproc->exit_code = ierr; } if (GetExitCodeResult == FALSE) { pproc->last_err = GetLastError(); pproc->lerrno = E_SCALL; } done2: if (pproc->lerrno) return(-1); else return(0); } /* * Description: Clean up any leftover handles, etc. It is up to the * caller to manage and free the input, output, and stderr buffers. */ void process_cleanup( HANDLE proc) { sub_process *pproc = (sub_process *)proc; int i; if (pproc->using_pipes) { for (i= 0; i <= 1; i++) { if ((HANDLE)pproc->sv_stdin[i] && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdin[i]); if ((HANDLE)pproc->sv_stdout[i] && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stdout[i]); if ((HANDLE)pproc->sv_stderr[i] && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE) CloseHandle((HANDLE)pproc->sv_stderr[i]); } } if ((HANDLE)pproc->pid) CloseHandle((HANDLE)pproc->pid); free(pproc); } /* * Description: * Create a command line buffer to pass to CreateProcess * * Returns: the buffer or NULL for failure * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... * Otherwise: argv[0] argv[1] argv[2] ... * * Notes/Dependencies: * CreateProcess does not take an argv, so this command creates a * command line for the executable. */ static char * make_command_line( char *shell_name, char *full_exec_path, char **argv) { int argc = 0; char** argvi; int* enclose_in_quotes = NULL; int* enclose_in_quotes_i; unsigned int bytes_required = 0; char* command_line; char* command_line_i; int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */ int have_sh = 0; /* HAVE_CYGWIN_SHELL */ #ifdef HAVE_CYGWIN_SHELL have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe")); cygwin_mode = 1; #endif if (shell_name && full_exec_path) { bytes_required = strlen(shell_name) + 1 + strlen(full_exec_path); /* * Skip argv[0] if any, when shell_name is given. * The special case of "-c" in full_exec_path means * argv[0] is not the shell name, but the command string * to pass to the shell. */ if (*argv && strcmp(full_exec_path, "-c")) argv++; /* * Add one for the intervening space. */ if (*argv) bytes_required++; } argvi = argv; while (*(argvi++)) argc++; if (argc) { enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); if (!enclose_in_quotes) { return NULL; } } /* We have to make one pass through each argv[i] to see if we need * to enclose it in ", so we might as well figure out how much * memory we'll need on the same pass. */ argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; /* * We have to enclose empty arguments in ". */ if (!(*p)) *enclose_in_quotes_i = 1; while(*p) { switch (*p) { case '\"': /* * We have to insert a backslash for each " * and each \ that precedes the ". */ bytes_required += (backslash_count + 1); backslash_count = 0; break; #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) case '\\': backslash_count++; break; #endif /* * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so * that argv in always equals argv out. This was removed. Say you have * such a program named glob.exe. You enter * glob '*' * at the sh command prompt. Obviously the intent is to make glob do the * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', * then the command line that glob would see would be * glob "*" * and the _setargv in SETARGV.OBJ would _not_ expand the *. */ case ' ': case '\t': *enclose_in_quotes_i = 1; /* fall through */ default: backslash_count = 0; break; } /* * Add one for each character in argv[i]. */ bytes_required++; p++; } if (*enclose_in_quotes_i) { /* * Add one for each enclosing ", * and one for each \ that precedes the * closing ". */ bytes_required += (backslash_count + 2); } /* * Add one for the intervening space. */ if (*(++argvi)) bytes_required++; enclose_in_quotes_i++; } /* * Add one for the terminating NULL. */ bytes_required++; command_line = (char*) malloc(bytes_required); if (!command_line) { free(enclose_in_quotes); return NULL; } command_line_i = command_line; if (shell_name && full_exec_path) { while(*shell_name) { *(command_line_i++) = *(shell_name++); } *(command_line_i++) = ' '; while(*full_exec_path) { *(command_line_i++) = *(full_exec_path++); } if (*argv) { *(command_line_i++) = ' '; } } argvi = argv; enclose_in_quotes_i = enclose_in_quotes; while(*argvi) { char* p = *argvi; unsigned int backslash_count = 0; if (*enclose_in_quotes_i) { *(command_line_i++) = '\"'; } while(*p) { if (*p == '\"') { if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */ /* instead of a \", cygwin likes "" */ *(command_line_i++) = '\"'; } else { /* * We have to insert a backslash for the " * and each \ that precedes the ". */ backslash_count++; while(backslash_count) { *(command_line_i++) = '\\'; backslash_count--; }; } #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) } else if (*p == '\\') { backslash_count++; } else { backslash_count = 0; #endif } /* * Copy the character. */ *(command_line_i++) = *(p++); } if (*enclose_in_quotes_i) { #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) /* * Add one \ for each \ that precedes the * closing ". */ while(backslash_count--) { *(command_line_i++) = '\\'; }; #endif *(command_line_i++) = '\"'; } /* * Append an intervening space. */ if (*(++argvi)) { *(command_line_i++) = ' '; } enclose_in_quotes_i++; } /* * Append the terminating NULL. */ *command_line_i = '\0'; free(enclose_in_quotes); return command_line; } /* * Description: Given an argv and optional envp, launch the process * using the default stdin, stdout, and stderr handles. * Also, register process so that process_wait_for_any_private() * can be used via process_file_io(NULL) or * process_wait_for_any(). * * Returns: * * Notes/Dependencies: */ HANDLE process_easy( char **argv, char **envp, int outfd, int errfd) { HANDLE hIn = INVALID_HANDLE_VALUE; HANDLE hOut = INVALID_HANDLE_VALUE; HANDLE hErr = INVALID_HANDLE_VALUE; HANDLE hProcess, tmpIn, tmpOut, tmpErr; DWORD e; if (proc_index >= MAXIMUM_WAIT_OBJECTS) { DB (DB_JOBS, ("process_easy: All process slots used up\n")); return INVALID_HANDLE_VALUE; } /* Standard handles returned by GetStdHandle can be NULL or INVALID_HANDLE_VALUE if the parent process closed them. If that happens, we open the null device and pass its handle to CreateProcess as the corresponding handle to inherit. */ tmpIn = GetStdHandle(STD_INPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpIn, GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpIn = CreateFile("NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpIn != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpIn, GetCurrentProcess(), &hIn, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpIn); } if (hIn == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } if (outfd >= 0) tmpOut = (HANDLE)_get_osfhandle (outfd); else tmpOut = GetStdHandle (STD_OUTPUT_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpOut, GetCurrentProcess(), &hOut, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpOut = CreateFile("NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpOut != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpOut, GetCurrentProcess(), &hOut, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpOut); } if (hOut == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } if (errfd >= 0) tmpErr = (HANDLE)_get_osfhandle (errfd); else tmpErr = GetStdHandle(STD_ERROR_HANDLE); if (DuplicateHandle(GetCurrentProcess(), tmpErr, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) { if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { tmpErr = CreateFile("NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (tmpErr != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), tmpErr, GetCurrentProcess(), &hErr, 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE) CloseHandle(tmpErr); } if (hErr == INVALID_HANDLE_VALUE) { fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e); return INVALID_HANDLE_VALUE; } } hProcess = process_init_fd(hIn, hOut, hErr); if (process_begin(hProcess, argv, envp, argv[0], NULL)) { fake_exits_pending++; /* process_begin() failed: make a note of that. */ if (!((sub_process*) hProcess)->last_err) ((sub_process*) hProcess)->last_err = -1; ((sub_process*) hProcess)->exit_code = process_last_err(hProcess); /* close up unused handles */ if (hIn != INVALID_HANDLE_VALUE) CloseHandle(hIn); if (hOut != INVALID_HANDLE_VALUE) CloseHandle(hOut); if (hErr != INVALID_HANDLE_VALUE) CloseHandle(hErr); } process_register(hProcess); return hProcess; } remake-4.1+dbg1.3~dfsg.1/w32/subproc/w32err.c000066400000000000000000000060031317072305000203520ustar00rootroot00000000000000/* Error handling for Windows Copyright (C) 1996-2014 Free Software Foundation, Inc. This file is part of GNU Make. GNU Make is free software; you can 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 Make is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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 #include "makeint.h" #include "w32err.h" /* * Description: the windows32 version of perror() * * Returns: a pointer to a static error * * Notes/Dependencies: I got this from * comp.os.ms-windows.programmer.win32 */ const char * map_windows32_error_to_string (DWORD ercode) { /* * We used to have an MSVC-specific '__declspec (thread)' qualifier * here, with the following comment: * * __declspec (thread) necessary if you will use multiple threads on MSVC * * However, Make was never multithreaded on Windows (except when * Ctrl-C is hit, in which case the main thread is stopped * immediately, so it doesn't matter in this context). The functions * on sub_proc.c that started and stopped additional threads were * never used, and are now #ifdef'ed away. Until we need more than * one thread, we have no problems with the following buffer being * static. (If and when we do need it to be in thread-local storage, * the corresponding GCC qualifier is '__thread'.) */ static char szMessageBuffer[128]; /* Fill message buffer with a default message in * case FormatMessage fails */ wsprintf (szMessageBuffer, "Error %ld\n", ercode); /* * Special code for winsock error handling. */ if (ercode > WSABASEERR) { #if 0 HMODULE hModule = GetModuleHandle("wsock32"); if (hModule != NULL) { FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, hModule, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); FreeLibrary(hModule); } #else O (fatal, NILF, szMessageBuffer); #endif } else { /* * Default system message handling */ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ercode, LANG_NEUTRAL, szMessageBuffer, sizeof(szMessageBuffer), NULL); } return szMessageBuffer; }