From 36f8666256633fd78112924c86921166a53c4cc2 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Sun, 26 Sep 2010 17:02:16 +0000 Subject: [PATCH] Removed make and mkdepend source files, and removed them from the Jamfile. These are now available as OptionalPackages grouped in DevelopmentBase git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38820 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/bin/Jamfile | 2 - src/bin/make/COPYING | 340 ---- src/bin/make/Jamfile | 42 - src/bin/make/README | 189 -- src/bin/make/ar.c | 309 ---- src/bin/make/arscan.c | 842 --------- src/bin/make/commands.c | 623 ------- src/bin/make/commands.h | 42 - src/bin/make/config.h | 401 ---- src/bin/make/debug.h | 38 - src/bin/make/default.c | 594 ------ src/bin/make/dep.h | 85 - src/bin/make/dir.c | 1216 ------------- src/bin/make/expand.c | 584 ------ src/bin/make/file.c | 1051 ----------- src/bin/make/filedef.h | 202 -- src/bin/make/function.c | 2340 ------------------------ src/bin/make/getloadavg.c | 1030 ----------- src/bin/make/getopt.c | 1030 ----------- src/bin/make/getopt.h | 133 -- src/bin/make/getopt1.c | 180 -- src/bin/make/gettext.h | 58 - src/bin/make/glob/COPYING.LIB | 481 ----- src/bin/make/glob/Jamfile | 17 - src/bin/make/glob/fnmatch.c | 488 ----- src/bin/make/glob/fnmatch.h | 84 - src/bin/make/glob/glob.c | 1426 --------------- src/bin/make/glob/glob.h | 209 --- src/bin/make/hash.c | 332 ---- src/bin/make/hash.h | 233 --- src/bin/make/implicit.c | 982 ---------- src/bin/make/job.c | 3070 ------------------------------- src/bin/make/job.h | 105 -- src/bin/make/main.c | 3129 ------------------------------- src/bin/make/make.h | 611 ------- src/bin/make/make.rdef | 11 - src/bin/make/misc.c | 897 --------- src/bin/make/read.c | 3138 -------------------------------- src/bin/make/remake.c | 1576 ---------------- src/bin/make/remote-stub.c | 101 - src/bin/make/rule.c | 586 ------ src/bin/make/rule.h | 60 - src/bin/make/signame.c | 255 --- src/bin/make/strcache.c | 216 --- src/bin/make/variable.c | 1508 --------------- src/bin/make/variable.h | 200 -- src/bin/make/version.c | 35 - src/bin/make/vpath.c | 605 ------ src/bin/mkdepend/HISTORY | 110 -- src/bin/mkdepend/Jamfile | 14 - src/bin/mkdepend/LICENSE | 28 - src/bin/mkdepend/MkDepend.doc | 622 ------- src/bin/mkdepend/MkDepend.txt | 21 - src/bin/mkdepend/args.c | 670 ------- src/bin/mkdepend/args.h | 61 - src/bin/mkdepend/getargs.c | 326 ---- src/bin/mkdepend/getargs.h | 37 - src/bin/mkdepend/main.c | 1503 --------------- src/bin/mkdepend/main.h | 37 - src/bin/mkdepend/mkdepend.rdef | 11 - src/bin/mkdepend/nodes.c | 587 ------ src/bin/mkdepend/nodes.h | 95 - src/bin/mkdepend/reader.c | 658 ------- src/bin/mkdepend/reader.h | 24 - src/bin/mkdepend/util.c | 146 -- src/bin/mkdepend/util.h | 14 - src/bin/mkdepend/version.h | 38 - 67 files changed, 36688 deletions(-) delete mode 100644 src/bin/make/COPYING delete mode 100644 src/bin/make/Jamfile delete mode 100644 src/bin/make/README delete mode 100644 src/bin/make/ar.c delete mode 100644 src/bin/make/arscan.c delete mode 100644 src/bin/make/commands.c delete mode 100644 src/bin/make/commands.h delete mode 100644 src/bin/make/config.h delete mode 100644 src/bin/make/debug.h delete mode 100644 src/bin/make/default.c delete mode 100644 src/bin/make/dep.h delete mode 100644 src/bin/make/dir.c delete mode 100644 src/bin/make/expand.c delete mode 100644 src/bin/make/file.c delete mode 100644 src/bin/make/filedef.h delete mode 100644 src/bin/make/function.c delete mode 100644 src/bin/make/getloadavg.c delete mode 100644 src/bin/make/getopt.c delete mode 100644 src/bin/make/getopt.h delete mode 100644 src/bin/make/getopt1.c delete mode 100644 src/bin/make/gettext.h delete mode 100644 src/bin/make/glob/COPYING.LIB delete mode 100644 src/bin/make/glob/Jamfile delete mode 100644 src/bin/make/glob/fnmatch.c delete mode 100644 src/bin/make/glob/fnmatch.h delete mode 100644 src/bin/make/glob/glob.c delete mode 100644 src/bin/make/glob/glob.h delete mode 100644 src/bin/make/hash.c delete mode 100644 src/bin/make/hash.h delete mode 100644 src/bin/make/implicit.c delete mode 100644 src/bin/make/job.c delete mode 100644 src/bin/make/job.h delete mode 100644 src/bin/make/main.c delete mode 100644 src/bin/make/make.h delete mode 100644 src/bin/make/make.rdef delete mode 100644 src/bin/make/misc.c delete mode 100644 src/bin/make/read.c delete mode 100644 src/bin/make/remake.c delete mode 100644 src/bin/make/remote-stub.c delete mode 100644 src/bin/make/rule.c delete mode 100644 src/bin/make/rule.h delete mode 100644 src/bin/make/signame.c delete mode 100644 src/bin/make/strcache.c delete mode 100644 src/bin/make/variable.c delete mode 100644 src/bin/make/variable.h delete mode 100644 src/bin/make/version.c delete mode 100644 src/bin/make/vpath.c delete mode 100644 src/bin/mkdepend/HISTORY delete mode 100644 src/bin/mkdepend/Jamfile delete mode 100644 src/bin/mkdepend/LICENSE delete mode 100644 src/bin/mkdepend/MkDepend.doc delete mode 100644 src/bin/mkdepend/MkDepend.txt delete mode 100644 src/bin/mkdepend/args.c delete mode 100644 src/bin/mkdepend/args.h delete mode 100644 src/bin/mkdepend/getargs.c delete mode 100644 src/bin/mkdepend/getargs.h delete mode 100644 src/bin/mkdepend/main.c delete mode 100644 src/bin/mkdepend/main.h delete mode 100644 src/bin/mkdepend/mkdepend.rdef delete mode 100644 src/bin/mkdepend/nodes.c delete mode 100644 src/bin/mkdepend/nodes.h delete mode 100644 src/bin/mkdepend/reader.c delete mode 100644 src/bin/mkdepend/reader.h delete mode 100644 src/bin/mkdepend/util.c delete mode 100644 src/bin/mkdepend/util.h delete mode 100644 src/bin/mkdepend/version.h diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 524441142f..2baabec525 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -242,10 +242,8 @@ SubInclude HAIKU_TOP src bin keymap ; SubInclude HAIKU_TOP src bin less ; SubInclude HAIKU_TOP src bin listdev ; SubInclude HAIKU_TOP src bin locale ; -SubInclude HAIKU_TOP src bin make ; SubInclude HAIKU_TOP src bin makebootable ; #SubInclude HAIKU_TOP src bin makeudfimage ; -SubInclude HAIKU_TOP src bin mkdepend ; SubInclude HAIKU_TOP src bin mkdos ; SubInclude HAIKU_TOP src bin mkfs ; SubInclude HAIKU_TOP src bin multiuser ; diff --git a/src/bin/make/COPYING b/src/bin/make/COPYING deleted file mode 100644 index a3f6b12eec..0000000000 --- a/src/bin/make/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/src/bin/make/Jamfile b/src/bin/make/Jamfile deleted file mode 100644 index e96ff49965..0000000000 --- a/src/bin/make/Jamfile +++ /dev/null @@ -1,42 +0,0 @@ -SubDir HAIKU_TOP src bin make ; - -SetSubDirSupportedPlatformsBeOSCompatible ; - -# filter warnings we don't want here -TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS) - : -Wall -Wmissing-prototypes -Wsign-compare ] ; - -SubDirSysHdrs [ FDirName $(SUBDIR) glob ] ; -SubDirSysHdrs [ FDirName $(SUBDIR) ] ; - -SubDirCcFlags -DHAVE_CONFIG_H ; - -BinCommand make : - ar.c - arscan.c - commands.c - default.c - dir.c - expand.c - file.c - function.c - getloadavg.c - getopt.c - getopt1.c - hash.c - implicit.c - job.c - main.c - misc.c - read.c - remake.c - remote-stub.c - rule.c - signame.c - strcache.c - variable.c - version.c - vpath.c -: libglob.a : make.rdef ; - -SubInclude HAIKU_TOP src bin make glob ; diff --git a/src/bin/make/README b/src/bin/make/README deleted file mode 100644 index 14277e5ca8..0000000000 --- a/src/bin/make/README +++ /dev/null @@ -1,189 +0,0 @@ -This directory contains the 3.81 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. - - -Ports ------ - - - See README.customs for details on integrating GNU make with the - Customs distributed build environment from the Pmake distribution. - - - See readme.vms for details about GNU Make on OpenVMS. - - - See README.Amiga for details about GNU Make on AmigaDOS. - - - See README.W32 for details about GNU Make on Windows NT, 95, or 98. - - - See README.DOS for compilation instructions on MS-DOS and MS-Windows - using DJGPP tools. - - A precompiled binary of the MSDOS port of GNU Make is available as part - of DJGPP; see the WWW page http://www.delorie.com/djgpp/ for more - information. - -Please note there are two _separate_ ports of GNU make for Microsoft -systems: a native Windows tool built with (for example) MSVC or Cygwin, -and a DOS-based tool built with DJGPP. Please be sure you are looking -at the right README! - - -------------------------------------------------------------------------------- -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/src/bin/make/ar.c b/src/bin/make/ar.c deleted file mode 100644 index 4d9f1bb1dd..0000000000 --- a/src/bin/make/ar.c +++ /dev/null @@ -1,309 +0,0 @@ -/* Interface to `ar' archives for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#ifndef NO_ARCHIVES - -#include "filedef.h" -#include "dep.h" -#include - -/* Defined in arscan.c. */ -extern long int ar_scan PARAMS ((char *archive, long int (*function) (), long int arg)); -extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated)); -#ifndef VMS -extern int ar_member_touch PARAMS ((char *arname, char *memname)); -#endif - -/* Return nonzero if NAME is an archive-member reference, zero if not. - An archive-member reference is a name like `lib(member)'. - If a name like `lib((entry))' is used, a fatal error is signaled at - the attempt to use this unsupported feature. */ - -int -ar_name (char *name) -{ - char *p = strchr (name, '('); - char *end; - - if (p == 0 || p == name) - return 0; - - end = p + strlen (p) - 1; - if (*end != ')') - return 0; - - if (p[1] == '(' && end[-1] == ')') - fatal (NILF, _("attempt to use unsupported feature: `%s'"), name); - - return 1; -} - - -/* Parse the archive-member reference NAME into the archive and member names. - Put the malloc'd archive name in *ARNAME_P if ARNAME_P is non-nil; - put the malloc'd member name in *MEMNAME_P if MEMNAME_P is non-nil. */ - -void -ar_parse_name (char *name, char **arname_p, char **memname_p) -{ - char *p = strchr (name, '('), *end = name + strlen (name) - 1; - - if (arname_p != 0) - *arname_p = savestring (name, p - name); - - if (memname_p != 0) - *memname_p = savestring (p + 1, end - (p + 1)); -} - -static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos, - long int datapos, long int size, long int date, int uid, int gid, int mode, char *name)); - -/* Return the modtime of NAME. */ - -time_t -ar_member_date (char *name) -{ - char *arname; - int arname_used = 0; - char *memname; - long int val; - - 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 (arname); - arname_used = 1; - } - - if (arfile != 0) - (void) f_mtime (arfile, 0); - } - - val = ar_scan (arname, ar_member_date_1, (long int) memname); - - if (!arname_used) - free (arname); - free (memname); - - return (val <= 0 ? (time_t) -1 : (time_t) val); -} - -/* This function is called by `ar_scan' to find which member to look at. */ - -/* ARGSUSED */ -static long int -ar_member_date_1 (int desc UNUSED, 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, char *name) -{ - return ar_name_equal (name, mem, truncated) ? date : 0; -} - -/* Set the archive-member NAME's modtime to now. */ - -#ifdef VMS -int -ar_touch (char *name) -{ - error (NILF, _("touch archive member is not available on VMS")); - return -1; -} -#else -int -ar_touch (char *name) -{ - char *arname, *memname; - int arname_used = 0; - register 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 itself. */ - { - struct file *arfile; - arfile = lookup_file (arname); - if (arfile == 0) - { - arfile = enter_file (arname); - arname_used = 1; - } - - (void) f_mtime (arfile, 0); - } - - val = 1; - switch (ar_member_touch (arname, memname)) - { - case -1: - error (NILF, _("touch: Archive `%s' does not exist"), arname); - break; - case -2: - error (NILF, _("touch: `%s' is not a valid archive"), arname); - break; - case -3: - perror_with_name ("touch: ", arname); - break; - case 1: - error (NILF, - _("touch: Member `%s' does not exist in `%s'"), memname, arname); - break; - case 0: - val = 0; - break; - default: - error (NILF, - _("touch: Bad return code from ar_member_touch on `%s'"), name); - } - - if (!arname_used) - free (arname); - free (memname); - - return val; -} -#endif /* !VMS */ - -/* State of an `ar_glob' run, passed to `ar_glob_match'. */ - -struct ar_glob_state - { - char *arname; - char *pattern; - 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, 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, struct ar_glob_state *state) -{ - if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0) - { - /* We have a match. Add it to the chain. */ - struct nameseq *new = (struct nameseq *) xmalloc (state->size); - new->name = concat (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 open = 0; - - for (p = pattern; *p != '\0'; ++p) - switch (*p) - { - case '?': - case '*': - return 1; - - case '\\': - if (quote) - ++p; - break; - - case '[': - open = 1; - break; - - case ']': - if (open) - 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 (char *arname, char *member_pattern, unsigned int size) -{ - struct ar_glob_state state; - char **names; - struct nameseq *n; - unsigned int i; - - if (! glob_pattern_p (member_pattern, 1)) - return 0; - - /* Scan the archive for matches. - ar_glob_match will accumulate them in STATE.chain. */ - i = strlen (arname); - state.arname = (char *) alloca (i + 2); - bcopy (arname, state.arname, i); - state.arname[i] = '('; - state.arname[i + 1] = '\0'; - state.pattern = member_pattern; - state.size = size; - state.chain = 0; - state.n = 0; - (void) ar_scan (arname, ar_glob_match, (long int) &state); - - if (state.chain == 0) - return 0; - - /* Now put the names into a vector for sorting. */ - names = (char **) alloca (state.n * sizeof (char *)); - i = 0; - for (n = state.chain; n != 0; n = n->next) - names[i++] = n->name; - - /* Sort them alphabetically. */ - qsort ((char *) 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. */ diff --git a/src/bin/make/arscan.c b/src/bin/make/arscan.c deleted file mode 100644 index 04b2efd629..0000000000 --- a/src/bin/make/arscan.c +++ /dev/null @@ -1,842 +0,0 @@ -/* Library function for scanning an archive file. -Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#ifdef HAVE_FCNTL_H -#include -#else -#include -#endif - -#ifndef NO_ARCHIVES - -#ifdef VMS -#include -#include -#include -#include -#include -#if __DECC -#include -#include -#endif - -static void *VMS_lib_idx; - -static char *VMS_saved_memname; - -static time_t VMS_member_date; - -static long int (*VMS_function) (); - -static int -VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa) -{ - int status, i; - long int fnval; - - time_t val; - - static struct dsc$descriptor_s bufdesc = - { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; - - struct mhddef *mhd; - char filename[128]; - - bufdesc.dsc$a_pointer = filename; - bufdesc.dsc$w_length = sizeof (filename); - - status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc, - &bufdesc.dsc$w_length, 0); - if (! (status & 1)) - { - error (NILF, _("lbr$set_module failed to extract module info, status = %d"), - status); - - lbr$close (&VMS_lib_idx); - - return 0; - } - - mhd = (struct mhddef *) filename; - -#ifdef __DECC - /* John Fowler writes this is needed in his environment, - * but that decc$fix_time() isn't documented to work this way. Let me - * know if this causes problems in other VMS environments. - */ - val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600; -#endif - - for (i = 0; i < module->dsc$w_length; i++) - filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]); - - filename[i] = '\0'; - - VMS_member_date = (time_t) -1; - - fnval = - (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0, - VMS_saved_memname); - - if (fnval) - { - VMS_member_date = fnval; - return 0; - } - else - return 1; -} - -/* 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 (char *archive, long int (*function) PARAMS ((void)), long int arg) -{ - char *p; - - static struct dsc$descriptor_s libdesc = - { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; - - unsigned long func = LBR$C_READ; - unsigned long type = LBR$C_TYP_UNK; - unsigned long index = 1; - - int status; - - status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0); - - if (! (status & 1)) - { - error (NILF, _("lbr$ini_control failed with status = %d"),status); - return -2; - } - - libdesc.dsc$a_pointer = archive; - libdesc.dsc$w_length = strlen (archive); - - status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0); - - if (! (status & 1)) - { - error (NILF, _("unable to open library `%s' to lookup member `%s'"), - archive, (char *)arg); - return -1; - } - - VMS_saved_memname = (char *)arg; - - /* For comparison, delete .obj from arg name. */ - - p = strrchr (VMS_saved_memname, '.'); - if (p) - *p = '\0'; - - VMS_function = function; - - VMS_member_date = (time_t) -1; - lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0); - - /* Undo the damage. */ - if (p) - *p = '.'; - - lbr$close (&VMS_lib_idx); - - return VMS_member_date > 0 ? VMS_member_date : 0; -} - -#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(__BEOS__) && !defined(__HAIKU__)) -# include -# else - /* BeOS 5 doesn't have but has 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 -#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 -#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 (char *archive, long int (*function)(), long int arg) -{ -#ifdef AIAMAG - FL_HDR fl_header; -#ifdef AIAMAGBIG - int big_archive = 0; - FL_HDR_BIG fl_header_big; -#endif -#else - int long_name = 0; -#endif - char *namemap = 0; - register 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 || bcmp (buf, ARMAG, SARMAG)) - { - (void) close (desc); - return -2; - } - } -#else -#ifdef AIAMAG - { - register int nread = read (desc, (char *) &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 (!bcmp (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, (char *) &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 (bcmp (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 -#ifndef M_XENIX - register long int member_offset = sizeof (int); -#else /* Xenix. */ - register long int member_offset = sizeof (unsigned short int); -#endif /* Not Xenix. */ -#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. */ -#endif - long int eltsize; - 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, (char *) &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, (char *) &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, (char *) &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 - bcmp (member_header.ar_fmag, ARFMAG, 2) -# else - 1 -# endif - && -# ifdef ARFZMAG - bcmp (member_header.ar_fmag, ARFZMAG, 2) -# else - 1 -# endif - ) -#endif - ) - { - (void) close (desc); - return -2; - } - - name = namebuf; - bcopy (member_header.ar_name, 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 = (char *) alloca (namesize + 1); - nread = read (desc, name, namesize); - if (nread != namesize) - { - close (desc); - return -2; - } - name[namesize] = '\0'; - - long_name = 1; - } -#endif /* Not AIAMAG. */ - } - -#ifndef M_XENIX - sscanf (member_header.ar_mode, "%o", &eltmode); - eltsize = atol (member_header.ar_size); -#else /* Xenix. */ - eltmode = (unsigned short int) member_header.ar_mode; - eltsize = member_header.ar_size; -#endif /* Not Xenix. */ - - fnval = - (*function) (desc, name, ! long_name, member_offset, - member_offset + AR_HDR_SIZE, eltsize, -#ifndef M_XENIX - atol (member_header.ar_date), - atoi (member_header.ar_uid), - atoi (member_header.ar_gid), -#else /* Xenix. */ - member_header.ar_date, - member_header.ar_uid, - member_header.ar_gid, -#endif /* Not Xenix. */ - 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 = (char *) 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 (char *name, char *mem, int truncated) -{ - 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 */ - } -#endif /* !VMS */ - - return !strcmp (name, mem); -} - -#ifndef VMS -/* ARGSUSED */ -static long int -ar_member_pos (int desc UNUSED, 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, char *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 (char *arname, char *memname) -{ - long int pos = ar_scan (arname, ar_member_pos, (long int) 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, (char *) &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, (char *) &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 (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, (char *) &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, char *name, int truncated, - long int hdrpos, long int datapos, long int size, - long int date, int uid, int gid, int mode) -{ - 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); - return 0; -} - -#endif /* TEST. */ -#endif /* NO_ARCHIVES. */ diff --git a/src/bin/make/commands.c b/src/bin/make/commands.c deleted file mode 100644 index a0a7c5cf9d..0000000000 --- a/src/bin/make/commands.c +++ /dev/null @@ -1,623 +0,0 @@ -/* Command processing for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "dep.h" -#include "filedef.h" -#include "variable.h" -#include "job.h" -#include "commands.h" -#ifdef WINDOWS32 -#include -#include "w32err.h" -#endif - -#if VMS -# define FILE_LIST_SEPARATOR ',' -#else -# define FILE_LIST_SEPARATOR ' ' -#endif - -extern int remote_kill PARAMS ((int id, int sig)); - -#ifndef HAVE_UNISTD_H -extern int getpid (); -#endif - -/* Set FILE's automatic variables up. */ - -void -set_file_variables (struct file *file) -{ - struct dep *d; - 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; - char *p; - - p = strchr (file->name, '('); - at = (char *) alloca (p - file->name + 1); - bcopy (file->name, at, p - file->name); - at[p - file->name] = '\0'; - len = strlen (p + 1); - percent = (char *) alloca (len); - bcopy (p + 1, percent, len - 1); - percent[len - 1] = '\0'; - } - 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. */ - register struct dep *d; - 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 (".SUFFIXES")->deps; d != 0; d = d->next) - { - unsigned int slen = strlen (dep_name (d)); - if (len > slen && strneq (dep_name (d), name + (len - slen), slen)) - { - file->stem = savestring (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) - { - 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 qmark_max=0, plus_max=0, bar_max=0; - - unsigned int qmark_len, plus_len, bar_len; - char *cp; - char *caret_value; - char *qp; - char *bp; - unsigned int len; - - /* Compute first the value for $+, which is supposed to contain - duplicate dependencies as they were listed in the makefile. */ - - plus_len = 0; - for (d = file->deps; d != 0; d = d->next) - if (! d->ignore_mtime) - plus_len += strlen (dep_name (d)) + 1; - 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) - { - 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); - - bcopy (c, cp, len); - cp += len; - *cp++ = FILE_LIST_SEPARATOR; - if (! d->changed) - 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); - - /* Make sure that no dependencies are repeated. This does not - really matter for the purpose of updating targets, but it - might make some names be listed twice for $^ and $?. */ - - uniquize_deps (file->deps); - - bar_len = 0; - for (d = file->deps; d != 0; d = d->next) - if (d->ignore_mtime) - bar_len += strlen (dep_name (d)) + 1; - if (bar_len == 0) - bar_len++; - - /* 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; - - for (d = file->deps; d != 0; d = d->next) - { - 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); - - if (d->ignore_mtime) - { - bcopy (c, bp, len); - bp += len; - *bp++ = FILE_LIST_SEPARATOR; - } - else - { - bcopy (c, cp, len); - cp += len; - *cp++ = FILE_LIST_SEPARATOR; - if (d->changed) - { - bcopy (c, qp, len); - qp += len; - *qp++ = FILE_LIST_SEPARATOR; - } - } - } - - /* 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) -{ - register char *p; - 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. - Also set the corresponding CMDS->lines_flags elements, - and the CMDS->any_recurse flag. */ - - nlines = 5; - lines = (char **) xmalloc (5 * sizeof (char *)); - idx = 0; - p = cmds->commands; - while (*p != '\0') - { - 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; - register char *b; - for (b = end - 2; b >= p && *b == '\\'; --b) - backslash = !backslash; - if (backslash) - { - ++end; - goto find_end; - } - } - - if (idx == nlines) - { - nlines += 2; - lines = (char **) xrealloc ((char *) lines, - nlines * sizeof (char *)); - } - lines[idx++] = savestring (p, end - p); - p = end; - if (*p != '\0') - ++p; - } - - if (idx != nlines) - { - nlines = idx; - lines = (char **) xrealloc ((char *) lines, - nlines * sizeof (char *)); - } - - cmds->ncommand_lines = nlines; - cmds->command_lines = lines; - - cmds->any_recurse = 0; - cmds->lines_flags = (char *) xmalloc (nlines); - for (idx = 0; idx < nlines; ++idx) - { - int flags = 0; - - for (p = lines[idx]; - isblank ((unsigned char)*p) || *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; - } -} - -/* 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 (struct file *file) -{ - register 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 = 0; - notice_finished_file (file); - return; - } - - /* First set the automatic variables according to this file. */ - - initialize_file_variables (file, 0); - - set_file_variables (file); - - /* Start the commands running. */ - new_job (file); -} - -/* 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) - { - register 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 - ) - { - register 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); - } - else - /* Wait for our children to die. */ - while (job_slots_used > 0) - reap_children (1, 1); - - /* 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 (EXIT_FAILURE); -#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, 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)); - if (ar_member_date (file->name) != file_date) - { - if (on_behalf_of) - error (NILF, _("*** [%s] Archive member `%s' may be bogus; not deleted"), - on_behalf_of, file->name); - else - 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) - error (NILF, _("*** [%s] Deleting file `%s'"), on_behalf_of, file->name); - else - 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, (char *) 0); - - /* 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. */ - -void -print_commands (struct commands *cmds) -{ - register char *s; - - fputs (_("# commands to execute"), stdout); - - if (cmds->fileinfo.filenm == 0) - puts (_(" (built-in):")); - else - printf (_(" (from `%s', line %lu):\n"), - cmds->fileinfo.filenm, cmds->fileinfo.lineno); - - s = cmds->commands; - while (*s != '\0') - { - char *end; - - while (isspace ((unsigned char)*s)) - ++s; - - end = strchr (s, '\n'); - if (end == 0) - end = s + strlen (s); - - printf ("\t%.*s\n", (int) (end - s), s); - - s = end; - } -} diff --git a/src/bin/make/commands.h b/src/bin/make/commands.h deleted file mode 100644 index 96a1a4db0b..0000000000 --- a/src/bin/make/commands.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Definition of data structures describing shell commands for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* Structure that gives the commands to make a file - and information about where these commands came from. */ - -struct commands - { - struct floc fileinfo; /* Where commands were defined. */ - char *commands; /* Commands text. */ - unsigned int ncommand_lines;/* Number of command lines. */ - char **command_lines; /* Commands chopped up into lines. */ - char *lines_flags; /* One set of flag bits for each line. */ - int any_recurse; /* Nonzero if any `lines_recurse' 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: -. */ - -extern void execute_file_commands PARAMS ((struct file *file)); -extern void print_commands PARAMS ((struct commands *cmds)); -extern void delete_child_targets PARAMS ((struct child *child)); -extern void chop_commands PARAMS ((struct commands *cmds)); -extern void set_file_variables PARAMS ((struct file *file)); diff --git a/src/bin/make/config.h b/src/bin/make/config.h deleted file mode 100644 index 458df1893e..0000000000 --- a/src/bin/make/config.h +++ /dev/null @@ -1,401 +0,0 @@ -/* Edited by Marcus Overhagen */ -/* config.h. Generated by configure. */ -/* config.h.in. Generated from configure.in by autoheader. */ - -#define LOCALEDIR "/etc/locale/" -#define LIBDIR "/boot/develop/lib/" -#define INCLUDEDIR "/boot/develop/headers/" - -/* Define to 1 if the `closedir' function returns void instead of `int'. */ -/* #undef CLOSEDIR_VOID */ - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define to 1 if using `getloadavg.c'. */ -#define C_GETLOADAVG 1 - -/* Define to 1 for DGUX with . */ -/* #undef DGUX */ - -/* Define to 1 if translation of program messages to the user's native - language is requested. */ -/* #undef ENABLE_NLS */ - -/* Use high resolution file timestamps if nonzero. */ -#define FILE_TIMESTAMP_HI_RES 0 - -/* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. - */ -/* #undef GETLOADAVG_PRIVILEGED */ - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#define HAVE_ALLOCA_H 1 - -/* This system has SA_RESTART, but it doesn't work properly. */ -/* #undef HAVE_BROKEN_RESTART */ - -/* Define to 1 if you have the `bsd_signal' function. */ -/* #undef HAVE_BSD_SIGNAL */ - -/* Define if you have the clock_gettime function. */ -/* #undef HAVE_CLOCK_GETTIME */ - -/* Define if the GNU dcgettext() function is already present or preinstalled. - */ -/* #undef HAVE_DCGETTEXT */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ - -/* Define to 1 if you have the `dup2' function. */ -#define HAVE_DUP2 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fdopen' function. */ -#define HAVE_FDOPEN 1 - -/* Define to 1 if you have the `fork' function. */ -#define HAVE_FORK 1 - -/* Define to 1 if you have the `getcwd' function. */ -#define HAVE_GETCWD 1 - -/* Define to 1 if you have the `getgroups' function. */ -#define HAVE_GETGROUPS 1 - -/* Define to 1 if you have the `gethostbyname' function. */ -/* #undef HAVE_GETHOSTBYNAME */ - -/* Define to 1 if you have the `gethostname' function. */ -/* #undef HAVE_GETHOSTNAME */ - -/* Define to 1 if you have the `getloadavg' function. */ -/* #undef HAVE_GETLOADAVG */ - -/* Define if the GNU gettext() function is already present or preinstalled. */ -/* #undef HAVE_GETTEXT */ - -/* Define if you have a standard gettimeofday function */ -#define HAVE_GETTIMEOFDAY 1 - -/* Define if you have the iconv() function. */ -/* #undef HAVE_ICONV */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `dgc' library (-ldgc). */ -/* #undef HAVE_LIBDGC */ - -/* Define to 1 if you have the `kstat' library (-lkstat). */ -/* #undef HAVE_LIBKSTAT */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACH_MACH_H */ - -/* Define to 1 if you have the `memcpy' function. */ -#define HAVE_MEMCPY 1 - -/* Define to 1 if you have the `memmove' function. */ -#define HAVE_MEMMOVE 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mkstemp' function. */ -#define HAVE_MKSTEMP 1 - -/* Define to 1 if you have the `mktemp' function. */ -#define HAVE_MKTEMP 1 - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NLIST_H */ - -/* Define to 1 if you have the `pipe' function. */ -#define HAVE_PIPE 1 - -/* Define to 1 if you have the `pstat_getdynamic' function. */ -/* #undef HAVE_PSTAT_GETDYNAMIC */ - -/* Define if defines the SA_RESTART constant. */ -/* #undef HAVE_SA_RESTART */ -#ifdef HAIKU_TARGET_PLATFORM_HAIKU -# define HAVE_SA_RESTART 1 -#endif - -/* Define to 1 if you have the `setegid' function. */ -/* #undef HAVE_SETEGID */ - -/* Define to 1 if you have the `seteuid' function. */ -/* #undef HAVE_SETEUID */ - -/* Define to 1 if you have the `setlinebuf' function. */ -#define HAVE_SETLINEBUF 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setregid' function. */ -/* #undef HAVE_SETREGID */ - -/* Define to 1 if you have the `setreuid' function. */ -/* #undef HAVE_SETREUID */ - -/* Define to 1 if you have the `setvbuf' function. */ -#define HAVE_SETVBUF 1 - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if you have the `sigsetmask' function. */ -/* #undef HAVE_SIGSETMASK */ - -/* Define to 1 if you have the `socket' function. */ -/* #undef HAVE_SOCKET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasecmp' function. */ -/* #undef HAVE_STRCASECMP */ -#define HAVE_STRCASECMP 1 - -/* Define to 1 if you have the `strchr' function. */ -#define HAVE_STRCHR 1 - -/* Define to 1 if you have the `strcoll' function and it is properly defined. - */ -#define HAVE_STRCOLL 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strsignal' function. */ -#define HAVE_STRSIGNAL 1 - -/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ -/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIMEB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define this if you have the `union wait' type in . */ -/* #undef HAVE_UNION_WAIT */ - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `vfork' function. */ -/* #undef HAVE_VFORK */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VFORK_H */ - -/* Define to 1 if you have the `vprintf' function. */ -#define HAVE_VPRINTF 1 - -/* Define to 1 if you have the `wait3' function. */ -/* #undef HAVE_WAIT3 */ - -/* Define to 1 if you have the `waitpid' function. */ -#define HAVE_WAITPID 1 - -/* Define to 1 if `fork' works. */ -#define HAVE_WORKING_FORK 1 - -/* Define to 1 if `vfork' works. */ -/* #undef HAVE_WORKING_VFORK */ - -/* Build host information. */ -#define MAKE_HOST "i586-pc-beos" - -/* Define this to enable job server support in GNU make. */ -/* #undef MAKE_JOBSERVER */ - -/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend - on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ -/* #undef NLIST_NAME_UNION */ - -/* Define if struct nlist.n_name is a pointer rather than an array. */ -/* #undef NLIST_STRUCT */ - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Name of package */ -#define PACKAGE "make" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "bug-make@gnu.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "GNU make" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU make 3.81" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "make" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "3.81" - -/* Define to 1 if the C compiler supports function prototypes. */ -#define PROTOTYPES 1 - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to the name of the SCCS 'get' command. */ -#define SCCS_GET "get" - -/* Define this if the SCCS 'get' command understands the '-G' option. */ -/* #undef SCCS_GET_MINUS_G */ - -/* Define to 1 if the `setvbuf' function takes the buffering type as its - second argument and the buffer pointer as the third, as on System V before - release 3. */ -/* #undef SETVBUF_REVERSED */ - -/* If using the C implementation of alloca, define 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 */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if the `S_IS*' macros in do not work properly. */ -/* #undef STAT_MACROS_BROKEN */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if 'struct stat' contains a nanoseconds field */ -/* #undef ST_MTIM_NSEC */ - -/* Define to 1 on System V Release 4. */ -/* #undef SVR4 */ - -/* Define to 1 if `sys_siglist' is declared by or . */ -#define SYS_SIGLIST_DECLARED 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 for Encore UMAX. */ -/* #undef UMAX */ - -/* Define to 1 for Encore UMAX 4.3 that has instead of - . */ -/* #undef UMAX4_3 */ - -/* Version number of package */ -#define VERSION "3.81" - -/* Define if using the dmalloc debugging malloc package */ -/* #undef WITH_DMALLOC */ - -/* Define to 1 if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* # undef _ALL_SOURCE */ -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define like PROTOTYPES; this can be used by system headers. */ -#define __PROTOTYPES 1 - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `int' if doesn't define. */ -/* #undef gid_t */ - -/* Define to `int' if does not define. */ -/* #undef pid_t */ - -/* Define to `int' if doesn't define. */ -/* #undef uid_t */ - -/* Define uintmax_t if not defined in or . */ -/* #undef uintmax_t */ - -/* Define as `fork' if `vfork' does not work. */ -#define vfork fork diff --git a/src/bin/make/debug.h b/src/bin/make/debug.h deleted file mode 100644 index 9b6ac07210..0000000000 --- a/src/bin/make/debug.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Debugging macros and interface. -Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#define DB_NONE (0x000) -#define DB_BASIC (0x001) -#define DB_VERBOSE (0x002) -#define DB_JOBS (0x004) -#define DB_IMPLICIT (0x008) -#define DB_MAKEFILES (0x100) - -#define DB_ALL (0xfff) - -extern int db_level; - -#define ISDB(_l) ((_l)&db_level) - -#define DBS(_l,_x) do{ if(ISDB(_l)) {print_spaces (depth); \ - printf _x; fflush (stdout);} }while(0) - -#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) diff --git a/src/bin/make/default.c b/src/bin/make/default.c deleted file mode 100644 index 86f719aa24..0000000000 --- a/src/bin/make/default.c +++ /dev/null @@ -1,594 +0,0 @@ -/* Data base of default implicit rules for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#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 - = ".exe .olb .ln .obj .c .cxx .cc .pas .p .for .f .r .y .l .mar \ -.s .ss .i .ii .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo \ -.w .ch .cweb .web .com .sh .elc .el"; -#elif defined(__EMX__) - = ".out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .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 .r .y .l .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[] = - { - { "(%)", "%", - "$(AR) $(ARFLAGS) $@ $<" }, - - /* 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", "%", - "copy $< $@" }, -#else - { "%.out", "%", - "@rm -f $@ \n cp $< $@" }, -#endif - /* 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 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=$@ $<", - ".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=$@ $<", - ".cxx.obj", - "$(COMPILE.cxx) /obj=$@ $<", - ".for.obj", - "$(COMPILE.for) /obj=$@ $<", - ".pas.obj", - "$(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 $@", - ".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) $<", - ".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) $< > $@", - - ".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 char *default_variables[] = - { -#ifdef VMS -#ifdef __ALPHA - "ARCH", "ALPHA", -#endif -#ifdef __ia64 - "ARCH", "IA64", -#endif -#ifdef __VAX - "ARCH", "VAX", -#endif - "AR", "library/obj", - "ARFLAGS", "/replace", - "AS", "macro", - "MACRO", "macro", -#ifdef GCC_IS_NATIVE - "CC", "gcc", -#else - "CC", "cc", -#endif - "CD", "builtin_cd", - "MAKE", "make", - "ECHO", "write sys$$output \"", -#ifdef GCC_IS_NATIVE - "C++", "gcc/plus", - "CXX", "gcc/plus", -#else - "C++", "cxx", - "CXX", "cxx", - "CXXLD", "cxxlink", -#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", - -#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__ */ -#else - "CC", "cc", - "CXX", "g++", -#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.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", - "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 - -#ifdef _AMIGA - ".LIBPATTERNS", "%.lib", -#else -#ifdef __MSDOS__ - ".LIBPATTERNS", "lib%.a $(DJDIR)/lib/lib%.a", -#else - ".LIBPATTERNS", "lib%.so lib%.a", -#endif -#endif - -#endif /* !VMS */ - 0, 0 - }; - -/* Set up the default .SUFFIXES list. */ - -void -set_default_suffixes (void) -{ - suffix_file = enter_file (".SUFFIXES"); - - if (no_builtin_rules_flag) - (void) define_variable ("SUFFIXES", 8, "", o_default, 0); - else - { - char *p = default_suffixes; - suffix_file->deps = (struct dep *) - multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1), - sizeof (struct dep)); - (void) define_variable ("SUFFIXES", 8, 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 thee pattern rules - installed after. */ - -void -install_default_suffix_rules (void) -{ - register char **s; - - if (no_builtin_rules_flag) - return; - - for (s = default_suffix_rules; *s != 0; s += 2) - { - register struct file *f = enter_file (s[0]); - /* Don't clobber cmds given in a makefile if there were any. */ - if (f->cmds == 0) - { - f->cmds = (struct commands *) xmalloc (sizeof (struct commands)); - f->cmds->fileinfo.filenm = 0; - f->cmds->commands = s[1]; - f->cmds->command_lines = 0; - } - } -} - - -/* Install the default pattern rules. */ - -void -install_default_implicit_rules (void) -{ - register 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) -{ - register char **s; - - if (no_builtin_variables_flag) - return; - - for (s = default_variables; *s != 0; s += 2) - (void) define_variable (s[0], strlen (s[0]), s[1], o_default, 1); -} diff --git a/src/bin/make/dep.h b/src/bin/make/dep.h deleted file mode 100644 index f0923cc2ed..0000000000 --- a/src/bin/make/dep.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Definitions of dependency data structures for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* 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'. */ - -#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; - char *name; - char *stem; - struct file *file; - unsigned int changed : 8; - unsigned int ignore_mtime : 1; - unsigned int staticpattern : 1; - unsigned int need_2nd_expansion : 1; - }; - - -/* Structure used in chains of names, for parsing and globbing. */ - -struct nameseq - { - struct nameseq *next; - char *name; - }; - - -extern struct nameseq *multi_glob PARAMS ((struct nameseq *chain, unsigned int size)); -#ifdef VMS -extern struct nameseq *parse_file_seq (); -#else -extern struct nameseq *parse_file_seq PARAMS ((char **stringp, int stopchar, unsigned int size, int strip)); -#endif -extern char *tilde_expand PARAMS ((char *name)); - -#ifndef NO_ARCHIVES -extern struct nameseq *ar_glob PARAMS ((char *arname, char *member_pattern, unsigned int size)); -#endif - -#ifndef iAPX286 -#define dep_name(d) ((d)->name == 0 ? (d)->file->name : (d)->name) -#else -/* Buggy compiler can't hack this. */ -extern char *dep_name (); -#endif - -extern struct dep *alloc_dep PARAMS ((void)); -extern void free_dep PARAMS ((struct dep *d)); -extern struct dep *copy_dep_chain PARAMS ((const struct dep *d)); -extern void free_dep_chain PARAMS ((struct dep *d)); -extern void free_ns_chain PARAMS ((struct nameseq *n)); -extern struct dep *read_all_makefiles PARAMS ((char **makefiles)); -extern int eval_buffer PARAMS ((char *buffer)); -extern int update_goal_chain PARAMS ((struct dep *goals)); -extern void uniquize_deps PARAMS ((struct dep *)); diff --git a/src/bin/make/dir.c b/src/bin/make/dir.c deleted file mode 100644 index f72ce42ac5..0000000000 --- a/src/bin/make/dir.c +++ /dev/null @@ -1,1216 +0,0 @@ -/* Directory hashing for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "hash.h" - -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -# ifdef VMS -extern char *vmsify PARAMS ((char *name, int type)); -# endif -#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 - -#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 char * -dosify (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; *filename != '\0' && i < 8 && *filename != '.'; ++i) - *df++ = tolower ((unsigned char)*filename++); - - /* Now skip to the next dot. */ - while (*filename != '\0' && *filename != '.') - ++filename; - if (*filename != '\0') - { - *df++ = *filename++; - for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i) - *df++ = tolower ((unsigned char)*filename++); - } - - /* Look for more dots. */ - while (*filename != '\0' && *filename != '.') - ++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 char * -downcase (char *filename) -{ - static PATH_VAR (new_filename); - char *df; - int i; - - if (filename == 0) - return 0; - - df = new_filename; - - /* First, transform the name part. */ - for (i = 0; *filename != '\0'; ++i) - { - *df++ = tolower ((unsigned char)*filename); - ++filename; - } - - *df = 0; - - return new_filename; -} -#endif /* HAVE_CASE_INSENSITIVE_FS */ - -#ifdef VMS - -static int -vms_hash (char *name) -{ - int h = 0; - int g; - - while (*name) - { - unsigned char uc = *name; -#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 (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) - { - *s++ = 0; - st->st_dev = (char *)vms_hash (name); - h = vms_hash (s); - *(s-1) = ':'; - } - else - { - st->st_dev = 0; - s = name; - h = vms_hash (s); - } - - 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) -{ - struct directory_contents const *key = (struct directory_contents const *) 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) -{ - struct directory_contents const *key = (struct directory_contents const *) 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) -{ - struct directory_contents const *x = (struct directory_contents const *) xv; - struct directory_contents const *y = (struct directory_contents const *) 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 - { - 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 (((struct directory const *) key)->name); -} - -static unsigned long -directory_hash_2 (const void *key) -{ - return_ISTRING_HASH_2 (((struct directory const *) key)->name); -} - -static int -directory_hash_cmp (const void *x, const void *y) -{ - return_ISTRING_COMPARE (((struct directory const *) x)->name, - ((struct directory const *) 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 - { - 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) -{ - struct dirfile const *x = ((struct dirfile const *) xv); - struct dirfile const *y = ((struct dirfile const *) 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 PARAMS ((struct directory_contents *dir, char *filename)); -static struct directory *find_directory PARAMS ((char *name)); - -/* Find the directory named NAME and return its `struct directory'. */ - -static struct directory * -find_directory (char *name) -{ - register char *p; - register struct directory *dir; - register struct directory **dir_slot; - struct directory dir_key; - int r; -#ifdef WINDOWS32 - char* w32_path; - char fs_label[BUFSIZ]; - char fs_type[BUFSIZ]; - unsigned long fs_serno; - unsigned long fs_flags; - unsigned long fs_len; -#endif -#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)) - { - struct stat st; - - /* The directory was not found. Create a new entry for it. */ - - p = name + strlen (name); - dir = (struct directory *) xmalloc (sizeof (struct directory)); - dir->name = savestring (name, p - name); - 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 WINDOWS32 - /* Remove any trailing '\'. Windows32 stat fails even on valid - directories if they end in '\'. */ - if (p[-1] == '\\') - p[-1] = '\0'; -#endif - -#ifdef VMS - r = vmsstat_dir (name, &st); -#else - EINTRLOOP (r, stat (name, &st)); -#endif - -#ifdef WINDOWS32 - /* Put back the trailing '\'. If we don't, we're permanently - truncating the value! */ - if (p[-1] == '\0') - p[-1] = '\\'; -#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. */ - - 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. */ - - 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. */ - (void) dir_contents_file_exists_p (dc, (char *) 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, char *filename) -{ - unsigned int hash; - 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 - - hash = 0; - 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 = (struct dirfile *) 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) - 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 = (struct dirfile *) xmalloc (sizeof (struct dirfile)); - df->name = savestring (d->d_name, len); - 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 && strieq (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 (char *dirname, 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 (char *name) -{ - char *dirend; - char *dirname; - char *slash; - -#ifndef NO_ARCHIVES - if (ar_name (name)) - return ar_member_date (name) != (time_t) -1; -#endif - -#ifdef VMS - dirend = strrchr (name, ']'); - if (dirend == 0) - dirend = strrchr (name, ':'); - if (dirend == (char *)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. */ - { - 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 - { -#ifdef HAVE_DOS_PATHS - /* d:/ and d: are *very* different... */ - if (dirend < name + 3 && name[1] == ':' && - (*dirend == '/' || *dirend == '\\' || *dirend == ':')) - dirend++; -#endif - dirname = (char *) alloca (dirend - name + 1); - bcopy (name, dirname, dirend - name); - dirname[dirend - name] = '\0'; - } - 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 (char *filename) -{ - char *dirend; - register char *p = filename; - register struct directory *dir; - register 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. */ - { - 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 - { - char *dirname; - char *slash = dirend; - if (dirend == p) - dirname = "/"; - else - { -#ifdef HAVE_DOS_PATHS - /* d:/ and d: are *very* different... */ - if (dirend < p + 3 && p[1] == ':' && - (*dirend == '/' || *dirend == '\\' || *dirend == ':')) - dirend++; -#endif - dirname = (char *) alloca (dirend - p + 1); - bcopy (p, dirname, dirend - p); - dirname[dirend - p] = '\0'; - } - 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 = (struct directory_contents *) - xmalloc (sizeof (struct directory_contents)); - bzero ((char *) dir->contents, 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 = (struct dirfile *) xmalloc (sizeof (struct dirfile)); - new->name = xstrdup (filename); - new->length = strlen (filename); - new->impossible = 1; - hash_insert (&dir->contents->dirfiles, new); -} - -/* Return nonzero if FILENAME has been marked impossible. */ - -int -file_impossible_p (char *filename) -{ - char *dirend; - register char *p = filename; - register struct directory_contents *dir; - register 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. */ - { - 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 - { - char *dirname; - char *slash = dirend; - if (dirend == filename) - dirname = "/"; - else - { -#ifdef HAVE_DOS_PATHS - /* d:/ and d: are *very* different... */ - if (dirend < filename + 3 && filename[1] == ':' && - (*dirend == '/' || *dirend == '\\' || *dirend == ':')) - dirend++; -#endif - dirname = (char *) alloca (dirend - filename + 1); - bcopy (p, dirname, dirend - p); - dirname[dirend - p] = '\0'; - } - dir = find_directory (dirname)->contents; - p = 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 (p); -#endif -#ifdef HAVE_CASE_INSENSITIVE_FS - filename = downcase (p); -#endif -#ifdef VMS - filename = vmsify (p, 1); -#endif - - dirfile_key.name = filename; - dirfile_key.length = strlen (filename); - dirfile = (struct 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. */ - -char * -dir_name (char *dir) -{ - return find_directory (dir)->name; -} - -/* Print the data base of directories. */ - -void -print_dir_data_base (void) -{ - register unsigned int files; - register unsigned int impossible; - register struct directory **dir_slot; - register 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++) - { - register 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 - { - register unsigned int f = 0; - register unsigned int im = 0; - register struct dirfile **files_slot; - register 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++) - { - register 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 PARAMS ((const char *)); -static struct dirent *read_dirstream PARAMS ((__ptr_t)); - -static __ptr_t -open_dirstream (const char *directory) -{ - struct dirstream *new; - struct directory *dir = find_directory ((char *)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. */ - - (void) dir_contents_file_exists_p (dir->contents, (char *) 0); - - new = (struct dirstream *) 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) -{ - 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; - static char *buf; - static unsigned int bufsz; - - while (ds->dirfile_slot < dirfile_end) - { - register 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; - if (sizeof *d - sizeof d->d_name + len > bufsz) - { - if (buf != 0) - free (buf); - bufsz *= 2; - if (sizeof *d - sizeof d->d_name + len > bufsz) - bufsz = sizeof *d - sizeof d->d_name + len; - buf = xmalloc (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; -} - -static void -ansi_free (void *p) -{ - if (p) - free(p); -} - -/* 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. - */ -#ifndef stat -# ifndef VMS -extern int stat PARAMS ((const char *path, struct stat *sbuf)); -# endif -# define local_stat stat -#else -static int -local_stat (const char *path, struct stat *buf) -{ - int e; - - EINTRLOOP (e, stat (path, buf)); - return e; -} -#endif - -void -dir_setup_glob (glob_t *gl) -{ - /* Bogus sunos4 compiler complains (!) about & before functions. */ - gl->gl_opendir = open_dirstream; - gl->gl_readdir = read_dirstream; - gl->gl_closedir = ansi_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); -} diff --git a/src/bin/make/expand.c b/src/bin/make/expand.c deleted file mode 100644 index 993e6d4f08..0000000000 --- a/src/bin/make/expand.c +++ /dev/null @@ -1,584 +0,0 @@ -/* Variable expansion functions for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.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 struct 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, 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 = (char *) xrealloc (variable_buffer, - variable_buffer_length); - ptr = variable_buffer + offset; - } - - bcopy (string, ptr, 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 = (char *) 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 PARAMS ((const struct variable *v)); - -char * -recursively_expand_for_file (struct variable *v, struct file *file) -{ - char *value; - const struct floc *this_var; - const struct 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. */ - 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, char *name, unsigned int length) -{ - register 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, char *string, long length) -{ - register struct variable *v; - register char *p, *o, *p1; - char save_char = '\0'; - unsigned int line_offset; - - if (!line) - line = initialize_variable_output(); - - p = string; - o = line; - line_offset = line - variable_buffer; - - if (length >= 0) - { - save_char = string[length]; - string[length] = '\0'; - } - - 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 == '(') ? ')' : '}'; - register char *beg = p + 1; - int free_beg = 0; - char *op, *begp; - 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. */ - 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) - { - beg = expand_argument (beg, p); /* Expand the name. */ - free_beg = 1; /* Remember to free BEG when finished. */ - 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). */ - char *subst_beg, *subst_end, *replace_beg, *replace_end; - - subst_beg = colon + 1; - 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 - { - replace_beg = subst_end + 1; - 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 = (char *) alloca (subst_end - subst_beg + 2); - *(pattern++) = '%'; - bcopy (subst_beg, pattern, subst_end - subst_beg); - pattern[subst_end - subst_beg] = '\0'; - - replace = (char *) alloca (replace_end - - replace_beg + 2); - *(replace++) = '%'; - bcopy (replace_beg, replace, - 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 = 0; - } - else - { - ppercent = pattern; - rpercent = replace; - --pattern; - --replace; - } - - o = patsubst_expand (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); - - if (free_beg) - free (beg); - } - 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; - else - ++p; - } - - if (save_char) - string[length] = save_char; - - (void)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 (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; - - if (str == end) - return xstrdup(""); - - if (!end || *end == '\0') - return allocated_variable_expand ((char *)str); - - tmp = (char *) alloca (end - str + 1); - bcopy (str, tmp, end - str); - tmp[end - str] = '\0'; - - return allocated_variable_expand (tmp); -} - -/* 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 (char *line, struct file *file) -{ - char *result; - struct variable_set_list *save; - - if (file == 0) - return variable_expand (line); - - save = current_variable_set_list; - current_variable_set_list = file->variables; - if (file->cmds && file->cmds->fileinfo.filenm) - reading_file = &file->cmds->fileinfo; - else - reading_file = 0; - result = variable_expand (line); - current_variable_set_list = save; - reading_file = 0; - - return 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) -{ - const struct variable *v; - char *buf = 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, look to see if there's one in a set above us. */ - if (!v) - return variable_append (name, length, set->next); - - /* 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); - 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); - 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 (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); - -#if 0 - /* Waste a little memory and save time. */ - value = xrealloc (value, strlen (value)) -#endif - - 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; -} diff --git a/src/bin/make/file.c b/src/bin/make/file.c deleted file mode 100644 index 90dd123058..0000000000 --- a/src/bin/make/file.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* Target file management for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#include - -#include "dep.h" -#include "filedef.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. */ - -static unsigned long -file_hash_1 (const void *key) -{ - return_ISTRING_HASH_1 (((struct file const *) key)->hname); -} - -static unsigned long -file_hash_2 (const void *key) -{ - return_ISTRING_HASH_2 (((struct file const *) key)->hname); -} - -static 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 -static struct hash_table files; - -/* Whether or not .SECONDARY with no prerequisites was given. */ -static int all_secondary = 0; - -/* 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. - enter_file similar, but create one if there is none. */ - -struct file * -lookup_file (char *name) -{ - register struct file *f; - struct file file_key; -#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) - register char *lname, *ln; -#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 != '.') - { - register char *n; - lname = (char *) malloc (strlen (name) + 1); - 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] == '.' && name[1] == '/' && name[2] != '\0') - { - name += 2; - while (*name == '/') - /* Skip following slashes: ".//foo" is "foo", not "/foo". */ - ++name; - } - - if (*name == '\0') - /* It was all slashes after a dot. */ -#ifdef VMS - name = "[]"; -#else -#ifdef _AMIGA - name = ""; -#else - name = "./"; -#endif /* AMIGA */ -#endif /* VMS */ - - file_key.hname = name; - f = (struct file *) 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 (char *name) -{ - register struct file *f; - register struct file *new; - register struct file **file_slot; - struct file file_key; -#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) - char *lname, *ln; -#endif - - assert (*name != '\0'); - -#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) - if (*name != '.') - { - register char *n; - lname = (char *) malloc (strlen (name) + 1); - for (n = name, ln = lname; *n != '\0'; ++n, ++ln) - { - if (isupper ((unsigned char)*n)) - *ln = tolower ((unsigned char)*n); - else - *ln = *n; - } - - *ln = 0; - /* Creates a possible leak, old value of name is unreachable, but I - currently don't know how to fix it. */ - name = 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) - { -#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS) - if (*name != '.') - free (lname); -#endif - return f; - } - - new = (struct file *) xmalloc (sizeof (struct file)); - bzero ((char *) new, sizeof (struct file)); - new->name = new->hname = name; - new->update_status = -1; - - 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; -} - -/* 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, char *to_hname) -{ - rehash_file (from_file, to_hname); - while (from_file) - { - from_file->name = from_file->hname; - from_file = from_file->prev; - } -} - -/* 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, char *to_hname) -{ - struct file file_key; - struct file **file_slot; - struct file *to_file; - struct file *deleted_file; - struct file *f; - - file_key.hname = to_hname; - if (0 == file_hash_cmp (from_file, &file_key)) - return; - - 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 (); - - deleted_file = hash_delete (&files, from_file); - if (deleted_file != from_file) - /* from_file isn't the one stored in files */ - abort (); - - file_key.hname = to_hname; - file_slot = (struct file **) hash_find_slot (&files, &file_key); - to_file = *file_slot; - - from_file->hname = to_hname; - for (f = from_file->double_colon; f != 0; f = f->prev) - f->hname = to_hname; - - if (HASH_VACANT (to_file)) - hash_insert_at (&files, from_file, file_slot); - else - { - /* 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) - { - /* 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, - _("Commands were 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, - _("Commands for file `%s' were found by implicit rule search,"), - from_file->name); - error (&from_file->cmds->fileinfo, - _("but `%s' is now considered the same file as `%s'."), - from_file->name, to_hname); - error (&from_file->cmds->fileinfo, - _("Commands for `%s' will be ignored in favor of those 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 - { - register 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) - 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) - 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 (ignore_vpath); -#undef MERGE - - from_file->renamed = to_file; - } -} - -/* 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) -{ - register struct file **file_slot; - register 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)) - { - register 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 == -1) - /* 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) - 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); - } -} - -struct dep * -parse_prereqs (char *p) -{ - struct dep *new = (struct dep *) - multi_glob (parse_file_seq (&p, '|', sizeof (struct dep), 1), - sizeof (struct dep)); - - 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 = (struct dep *) - multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1), - sizeof (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; -} - - -/* 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. */ -static void -expand_deps (struct file *f) -{ - struct dep *d; - struct dep *old = f->deps; - char *file_stem = f->stem; - unsigned int last_dep_has_cmds = f->updating; - int initialized = 0; - - f->updating = 0; - f->deps = 0; - - for (d = old; d != 0; d = d->next) - { - struct dep *new, *d1; - char *p; - - if (! d->name) - continue; - - /* Create the dependency list. - If we're not doing 2nd expansion, then it's just the name. */ - if (! d->need_2nd_expansion) - p = d->name; - else - { - /* If it's from a static pattern rule, convert the patterns into - "$*" so they'll expand properly. */ - if (d->staticpattern) - { - char *o; - char *buffer = variable_expand (""); - - o = subst_expand (buffer, d->name, "%", "$*", 1, 2, 0); - - free (d->name); - d->name = savestring (buffer, o - buffer); - d->staticpattern = 0; /* Clear staticpattern so that we don't - re-expand %s below. */ - } - - /* We are 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; - } - - /* Parse the prerequisites. */ - new = parse_prereqs (p); - - /* If this dep list was from a static pattern rule, expand the %s. We - use patsubst_expand to translate the prerequisites' patterns into - plain prerequisite names. */ - if (new && d->staticpattern) - { - char *pattern = "%"; - char *buffer = variable_expand (""); - struct dep *dp = new, *dl = 0; - - while (dp != 0) - { - char *percent = find_percent (dp->name); - if (percent) - { - /* We have to handle empty stems specially, because that - would be equivalent to $(patsubst %,dp->name,) which - will always be empty. */ - if (d->stem[0] == '\0') - /* This needs memmove() in ISO C. */ - bcopy (percent+1, percent, strlen (percent)); - else - { - char *o = patsubst_expand (buffer, d->stem, pattern, - dp->name, pattern+1, - percent+1); - if (o == buffer) - dp->name[0] = '\0'; - else - { - free (dp->name); - dp->name = savestring (buffer, o - buffer); - } - } - - /* If the name expanded to the empty string, ignore it. */ - if (dp->name[0] == '\0') - { - struct dep *df = dp; - if (dp == new) - dp = new = new->next; - else - dp = dl->next = dp->next; - /* @@ Are we leaking df->name here? */ - df->name = 0; - free_dep (df); - continue; - } - } - dl = dp; - dp = dp->next; - } - } - - /* Enter them as files. */ - for (d1 = new; d1 != 0; d1 = d1->next) - { - d1->file = lookup_file (d1->name); - if (d1->file == 0) - d1->file = enter_file (d1->name); - else - free (d1->name); - d1->name = 0; - d1->staticpattern = 0; - d1->need_2nd_expansion = 0; - } - - /* Add newly parsed deps to f->deps. If this is the last dependency - line and this target has commands then put it in front so the - last dependency line (the one with commands) ends up being the - first. This is important because people expect $< to hold first - prerequisite from the rule with commands. If it is not the last - dependency line or the rule does not have commands then link it - at the end so it appears in makefile order. */ - - if (new != 0) - { - if (d->next == 0 && last_dep_has_cmds) - { - struct dep **d_ptr; - for (d_ptr = &new; *d_ptr; d_ptr = &(*d_ptr)->next) - ; - - *d_ptr = f->deps; - f->deps = new; - } - else - { - struct dep **d_ptr; - for (d_ptr = &f->deps; *d_ptr; d_ptr = &(*d_ptr)->next) - ; - - *d_ptr = new; - } - } - } - - free_dep_chain (old); -} - -/* 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; - struct file **file_slot_0; - struct file **file_slot; - struct file **file_end; - - /* Perform second expansion and enter each dependency - name as a file. */ - - /* Expand .SUFFIXES first; it's dependencies are used for - $$* calculation. */ - for (f = lookup_file (".SUFFIXES"); f != 0; f = f->prev) - expand_deps (f); - - /* We must use hash_dump (), because within this loop - we might add new files to the table, possibly causing - an in-situ table expansion. */ - file_slot_0 = (struct file **) hash_dump (&files, 0, 0); - file_end = file_slot_0 + files.ht_fill; - for (file_slot = file_slot_0; file_slot < file_end; file_slot++) - for (f = *file_slot; f != 0; f = f->prev) - { - if (strcmp (f->name, ".SUFFIXES") != 0) - expand_deps (f); - } - free (file_slot_0); - - 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) - { - /* .INTERMEDIATE with deps listed - marks those 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) - { - /* .SECONDARY with deps listed - marks those deps as intermediate files - in that they don't get rebuilt if not actually needed; - but unlike real intermediate files, - these are not deleted after make finishes. */ - 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 (STRING_SIZE_TUPLE("OUTPUT_OPTION"), "", o_default, 1); - */ -#endif - - /* Remember that we've done this. */ - snapped_deps = 1; -} - -/* 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 s, int ns) -{ - int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0); - 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]; - ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX; - file_timestamp_sprintf (buf, ts); - error (NILF, _("%s: Timestamp out of range; substituting %s"), - fname ? fname : _("Current time"), 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 the data base of files. */ - -static void -print_file (const void *item) -{ - struct file *f = (struct file *) item; - struct dep *d; - struct dep *ood = 0; - - putchar ('\n'); - if (!f->is_target) - puts (_("# Not a target:")); - printf ("%s:%s", f->name, f->double_colon ? ":" : ""); - - /* Print all normal dependencies; note any order-only deps. */ - for (d = f->deps; d != 0; d = d->next) - if (! d->ignore_mtime) - printf (" %s", dep_name (d)); - else if (! ood) - ood = d; - - /* 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 (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.")); - 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) - { - 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 (_("# 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: - case cs_finished: - switch (f->update_status) - { - case -1: - break; - case 0: - puts (_("# Successfully updated.")); - break; - case 1: - assert (question_flag); - puts (_("# Needs to be updated (-q is set).")); - break; - case 2: - 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 (f->variables != 0) - print_file_variables (f); - - if (f->cmds != 0) - print_commands (f->cmds); - - if (f->prev) - print_file ((const void *) f->prev); -} - -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); -} - -#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]; - } - - bcopy (f->name, p, l); - p += l; - *(p++) = ' '; - } - *(p-1) = '\0'; - - last_targ_count = files.ht_fill; - } - - return value; -} - -void -init_hash_files (void) -{ - hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp); -} - -/* EOF */ diff --git a/src/bin/make/filedef.h b/src/bin/make/filedef.h deleted file mode 100644 index e4fe7c970f..0000000000 --- a/src/bin/make/filedef.h +++ /dev/null @@ -1,202 +0,0 @@ -/* Definition of target file data structures for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - - -/* Structure that represents the info on one file - that the makefile says how to make. - All of these are chained together through `next'. */ - -#include "hash.h" - -struct file - { - char *name; - char *hname; /* Hashed filename */ - char *vpath; /* VPATH/vpath pathname */ - struct dep *deps; /* all dependencies, including duplicates */ - struct commands *cmds; /* Commands to execute for this target. */ - int command_flags; /* Flags OR'd in for cmds; see commands.h. */ - char *stem; /* Implicit stem, if an implicit - rule has been used */ - struct dep *also_make; /* Targets that are made by making this. */ - FILE_TIMESTAMP last_mtime; /* File's modtime, if already known. */ - FILE_TIMESTAMP mtime_before_update; /* File's modtime before any updating - has been performed. */ - 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; - - short int update_status; /* Status of the last attempt to update, - or -1 if none has been made. */ - - enum cmd_state /* State of the commands. */ - { /* Note: It is important that cs_not_started be zero. */ - cs_not_started, /* Not yet started. */ - cs_deps_running, /* Dep commands running. */ - cs_running, /* Commands running. */ - cs_finished /* Commands finished. */ - } command_state ENUM_BITFIELD (2); - - unsigned int precious:1; /* Non-0 means don't delete file on quit */ - 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 */ - }; - - -extern struct file *default_goal_file, *suffix_file, *default_file; -extern char **default_goal_name; - - -extern struct file *lookup_file PARAMS ((char *name)); -extern struct file *enter_file PARAMS ((char *name)); -extern struct dep *parse_prereqs PARAMS ((char *prereqs)); -extern void remove_intermediates PARAMS ((int sig)); -extern void snap_deps PARAMS ((void)); -extern void rename_file PARAMS ((struct file *file, char *name)); -extern void rehash_file PARAMS ((struct file *file, char *name)); -extern void set_command_state PARAMS ((struct file *file, enum cmd_state state)); -extern void notice_finished_file PARAMS ((struct file *file)); -extern void init_hash_files PARAMS ((void)); -extern char *build_target_list PARAMS ((char *old_list)); - -#if FILE_TIMESTAMP_HI_RES -# define FILE_TIMESTAMP_STAT_MODTIME(fname, st) \ - file_timestamp_cons (fname, (st).st_mtime, (st).st_mtim.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 19, - 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) - -extern FILE_TIMESTAMP file_timestamp_cons PARAMS ((char const *, - time_t, int)); -extern FILE_TIMESTAMP file_timestamp_now PARAMS ((int *)); -extern void file_timestamp_sprintf PARAMS ((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) -extern FILE_TIMESTAMP f_mtime PARAMS ((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; diff --git a/src/bin/make/function.c b/src/bin/make/function.c deleted file mode 100644 index c62f7abc92..0000000000 --- a/src/bin/make/function.c +++ /dev/null @@ -1,2340 +0,0 @@ -/* Builtin function expansion for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "filedef.h" -#include "variable.h" -#include "dep.h" -#include "job.h" -#include "commands.h" -#include "debug.h" - -#ifdef _AMIGA -#include "amiga.h" -#endif - - -struct function_table_entry - { - const char *name; - unsigned char len; - unsigned char minimum_args; - unsigned char maximum_args; - char expand_args; - char *(*func_ptr) PARAMS ((char *output, char **argv, const char *fname)); - }; - -static unsigned long -function_table_entry_hash_1 (const void *keyv) -{ - struct function_table_entry const *key = (struct function_table_entry const *) keyv; - return_STRING_N_HASH_1 (key->name, key->len); -} - -static unsigned long -function_table_entry_hash_2 (const void *keyv) -{ - struct function_table_entry const *key = (struct function_table_entry const *) keyv; - return_STRING_N_HASH_2 (key->name, key->len); -} - -static int -function_table_entry_hash_cmp (const void *xv, const void *yv) -{ - struct function_table_entry const *x = (struct function_table_entry const *) xv; - struct function_table_entry const *y = (struct function_table_entry const *) 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, char *text, char *subst, char *replace, - unsigned int slen, unsigned int rlen, int by_word) -{ - char *t = text; - 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])) - || (p[slen] != '\0' && !isblank ((unsigned char)p[slen])))) - /* 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. */ - { - char *nt = p + slen; - t = nt; - } - } 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 (char *o, char *text, char *pattern, char *replace, - char *pattern_percent, char *replace_percent) -{ - unsigned int pattern_prepercent_len, pattern_postpercent_len; - unsigned int replace_prepercent_len, replace_postpercent_len; - char *t; - unsigned int len; - int doneany = 0; - - /* We call find_percent on REPLACE before checking PATTERN so that REPLACE - will be collapsed before we call subst_expand if PATTERN has no %. */ - if (!replace_percent) - { - replace_percent = find_percent (replace); - if (replace_percent) - ++replace_percent; - } - - /* 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) - { - pattern_percent = find_percent (pattern); - if (pattern_percent) - ++pattern_percent; - } - 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; -} - - -/* Look up a function by name. */ - -static const struct function_table_entry * -lookup_function (const char *s) -{ - const char *e = s; - - while (*e && ( (*e >= 'a' && *e <= 'z') || *e == '-')) - e++; - if (*e == '\0' || isblank ((unsigned char) *e)) - { - struct function_table_entry function_table_entry_key; - function_table_entry_key.name = s; - function_table_entry_key.len = e - s; - - return hash_find_item (&function_table, &function_table_entry_key); - } - return 0; -} - - -/* Return 1 if PATTERN matches STR, 0 if not. */ - -int -pattern_matches (char *pattern, char *percent, char *str) -{ - unsigned int sfxlen, strlength; - - if (percent == 0) - { - unsigned int len = strlen (pattern) + 1; - char *new_chars = (char *) alloca (len); - bcopy (pattern, new_chars, len); - pattern = new_chars; - percent = find_percent (pattern); - if (percent == 0) - return streq (pattern, str); - } - - 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; - register struct nameseq *chain; - register unsigned int idx; - - chain = multi_glob (parse_file_seq - (&line, '\0', sizeof (struct nameseq), - /* We do not want parse_file_seq to strip `./'s. - That would break examples like: - $(patsubst ./%.c,obj/%.o,$(wildcard ./?*.c)). */ - 0), - sizeof (struct nameseq)); - - if (result == 0) - { - length = 100; - result = (char *) xmalloc (100); - } - - idx = 0; - while (chain != 0) - { - register char *name = chain->name; - unsigned int len = strlen (name); - - struct nameseq *next = chain->next; - free ((char *) chain); - chain = next; - - /* multi_glob will pass names without globbing metacharacters - through as is, but we want only files that actually exist. */ - if (file_exists_p (name)) - { - if (idx + len + 1 > length) - { - length += (len + 1) * 2; - result = (char *) xrealloc (result, length); - } - bcopy (name, &result[idx], len); - idx += len; - result[idx++] = ' '; - } - - free (name); - } - - /* 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], (char *) 0, (char *) 0); - 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. */ - register char *tp; - register char *pp; - char *list1_iterator = argv[0]; - 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. */ - register 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) -{ - register 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; -} - -#ifdef VMS -# define IS_PATHSEP(c) ((c) == ']') -#else -# ifdef HAVE_DOS_PATHS -# define IS_PATHSEP(c) ((c) == '/' || (c) == '\\') -# else -# define IS_PATHSEP(c) ((c) == '/') -# endif -#endif - - -static char * -func_notdir_suffix (char *o, char **argv, const char *funcname) -{ - /* Expand the argument. */ - char *list_iterator = argv[0]; - char *p2 =0; - int doneany =0; - unsigned int len=0; - - int is_suffix = streq (funcname, "suffix"); - int is_notdir = !is_suffix; - while ((p2 = find_next_token (&list_iterator, &len)) != 0) - { - char *p = p2 + len; - - - while (p >= p2 && (!is_suffix || *p != '.')) - { - if (IS_PATHSEP (*p)) - break; - --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 (streq (funcname, "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. */ - char *p3 = argv[0]; - char *p2=0; - int doneany=0; - unsigned int len=0; - char *p=0; - int is_basename= streq (funcname, "basename"); - int is_dir= !is_basename; - - while ((p2 = find_next_token (&p3, &len)) != 0) - { - p = p2 + len; - while (p >= p2 && (!is_basename || *p != '.')) - { - if (IS_PATHSEP (*p)) - break; - --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) -#ifdef VMS - o = variable_buffer_output (o, "[]", 2); -#else -#ifndef _AMIGA - o = variable_buffer_output (o, "./", 2); -#else - ; /* Just a nop... */ -#endif /* AMIGA */ -#endif /* !VMS */ - 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]); - char *list_iterator = argv[1]; - int is_addprefix = streq (funcname, "addprefix"); - int is_addsuffix = !is_addprefix; - - int doneany = 0; - 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; - char *words = argv[0]; /* Use a temp variable for find_next_token */ - 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; - char *words = argv[0]; /* Use a temp variable for find_next_token */ - char *p = 0; - 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; - char *word_iterator = argv[0]; - char buf[20]; - - while (find_next_token (&word_iterator, (unsigned int *) 0) != 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 *message) -{ - 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 make.h. */ - break; - - if (s <= end || end - beg < 0) - fatal (*expanding_var, "%s: '%s'", message, beg); -} - - - -static char * -func_word (char *o, char **argv, const char *funcname UNUSED) -{ - char *end_p=0; - int i=0; - char *p=0; - - /* Check the first argument. */ - check_numeric (argv[0], _("non-numeric first argument to `word' function")); - i = atoi (argv[0]); - - if (i == 0) - 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) - fatal (*expanding_var, - "invalid first argument to `wordlist' function: `%d'", start); - - count = atoi (argv[1]) - start + 1; - - if (count > 0) - { - char *p; - 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); - char *body = argv[2]; - - int doneany = 0; - char *list_iterator = list; - char *p; - unsigned int len; - register 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; - - { - char save = p[len]; - - p[len] = '\0'; - free (var->value); - var->value = (char *) xstrdup ((char*) p); - p[len] = save; - } - - 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; - int save_c; -}; - -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 = streq (funcname, "filter"); - char *pat_iterator = argv[0]; - 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. */ - - pattail = &pathead; - while ((p = find_next_token (&pat_iterator, &len)) != 0) - { - struct a_pattern *pat = (struct a_pattern *) alloca (sizeof (struct a_pattern)); - - *pattail = pat; - pattail = &pat->next; - - if (*pat_iterator != '\0') - ++pat_iterator; - - pat->str = p; - pat->length = len; - pat->save_c = p[len]; - p[len] = '\0'; - pat->percent = find_percent (p); - if (pat->percent == 0) - literals++; - } - *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 = (struct a_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 = (struct a_word *) 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; - } - - for (pp = pathead; pp != 0; pp = pp->next) - pp->str[pp->length] = pp->save_c; - - if (hashing) - hash_free (&a_word_table, 0); - - return o; -} - - -static char * -func_strip (char *o, char **argv, const char *funcname UNUSED) -{ - char *p = argv[0]; - int doneany =0; - - while (*p != '\0') - { - int i=0; - char *word_start=0; - - 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 = (char *) 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': - fatal (reading_file, "%s", msg); - - case 'w': - error (reading_file, "%s", msg); - break; - - case 'i': - printf ("%s\n", msg); - fflush(stdout); - break; - - default: - 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) -{ - char **words = 0; - int nwords = 0; - register int wordi = 0; - - /* Chop ARGV[0] into words and put them in WORDS. */ - char *t = argv[0]; - char *p; - unsigned int len; - int i; - - while ((p = find_next_token (&t, &len)) != 0) - { - if (wordi >= nwords - 1) - { - nwords = (2 * nwords) + 5; - words = (char **) xrealloc ((char *) words, - nwords * sizeof (char *)); - } - words[wordi++] = savestring (p, len); - } - - if (!wordi) - return o; - - /* Now sort the list of words. */ - qsort ((char *) words, wordi, sizeof (char *), alpha_compare); - - /* Now write the sorted list. */ - 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); - } - free (words[i]); - } - /* 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[0]) - { - char *expansion; - - expansion = expand_argument (argv[0], 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; - int result; - - while (1) - { - const char *begp = *argv; - const char *endp = begp + strlen (*argv) - 1; - - /* 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. -*/ - -static 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]); - - restore_variable_buffer (buf, len); - - 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) -{ - 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; - } - } - *(++last_nonnl) = '\0'; - *length = last_nonnl - buffer; -} - - - -int shell_function_pid = 0, shell_function_completed; - - -#ifdef WINDOWS32 -/*untested*/ - -#include -#include -#include "sub_proc.h" - - -void -windows32_openpipe (int *pipedes, int *pid_p, char **command_argv, char **envp) -{ - SECURITY_ATTRIBUTES saAttr; - HANDLE hIn; - HANDLE hErr; - HANDLE hChildOutRd; - HANDLE hChildOutWr; - HANDLE hProcess; - - - saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (DuplicateHandle (GetCurrentProcess(), - GetStdHandle(STD_INPUT_HANDLE), - GetCurrentProcess(), - &hIn, - 0, - TRUE, - DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(In) failed (e=%ld)\n"), - GetLastError()); - - } - if (DuplicateHandle(GetCurrentProcess(), - GetStdHandle(STD_ERROR_HANDLE), - GetCurrentProcess(), - &hErr, - 0, - TRUE, - DUPLICATE_SAME_ACCESS) == FALSE) { - fatal (NILF, _("create_child_process: DuplicateHandle(Err) failed (e=%ld)\n"), - GetLastError()); - } - - if (!CreatePipe(&hChildOutRd, &hChildOutWr, &saAttr, 0)) - fatal (NILF, _("CreatePipe() failed (e=%ld)\n"), GetLastError()); - - hProcess = process_init_fd(hIn, hChildOutWr, hErr); - - if (!hProcess) - fatal (NILF, _("windows32_openpipe (): process_init_fd() failed\n")); - - /* make sure that CreateProcess() has Path it needs */ - sync_Path_environment(); - - 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 = (int) hProcess; - - /* set up to read data from child */ - pipedes[0] = _open_osfhandle((long) hChildOutRd, O_RDONLY); - - /* this will be closed almost right away */ - pipedes[1] = _open_osfhandle((long) hChildOutWr, O_APPEND); - } else { - /* reap/cleanup the failed process */ - process_cleanup(hProcess); - - /* close handles which were duplicated, they weren't used */ - CloseHandle(hIn); - CloseHandle(hErr); - - /* close pipe handles, they won't be used */ - CloseHandle(hChildOutRd); - CloseHandle(hChildOutWr); - - /* set status for return */ - pipedes[0] = pipedes[1] = -1; - *pid_p = -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 ...) */ -#define func_shell 0 - -#else -#ifndef _AMIGA -static char * -func_shell (char *o, char **argv, const char *funcname UNUSED) -{ - char* batch_filename = NULL; - -#ifdef __MSDOS__ - FILE *fpipe; -#endif - char **command_argv; - char *error_prefix; - char **envp; - int pipedes[2]; - int pid; - -#ifndef __MSDOS__ - /* Construct the argument list. */ - command_argv = construct_command_argv (argv[0], - (char **) NULL, (struct file *) 0, - &batch_filename); - if (command_argv == 0) - return o; -#endif - - /* Using a target environment for `shell' loses in cases like: - export var = $(shell echo foobie) - 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. - - envp = target_environment (NILF); - */ - - envp = environ; - - /* For error messages. */ - if (reading_file && reading_file->filenm) - { - error_prefix = (char *) alloca (strlen (reading_file->filenm)+11+4); - sprintf (error_prefix, - "%s:%lu: ", reading_file->filenm, reading_file->lineno); - } - else - error_prefix = ""; - -#ifdef WINDOWS32 - - windows32_openpipe (pipedes, &pid, command_argv, envp); - - if (pipedes[0] < 0) { - /* open of the pipe failed, mark as failed execution */ - shell_function_completed = -1; - - return o; - } else - -#elif defined(__MSDOS__) - - fpipe = msdos_openpipe (pipedes, &pid, argv[0]); - if (pipedes[0] < 0) - { - perror_with_name (error_prefix, "pipe"); - return o; - } - -#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 (0, pipedes[1], command_argv, envp); - if (pid < 0) - perror_with_name (error_prefix, "spawn"); - -# else /* ! __EMX__ */ - - pid = vfork (); - if (pid < 0) - perror_with_name (error_prefix, "fork"); - else if (pid == 0) - child_execute_job (0, pipedes[1], 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 ((char *) command_argv); - - /* Close the write side of the pipe. */ - (void) close (pipedes[1]); -#endif - - /* Set up and read from the pipe. */ - - maxlen = 200; - buffer = (char *) xmalloc (maxlen + 1); - - /* Read from the pipe until it gets EOF. */ - for (i = 0; ; i += cc) - { - if (i == maxlen) - { - maxlen += 512; - buffer = (char *) 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); - - 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); - o = variable_buffer_output (o, buffer, i); - } - - free (buffer); - } - - return o; -} - -#else /* _AMIGA */ - -/* Do the Amiga version of func_shell. */ - -static char * -func_shell (char *o, char **argv, const char *funcname) -{ - /* 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], (char **) NULL, - (struct file *) 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 main.c:open_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 = (char *) 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); - o = variable_buffer_output (o, buffer, i); - free (buffer); - return o; -} -#endif /* _AMIGA */ -#endif /* !VMS */ - -#ifdef EXPERIMENTAL - -/* - equality. Return is string-boolean, ie, the empty string is false. - */ -static char * -func_eq (char *o, char **argv, char *funcname) -{ - 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) -{ - 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 - - -/* 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; - - if (name[0] == '\0' || apath == NULL) - return NULL; - - apath_limit = apath + GET_PATH_MAX; - - if (name[0] != '/') - { - /* It is unlikely we would make it until here but just to make sure. */ - if (!starting_directory) - return NULL; - - strcpy (apath, starting_directory); - - dest = strchr (apath, '\0'); - } - else - { - apath[0] = '/'; - dest = apath + 1; - } - - for (start = end = name; *start != '\0'; start = end) - { - unsigned long len; - - /* Skip sequence of multiple path-separators. */ - while (*start == '/') - ++start; - - /* Find end of path component. */ - for (end = start; *end != '\0' && *end != '/'; ++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 + 1) - while ((--dest)[-1] != '/'); - } - else - { - if (dest[-1] != '/') - *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 + 1 && dest[-1] == '/') - --dest; - - *dest = '\0'; - - return apath; -} - - -static char * -func_realpath (char *o, char **argv, const char *funcname UNUSED) -{ - /* Expand the argument. */ - char *p = argv[0]; - char *path = 0; - int doneany = 0; - unsigned int len = 0; - PATH_VAR (in); - PATH_VAR (out); - - while ((path = find_next_token (&p, &len)) != 0) - { - if (len < GET_PATH_MAX) - { - strncpy (in, path, len); - in[len] = '\0'; - - if - ( -#ifdef HAVE_REALPATH - realpath (in, out) -#else - abspath (in, out) -#endif - ) - { - 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_abspath (char *o, char **argv, const char *funcname UNUSED) -{ - /* Expand the argument. */ - char *p = argv[0]; - char *path = 0; - int doneany = 0; - unsigned int len = 0; - PATH_VAR (in); - PATH_VAR (out); - - while ((path = find_next_token (&p, &len)) != 0) - { - if (len < GET_PATH_MAX) - { - 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 PARAMS ((char *o, char **argv, const char *funcname)); - - -static struct function_table_entry function_table_init[] = -{ - /* Name/size */ /* MIN MAX EXP? Function */ - { STRING_SIZE_TUPLE("abspath"), 0, 1, 1, func_abspath}, - { STRING_SIZE_TUPLE("addprefix"), 2, 2, 1, func_addsuffix_addprefix}, - { STRING_SIZE_TUPLE("addsuffix"), 2, 2, 1, func_addsuffix_addprefix}, - { STRING_SIZE_TUPLE("basename"), 0, 1, 1, func_basename_dir}, - { STRING_SIZE_TUPLE("dir"), 0, 1, 1, func_basename_dir}, - { STRING_SIZE_TUPLE("notdir"), 0, 1, 1, func_notdir_suffix}, - { STRING_SIZE_TUPLE("subst"), 3, 3, 1, func_subst}, - { STRING_SIZE_TUPLE("suffix"), 0, 1, 1, func_notdir_suffix}, - { STRING_SIZE_TUPLE("filter"), 2, 2, 1, func_filter_filterout}, - { STRING_SIZE_TUPLE("filter-out"), 2, 2, 1, func_filter_filterout}, - { STRING_SIZE_TUPLE("findstring"), 2, 2, 1, func_findstring}, - { STRING_SIZE_TUPLE("firstword"), 0, 1, 1, func_firstword}, - { STRING_SIZE_TUPLE("flavor"), 0, 1, 1, func_flavor}, - { STRING_SIZE_TUPLE("join"), 2, 2, 1, func_join}, - { STRING_SIZE_TUPLE("lastword"), 0, 1, 1, func_lastword}, - { STRING_SIZE_TUPLE("patsubst"), 3, 3, 1, func_patsubst}, - { STRING_SIZE_TUPLE("realpath"), 0, 1, 1, func_realpath}, - { STRING_SIZE_TUPLE("shell"), 0, 1, 1, func_shell}, - { STRING_SIZE_TUPLE("sort"), 0, 1, 1, func_sort}, - { STRING_SIZE_TUPLE("strip"), 0, 1, 1, func_strip}, - { STRING_SIZE_TUPLE("wildcard"), 0, 1, 1, func_wildcard}, - { STRING_SIZE_TUPLE("word"), 2, 2, 1, func_word}, - { STRING_SIZE_TUPLE("wordlist"), 3, 3, 1, func_wordlist}, - { STRING_SIZE_TUPLE("words"), 0, 1, 1, func_words}, - { STRING_SIZE_TUPLE("origin"), 0, 1, 1, func_origin}, - { STRING_SIZE_TUPLE("foreach"), 3, 3, 0, func_foreach}, - { STRING_SIZE_TUPLE("call"), 1, 0, 1, func_call}, - { STRING_SIZE_TUPLE("info"), 0, 1, 1, func_error}, - { STRING_SIZE_TUPLE("error"), 0, 1, 1, func_error}, - { STRING_SIZE_TUPLE("warning"), 0, 1, 1, func_error}, - { STRING_SIZE_TUPLE("if"), 2, 3, 0, func_if}, - { STRING_SIZE_TUPLE("or"), 1, 0, 0, func_or}, - { STRING_SIZE_TUPLE("and"), 1, 0, 0, func_and}, - { STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value}, - { STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval}, -#ifdef EXPERIMENTAL - { STRING_SIZE_TUPLE("eq"), 2, 2, 1, func_eq}, - { STRING_SIZE_TUPLE("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) -{ - if (argc < (int)entry_p->minimum_args) - fatal (*expanding_var, - _("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 none do, so just test it for all functions here - rather than in each one. We can change it later if necessary. */ - - if (!argc) - return o; - - if (!entry_p->func_ptr) - fatal (*expanding_var, - _("unimplemented on this platform: function `%s'"), entry_p->name); - - return entry_p->func_ptr (o, argv, entry_p->name); -} - -/* 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, char **stringp) -{ - const struct function_table_entry *entry_p; - char openparen = (*stringp)[0]; - char closeparen = openparen == '(' ? ')' : '}'; - char *beg; - char *end; - int count = 0; - register char *p; - 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, - _("unterminated call to function `%s': missing `%c'"), - entry_p->name, closeparen); - - *stringp = end; - - /* Get some memory to store the arg pointers. */ - argvp = argv = (char **) 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) - { - int len = end - beg; - - p = xmalloc (len+1); - memcpy (p, beg, len); - p[len] = '\0'; - beg = p; - end = beg + len; - } - - for (p=beg, nargs=0; p <= end; ++argvp) - { - char *next; - - ++nargs; - - if (nargs == entry_p->maximum_args - || (! (next = find_next_argument (openparen, closeparen, p, end)))) - next = end; - - if (entry_p->expand_args) - *argvp = expand_argument (p, next); - else - { - *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 (beg); - - 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 (*fname != '\0' && 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 = (char *) 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 -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)); -} diff --git a/src/bin/make/getloadavg.c b/src/bin/make/getloadavg.c deleted file mode 100644 index 9367e473a5..0000000000 --- a/src/bin/make/getloadavg.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* Get the system load averages. -Copyright (C) 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, -1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free -Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* 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; - bzero ((char *) &stats, 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 "make.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 */ diff --git a/src/bin/make/getopt.c b/src/bin/make/getopt.c deleted file mode 100644 index f0fac4fe5e..0000000000 --- a/src/bin/make/getopt.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* 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, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, -1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software -Foundation, Inc. - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@gnu.org. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* 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 */ diff --git a/src/bin/make/getopt.h b/src/bin/make/getopt.h deleted file mode 100644 index 80efe9652f..0000000000 --- a/src/bin/make/getopt.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Declarations for getopt. -Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@gnu.org. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -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 */ diff --git a/src/bin/make/getopt1.c b/src/bin/make/getopt1.c deleted file mode 100644 index 9ad51274b5..0000000000 --- a/src/bin/make/getopt1.c +++ /dev/null @@ -1,180 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. -Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software -Foundation, Inc. - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@gnu.org. - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#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 */ diff --git a/src/bin/make/gettext.h b/src/bin/make/gettext.h deleted file mode 100644 index 17e999147c..0000000000 --- a/src/bin/make/gettext.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Convenience header for conditional use of GNU . -Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, -2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -#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 */ diff --git a/src/bin/make/glob/COPYING.LIB b/src/bin/make/glob/COPYING.LIB deleted file mode 100644 index bbe3fe1987..0000000000 --- a/src/bin/make/glob/COPYING.LIB +++ /dev/null @@ -1,481 +0,0 @@ - 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! diff --git a/src/bin/make/glob/Jamfile b/src/bin/make/glob/Jamfile deleted file mode 100644 index f133eaa393..0000000000 --- a/src/bin/make/glob/Jamfile +++ /dev/null @@ -1,17 +0,0 @@ -SubDir HAIKU_TOP src bin make glob ; - -SetSubDirSupportedPlatformsBeOSCompatible ; - -# filter warnings we don't want here -TARGET_WARNING_CCFLAGS = [ FFilter $(TARGET_WARNING_CCFLAGS) - : -Wall -Wmissing-prototypes -Wsign-compare ] ; - -SubDirCcFlags -DHAVE_CONFIG_H ; - -SubDirSysHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; -SubDirSysHdrs [ FDirName $(SUBDIR) ] ; - -StaticLibrary libglob.a : - fnmatch.c - glob.c -; diff --git a/src/bin/make/glob/fnmatch.c b/src/bin/make/glob/fnmatch.c deleted file mode 100644 index 49dd2f5900..0000000000 --- a/src/bin/make/glob/fnmatch.c +++ /dev/null @@ -1,488 +0,0 @@ -/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 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__. */ diff --git a/src/bin/make/glob/fnmatch.h b/src/bin/make/glob/fnmatch.h deleted file mode 100644 index 07a258f61c..0000000000 --- a/src/bin/make/glob/fnmatch.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 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__ || !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. */ - -#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 */ diff --git a/src/bin/make/glob/glob.c b/src/bin/make/glob/glob.c deleted file mode 100644 index 1af0a5ddce..0000000000 --- a/src/bin/make/glob/glob.c +++ /dev/null @@ -1,1426 +0,0 @@ -/* Copyright (C) 1991,92,93,94,95,96,97,98,99 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(__BEOS__) || defined(__HAIKU__)) && !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 - -#ifndef __GNU_LIBRARY__ -# 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__ */ - - -#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; - } - - 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. */ diff --git a/src/bin/make/glob/glob.h b/src/bin/make/glob/glob.h deleted file mode 100644 index c3ab64ad6c..0000000000 --- a/src/bin/make/glob/glob.h +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright (C) 1991, 92, 95, 96, 97, 98 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 aready 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 */ diff --git a/src/bin/make/hash.c b/src/bin/make/hash.c deleted file mode 100644 index f11a74fc66..0000000000 --- a/src/bin/make/hash.c +++ /dev/null @@ -1,332 +0,0 @@ -/* hash.c -- hash table maintenance - Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc. - Written by Greg McGary - -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; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "hash.h" - -#define CALLOC(t, n) ((t *) calloc (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 %ld bytes for hash table: memory exhausted"), - ht->ht_size * sizeof(struct token *)); - exit (1); - } - - 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 ? *slot : 0; - 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; -} diff --git a/src/bin/make/hash.h b/src/bin/make/hash.h deleted file mode 100644 index d0ba835625..0000000000 --- a/src/bin/make/hash.h +++ /dev/null @@ -1,233 +0,0 @@ -/* hash.h -- decls for hash table -Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc. -Written by Greg McGary - -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; see the file COPYING. If not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#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; - 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 */ - 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 */ -}; - -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. */ - -#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 = strcmp ((X), (Y)); \ -} while (0) -#define return_STRING_COMPARE(X, Y) do { \ - return 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 = strncmp ((X), (Y), (N)); \ -} while (0) -#define return_STRING_N_COMPARE(X, Y, N) do { \ - return 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 = strcmpi ((X), (Y)); \ -} while (0) -#define return_ISTRING_COMPARE(X, Y) do { \ - return strcmpi ((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_ */ diff --git a/src/bin/make/implicit.c b/src/bin/make/implicit.c deleted file mode 100644 index 014828fead..0000000000 --- a/src/bin/make/implicit.c +++ /dev/null @@ -1,982 +0,0 @@ -/* Implicit rule searching for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.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 PARAMS ((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; -} - - -/* Struct idep captures information about implicit prerequisites - that come from implicit rules. */ -struct idep -{ - struct idep *next; /* struct dep -compatible interface */ - char *name; /* name of the prerequisite */ - struct file *intermediate_file; /* intermediate file, 0 otherwise */ - char *intermediate_pattern; /* pattern for intermediate file */ - unsigned char had_stem; /* had % substituted with stem */ - unsigned char ignore_mtime; /* ignore_mtime flag */ -}; - -static void -free_idep_chain (struct idep *p) -{ - struct idep *n; - - for (; p != 0; p = n) - { - n = p->next; - - if (p->name) - { - struct file *f = p->intermediate_file; - - if (f != 0 - && (f->stem < f->name || f->stem > f->name + strlen (f->name))) - free (f->stem); - - free (p->name); - } - - free (p); - } -} - - -/* 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 char * -get_next_word (char *buffer, unsigned int *length) -{ - 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; -} - -/* 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. */ - 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). */ - 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 *intermediate_file = 0; - - /* This linked list records all the prerequisites actually - found for a rule along with some other useful information - (see struct idep for details). */ - struct idep* deps = 0; - - /* 1 if we need to remove explicit prerequisites, 0 otherwise. */ - unsigned int remove_explicit_deps = 0; - - /* Names of possible dependencies are constructed in this buffer. */ - register char *depname = (char *) alloca (namelen + max_pattern_dep_length); - - /* The start and length of the stem of FILENAME for the current rule. */ - register char *stem = 0; - register unsigned int stemlen = 0; - register unsigned int fullstemlen = 0; - - /* Buffer in which we store all the rules that are possibly applicable. */ - struct rule **tryrules - = (struct rule **) xmalloc (num_pattern_rules * max_pattern_targets - * sizeof (struct rule *)); - - /* Number of valid elements in TRYRULES. */ - unsigned int nrules; - - /* The numbers of the rule targets of each rule - in TRYRULES that matched the target file. */ - unsigned int *matches - = (unsigned int *) alloca (num_pattern_rules * sizeof (unsigned int)); - - /* Each element is nonzero if LASTSLASH was used in - matching the corresponding element of TRYRULES. */ - char *checked_lastslash - = (char *) alloca (num_pattern_rules * sizeof (char)); - - /* 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 matched a pattern-rule target - that is not just `%'. */ - int specific_rule_matched = 0; - - unsigned int i = 0; /* uninit checks OK */ - struct rule *rule; - struct dep *dep, *expl_d; - - char *p, *vname; - - struct idep *d; - struct idep **id_ptr; - struct dep **d_ptr; - - 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; - } - - /* 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) - { - /* 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 (i = 0; rule->targets[i] != 0; ++i) - { - char *target = rule->targets[i]; - char *suffix = rule->suffixes[i]; - 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[i] > 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[i] + 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. */ - unsigned int difference = lastslash - filename + 1; - if (difference > stemlen) - continue; - stemlen -= difference; - stem += difference; - } - - /* 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; - matches[nrules] = i; - checked_lastslash[nrules] = check_lastslash; - ++nrules; - } - } - - /* 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 (i = 0; i < nrules; ++i) - if (!tryrules[i]->terminal) - { - register unsigned int j; - for (j = 0; tryrules[i]->targets[j] != 0; ++j) - if (tryrules[i]->targets[j][1] == '\0') - break; - if (tryrules[i]->targets[j] != 0) - tryrules[i] = 0; - } - - /* We are going to do second expansion so initialize file variables - for the rule. */ - initialize_file_variables (file, 0); - - /* Try each rule once without intermediate files, then once with them. */ - for (intermed_ok = 0; intermed_ok == !!intermed_ok; ++intermed_ok) - { - /* Try each pattern rule till we find one that applies. - If it does, expand its dependencies (as substituted) - and chain them in DEPS. */ - - for (i = 0; i < nrules; i++) - { - struct file *f; - unsigned int failed = 0; - int check_lastslash; - int file_variables_set = 0; - - rule = tryrules[i]; - - remove_explicit_deps = 0; - - /* 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; - - /* Mark this rule as in use so a recursive - pattern_search won't try to use it. */ - rule->in_use = 1; - - /* From the lengths of the filename and the matching pattern parts, - find the stem: the part of the filename that matches the %. */ - stem = filename - + (rule->suffixes[matches[i]] - rule->targets[matches[i]]) - 1; - stemlen = namelen - rule->lens[matches[i]] + 1; - check_lastslash = checked_lastslash[i]; - if (check_lastslash) - { - stem += lastslash - filename + 1; - stemlen -= (lastslash - filename) + 1; - } - - DBS (DB_IMPLICIT, (_("Trying pattern rule with stem `%.*s'.\n"), - (int) stemlen, stem)); - - strncpy (stem_str, stem, stemlen); - stem_str[stemlen] = '\0'; - - /* Temporary assign STEM to file->stem (needed to set file - variables below). */ - file->stem = stem_str; - - /* Try each dependency; see if it "exists". */ - - for (dep = rule->deps; dep != 0; dep = dep->next) - { - unsigned int len; - char *p2; - unsigned int order_only = 0; /* Set if '|' was seen. */ - - /* 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. */ - - p = get_next_word (dep->name, &len); - - while (1) - { - int add_dir = 0; - int had_stem = 0; - - if (p == 0) - break; /* No more words */ - - /* Is there a pattern in this prerequisite? */ - - for (p2 = p; p2 < p + len && *p2 != '%'; ++p2) - ; - - if (dep->need_2nd_expansion) - { - /* If the dependency name has %, substitute the stem. - - Watch out, we are going to do something tricky - here. If we just replace % with the stem value, - later, when we do the second expansion, we will - re-expand this stem value once again. This is not - good especially 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. */ - - if (p2 < p + len) - { - register unsigned int i = p2 - p; - bcopy (p, depname, i); - bcopy ("$*", depname + i, 2); - bcopy (p2 + 1, depname + i + 2, len - i - 1); - depname[len + 2 - 1] = '\0'; - - if (check_lastslash) - add_dir = 1; - - had_stem = 1; - } - else - { - bcopy (p, depname, len); - depname[len] = '\0'; - } - - /* Set file variables. Note that we cannot do it once - at the beginning of the function because of the stem - value. */ - if (!file_variables_set) - { - set_file_variables (file); - file_variables_set = 1; - } - - p2 = variable_expand_for_file (depname, file); - } - else - { - if (p2 < p + len) - { - register unsigned int i = p2 - p; - bcopy (p, depname, i); - bcopy (stem_str, depname + i, stemlen); - bcopy (p2 + 1, depname + i + stemlen, len - i - 1); - depname[len + stemlen - 1] = '\0'; - - if (check_lastslash) - add_dir = 1; - - had_stem = 1; - } - else - { - bcopy (p, depname, len); - depname[len] = '\0'; - } - - p2 = depname; - } - - /* Parse the dependencies. */ - - while (1) - { - id_ptr = &deps; - - for (; *id_ptr; id_ptr = &(*id_ptr)->next) - ; - - *id_ptr = (struct idep *) - multi_glob ( - parse_file_seq (&p2, - order_only ? '\0' : '|', - sizeof (struct idep), - 1), sizeof (struct idep)); - - /* @@ It would be nice to teach parse_file_seq or - multi_glob to add prefix. This would save us some - reallocations. */ - - if (order_only || add_dir || had_stem) - { - unsigned long l = lastslash - filename + 1; - - for (d = *id_ptr; d != 0; d = d->next) - { - if (order_only) - d->ignore_mtime = 1; - - if (add_dir) - { - char *p = d->name; - - d->name = xmalloc (strlen (p) + l + 1); - - bcopy (filename, d->name, l); - bcopy (p, d->name + l, strlen (p) + 1); - - free (p); - } - - if (had_stem) - d->had_stem = 1; - } - } - - if (!order_only && *p2) - { - ++p2; - order_only = 1; - continue; - } - - break; - } - - p += len; - p = get_next_word (p, &len); - } - } - - /* Reset the stem in FILE. */ - - file->stem = 0; - - /* @@ This loop can be combined with the previous one. I do - it separately for now for transparency.*/ - - for (d = deps; d != 0; d = d->next) - { - char *name = d->name; - - if (file_impossible_p (name)) - { - /* If this dependency has already been ruled "impossible", - then the rule fails and don't bother trying it on the - second pass either since we know that will fail too. */ - DBS (DB_IMPLICIT, - (d->had_stem - ? _("Rejecting impossible implicit prerequisite `%s'.\n") - : _("Rejecting impossible rule prerequisite `%s'.\n"), - name)); - tryrules[i] = 0; - - failed = 1; - break; - } - - DBS (DB_IMPLICIT, - (d->had_stem - ? _("Trying implicit prerequisite `%s'.\n") - : _("Trying rule prerequisite `%s'.\n"), name)); - - /* If this prerequisite also happened to be explicitly mentioned - for FILE skip all the test below since it it has to be built - anyway, 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), name)) - break; - if (expl_d != 0) - 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 (((f = lookup_file (name)) != 0 && f->is_target) - /*|| ((!dep->changed || check_lastslash) && */ - || file_exists_p (name)) - continue; - - /* This code, given FILENAME = "lib/foo.o", dependency name - "lib/foo.c", and VPATH=src, searches for "src/lib/foo.c". */ - vname = name; - if (vpath_search (&vname, (FILE_TIMESTAMP *) 0)) - { - DBS (DB_IMPLICIT, - (_("Found prerequisite `%s' as VPATH `%s'\n"), - name, - vname)); - - free (vname); - 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) - { - if (intermediate_file == 0) - intermediate_file - = (struct file *) alloca (sizeof (struct file)); - - DBS (DB_IMPLICIT, - (_("Looking for a rule with intermediate file `%s'.\n"), - name)); - - bzero ((char *) intermediate_file, sizeof (struct file)); - intermediate_file->name = name; - if (pattern_search (intermediate_file, - 0, - depth + 1, - recursions + 1)) - { - d->intermediate_file = intermediate_file; - d->intermediate_pattern = intermediate_file->name; - - intermediate_file->name = xstrdup (name); - intermediate_file = 0; - - 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 (intermediate_file->variables) - free_variable_set (intermediate_file->variables); - file_impossible (name); - } - - /* A dependency of this rule does not exist. Therefore, - this rule fails. */ - failed = 1; - break; - } - - /* This rule is no longer `in use' for recursive searches. */ - rule->in_use = 0; - - if (failed) - { - /* This pattern rule does not apply. If some of its - dependencies succeeded, free the data structure - describing them. */ - free_idep_chain (deps); - deps = 0; - } - else - /* This pattern rule does apply. Stop looking for one. */ - break; - } - - /* If we found an applicable rule without - intermediate files, don't try with them. */ - if (i < nrules) - break; - - rule = 0; - } - - /* RULE is nil if the loop went all the way - through the list and everything failed. */ - if (rule == 0) - goto done; - - foundrule = i; - - /* 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[matches[foundrule]]; - - /* FOUND_FILES lists the dependencies for the rule we found. - This includes the intermediate files, if any. - Convert them into entries on the deps-chain of FILE. */ - - if (remove_explicit_deps) - { - /* Remove all the dependencies that didn't come from - this implicit rule. */ - - dep = file->deps; - while (dep != 0) - { - struct dep *next = dep->next; - free_dep (dep); - dep = next; - } - file->deps = 0; - } - - expl_d = file->deps; /* We will add them at the end. */ - d_ptr = &file->deps; - - for (d = deps; d != 0; d = d->next) - { - register char *s; - - if (d->intermediate_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 = d->intermediate_file; - register 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->also_make = imf->also_make; - f->is_target = 1; - - if (!f->precious) - { - imf = lookup_file (d->intermediate_pattern); - if (imf != 0 && imf->precious) - f->precious = 1; - } - - f->intermediate = 1; - f->tried_implicit = 1; - for (dep = f->deps; dep != 0; dep = dep->next) - { - dep->file = enter_file (dep->name); - /* enter_file uses dep->name _if_ we created a new file. */ - if (dep->name != dep->file->name) - free (dep->name); - dep->name = 0; - dep->file->tried_implicit |= dep->changed; - } - } - - dep = alloc_dep (); - dep->ignore_mtime = d->ignore_mtime; - s = d->name; /* Hijacking the name. */ - d->name = 0; - if (recursions == 0) - { - dep->file = lookup_file (s); - if (dep->file == 0) - /* enter_file consumes S's storage. */ - dep->file = enter_file (s); - else - /* A copy of S is already allocated in DEP->file->name. - So we can free S. */ - free (s); - } - else - { - dep->name = s; - } - - if (d->intermediate_file == 0 && tryrules[foundrule]->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; - } - - *d_ptr = dep; - d_ptr = &dep->next; - } - - *d_ptr = expl_d; - - if (!checked_lastslash[foundrule]) - { - /* Always allocate new storage, since STEM might be - on the stack for an intermediate file. */ - file->stem = savestring (stem, stemlen); - fullstemlen = stemlen; - } - else - { - int dirlen = (lastslash + 1) - filename; - - /* We want to prepend the directory from - the original FILENAME onto the stem. */ - fullstemlen = dirlen + stemlen; - file->stem = (char *) xmalloc (fullstemlen + 1); - bcopy (filename, file->stem, dirlen); - bcopy (stem, file->stem + dirlen, stemlen); - file->stem[fullstemlen] = '\0'; - } - - file->cmds = rule->cmds; - file->is_target = 1; - - /* Set precious flag. */ - { - struct file *f = lookup_file (rule->targets[matches[foundrule]]); - 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->targets[1] != 0) - for (i = 0; rule->targets[i] != 0; ++i) - if (i != matches[foundrule]) - { - struct file *f; - struct dep *new = alloc_dep (); - - /* GKM FIMXE: handle '|' here too */ - new->name = p = (char *) xmalloc (rule->lens[i] + fullstemlen + 1); - bcopy (rule->targets[i], p, - rule->suffixes[i] - rule->targets[i] - 1); - p += rule->suffixes[i] - rule->targets[i] - 1; - bcopy (file->stem, p, fullstemlen); - p += fullstemlen; - bcopy (rule->suffixes[i], p, - rule->lens[i] - (rule->suffixes[i] - rule->targets[i]) + 1); - new->file = enter_file (new->name); - new->next = file->also_make; - - /* Set precious flag. */ - f = lookup_file (rule->targets[i]); - 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_idep_chain (deps); - free (tryrules); - - return rule != 0; -} diff --git a/src/bin/make/job.c b/src/bin/make/job.c deleted file mode 100644 index a81cd81cea..0000000000 --- a/src/bin/make/job.c +++ /dev/null @@ -1,3070 +0,0 @@ -/* Job execution and handling for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#include - -#include "job.h" -#include "debug.h" -#include "filedef.h" -#include "commands.h" -#include "variable.h" -#include "debug.h" - -#include - -/* Default shell to use. */ -#ifdef WINDOWS32 -#include - -char *default_shell = "sh.exe"; -int no_default_sh_exe = 1; -int batch_mode_shell = 1; -HANDLE main_thread; - -#elif defined (_AMIGA) - -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). */ -char *default_shell = "command.com"; -int batch_mode_shell = 0; - -#elif defined (__EMX__) - -char *default_shell = "/bin/sh"; -int batch_mode_shell = 0; - -#elif defined (VMS) - -# include -char default_shell[] = ""; -int batch_mode_shell = 0; - -#elif defined (__riscos__) - -char default_shell[] = ""; -int batch_mode_shell = 0; - -#else - -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 PARAMS ((int *)); -#endif - -#ifdef WINDOWS32 -# include -# include -# include -# include "sub_proc.h" -# include "w32err.h" -# include "pathstuff.h" -#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) -extern 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'. */ - -#ifndef HAVE_UNISTD_H -extern int dup2 (); -extern int execve (); -extern void _exit (); -# ifndef VMS -extern int geteuid (); -extern int getegid (); -extern int setgid (); -extern int getgid (); -# endif -#endif - -extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file)); - -extern int getloadavg PARAMS ((double loadavg[], int nelem)); -extern int start_remote_job PARAMS ((char **argv, char **envp, int stdin_fd, - int *is_remote, int *id_ptr, int *used_stdin)); -extern int start_remote_job_p PARAMS ((int)); -extern int remote_status PARAMS ((int *exit_code_ptr, int *signal_ptr, - int *coredump_ptr, int block)); - -RETSIGTYPE child_handler PARAMS ((int)); -static void free_child PARAMS ((struct child *)); -static void start_job_command PARAMS ((struct child *child)); -static int load_too_high PARAMS ((void)); -static int job_next_command PARAMS ((struct child *)); -static int start_waiting_job PARAMS ((struct child *)); - -/* 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 make.h. - */ -int -w32_kill(int 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 = NULL; - char temp_path[MAXPATHLEN]; /* need to know its length */ - unsigned path_size = GetTempPath(sizeof temp_path, temp_path); - int path_is_dot = 0; - unsigned uniq = 1; - const unsigned sizemax = strlen (base) + strlen (ext) + 10; - - if (path_size == 0) - { - path_size = GetCurrentDirectory (sizeof temp_path, temp_path); - path_is_dot = 1; - } - - while (path_size > 0 && - path_size + sizemax < sizeof temp_path && - uniq < 0x10000) - { - 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; - - /* 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 = map_windows32_error_to_string (er); - break; - } - } - else - { - const unsigned final_size = path_size + size + 1; - char *const path = (char *) xmalloc (final_size); - memcpy (path, temp_path, final_size); - *fd = _open_osfhandle ((long)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 == NULL) - error = _("Cannot create a temporary file\n"); - fatal (NILF, error); - - /* 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 (stricmp (name, known_os2shells[i]) == 0) /* strcasecmp() */ - return 0; /* not a unix shell */ - i++; - } - - /* in doubt assume a unix like shell */ - return 1; -} -#endif /* __EMX__ */ - - -/* 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 (char *target_name, int exit_code, int exit_sig, int coredump, - int ignored) -{ - if (ignored && silent_flag) - return; - -#ifdef VMS - if (!(exit_code & 1)) - error (NILF, - (ignored ? _("*** [%s] Error 0x%x (ignored)") - : _("*** [%s] Error 0x%x")), - target_name, exit_code); -#else - if (exit_sig == 0) - error (NILF, ignored ? _("[%s] Error %d (ignored)") : - _("*** [%s] Error %d"), - target_name, exit_code); - else - error (NILF, "*** [%s] %s%s", - target_name, strsignal (exit_sig), - coredump ? _(" (core dumped)") : ""); -#endif /* VMS */ -} - - -/* 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) -{ -#ifndef WINDOWS32 - WAIT_T status; - /* Initially, assume we have some. */ - int reap_more = 1; -#endif - -#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; - register 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) - 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 0x%08lx (%s) PID %ld %s\n"), - (unsigned long int) c, c->file->name, - (long) 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 - 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; - int werr; - HANDLE hcTID, hcPID; - 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 = 0x%08lx\n", - (unsigned long)main_thread)); - } - - /* wait for anything to finish */ - hPID = process_wait_for_any(); - if (hPID) - { - - /* was an error found on this process? */ - 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; - } - 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->remote == remote && c->pid == pid) - 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 0x%08lx PID %ld %s\n") - : _("Reaping winning child 0x%08lx PID %ld %s\n"), - (unsigned long int) c, (long) c->pid, - c->remote ? _(" (remote)") : "")); - - if (c->sh_batch_file) { - DB (DB_JOBS, (_("Cleaning up temp batch file %s\n"), - c->sh_batch_file)); - - /* just try and remove, don't care if this fails */ - remove (c->sh_batch_file); - - /* 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 (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->file->name, exit_code, exit_sig, coredump, 0); - - c->file->update_status = 2; - 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->file->name, - 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 = 2; - } - else - { - /* 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); - /* 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 != 0) - /* 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 = 0; - } - - /* When we get here, all the commands for C->file are finished - (or aborted) and C->file->update_status contains 0 or 2. 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 0x%08lx PID %ld%s from chain.\n"), - (unsigned long int) c, (long) 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; - - free_child (c); - - unblock_sigs (); - - /* 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) - die (2); - - /* Only block for one child. */ - block = 0; - } - - return; -} - -/* Free the storage allocated for CHILD. */ - -static void -free_child (struct child *child) -{ - if (!jobserver_tokens) - fatal (NILF, "INTERNAL: Freeing child 0x%08lx (%s) but no tokens left!\n", - (unsigned long int) 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. */ - - 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 0x%08lx (%s).\n"), - (unsigned long int) child, child->file->name)); - } - - --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 ((char *) child->command_lines); - } - - if (child->environment != 0) - { - register char **ep = child->environment; - while (*ep != 0) - free (*ep++); - free ((char *) child->environment); - } - - free ((char *) 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 - -#ifdef MAKE_JOBSERVER -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 - - bzero ((char *) &sa, 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. */ - alarm (set_handler ? 1 : 0); - sa.sa_handler = set_handler ? job_noop : 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 (struct child *child) -{ -#if !defined(_AMIGA) && !defined(WINDOWS32) - static int bad_stdin = -1; -#endif - register char *p; - int flags; -#ifdef VMS - char *argv; -#else - char **argv; -#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; - - /* Figure out an argument list from this command line. */ - - { - char *end = 0; -#ifdef VMS - argv = p; -#else - argv = construct_command_argv (p, &end, child->file, &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 ((char *) argv); -#endif - child->file->update_status = 1; - 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 ((char *) 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); - 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 = 0; - notice_finished_file (child->file); - } - return; - } - - /* Print out the command. If silent, we call `message' with null so it - can log the working directory before the command's own error messages - appear. */ - - message (0, (just_print_flag || (!(flags & COMMANDS_SILENT) && !silent_flag)) - ? "%s" : (char *) 0, 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] && !strcmp (argv[0], "/bin/sh")) -#endif - && (argv[1] - && argv[1][0] == '-' && argv[1][1] == 'c' && argv[1][2] == '\0') - && (argv[2] && argv[2][0] == ':' && argv[2][1] == '\0') - && argv[3] == NULL) - { - free (argv[0]); - free ((char *) 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 ((char *) argv); -#endif - goto next_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 ("vfork", ""); - goto error; - } - -#else - - parent_environ = environ; - -# 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 ? 0 : bad_stdin, 1, - 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 = vfork (); - 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); - - child_execute_job (child->good_stdin ? 0 : bad_stdin, 1, - argv, child->environment); - } - else if (child->pid < 0) - { - /* Fork failed! */ - unblock_sigs (); - perror_with_name ("vfork", ""); - 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(); - - hPID = process_easy(argv, child->environment); - - if (hPID != INVALID_HANDLE_VALUE) - child->pid = (int) 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 ((char *) argv); -#endif - - return; - - error: - child->file->update_status = 2; - notice_finished_file (child->file); - return; -} - -/* 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) -{ - 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); - - switch (f->command_state) - { - case cs_running: - c->next = children; - DB (DB_JOBS, (_("Putting child 0x%08lx (%s) PID %ld%s on the chain.\n"), - (unsigned long int) c, c->file->name, - (long) 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 = 0; - /* 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) -{ - register struct commands *cmds = file->cmds; - register struct child *c; - char **lines; - register 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 (); - - /* Reap any children that might have finished recently. */ - reap_children (0, 0); - - /* Chop the commands up into lines if they aren't already. */ - chop_commands (cmds); - - /* Expand the command lines and store the results in LINES. */ - lines = (char **) 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). */ - bcopy (in, out, 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) - strcpy (out, in); - - /* Finally, expand the line. */ - lines[i] = allocated_variable_expand_for_file (cmds->command_lines[i], - file); - } - - /* Start the command sequence, record it in a new - `struct child', and add that to the chain. */ - - c = (struct child *) xmalloc (sizeof (struct child)); - bzero ((char *)c, sizeof (struct child)); - c->file = file; - c->command_lines = lines; - 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; - - /* 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); - -#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... */ - - else if (job_fds[0] >= 0) - while (1) - { - char token; - int got_token; - int saved_errno; - - 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; - - /* 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]); - } - - /* Reap anything that's currently waiting. */ - reap_children (0, 0); - - /* Kick off any jobs we have waiting for an opportunity that - can run now (ie waiting for load). */ - start_waiting_jobs (); - - /* 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 (NILF, "INTERNAL: no children as we go to sleep on read\n"); - - /* 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); - - /* If we got one, we're done here. */ - if (got_token == 1) - { - DB (DB_JOBS, (_("Obtained token for child 0x%08lx (%s).\n"), - (unsigned long int) c, c->file->name)); - break; - } - - /* 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 - - ++jobserver_tokens; - - /* The job is now primed. Start it running. - (This will notice if there are in fact no commands.) */ - (void) start_waiting_job (c); - - 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); - - 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. */ - 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 (void) -{ - struct child *job; - - if (waiting_jobs == 0) - return; - - do - { - /* Check for recently deceased descendants. */ - reap_children (0, 0); - - /* 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) && waiting_jobs != 0); - - return; -} - -#ifndef WINDOWS32 - -/* EMX: Start a child process. This function returns the new pid. */ -# if defined __MSDOS__ || defined __EMX__ -int -child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) -{ - int pid; - /* stdin_fd == 0 means: nothing to do for stdin; - stdout_fd == 1 means: nothing to do for stdout */ - int save_stdin = (stdin_fd != 0) ? dup (0) : 0; - int save_stdout = (stdout_fd != 1) ? dup (1): 1; - - /* < 0 only if dup() failed */ - if (save_stdin < 0) - fatal (NILF, _("no more file handles: could not duplicate stdin\n")); - if (save_stdout < 0) - fatal (NILF, _("no more file handles: could not duplicate stdout\n")); - - /* Close unnecessary file handles for the child. */ - if (save_stdin != 0) - CLOSE_ON_EXEC (save_stdin); - if (save_stdout != 1) - CLOSE_ON_EXEC (save_stdout); - - /* Connect the pipes to the child process. */ - if (stdin_fd != 0) - (void) dup2 (stdin_fd, 0); - if (stdout_fd != 1) - (void) dup2 (stdout_fd, 1); - - /* stdin_fd and stdout_fd must be closed on exit because we are - still in the parent process */ - if (stdin_fd != 0) - CLOSE_ON_EXEC (stdin_fd); - if (stdout_fd != 1) - CLOSE_ON_EXEC (stdout_fd); - - /* Run the command. */ - pid = exec_command (argv, envp); - - /* Restore stdout/stdin of the parent and close temporary FDs. */ - if (stdin_fd != 0) - { - if (dup2 (save_stdin, 0) != 0) - fatal (NILF, _("Could not restore stdin\n")); - else - close (save_stdin); - } - - if (stdout_fd != 1) - { - if (dup2 (save_stdout, 1) != 1) - fatal (NILF, _("Could not restore stdout\n")); - else - close (save_stdout); - } - - return pid; -} - -#elif !defined (_AMIGA) && !defined (__MSDOS__) && !defined (VMS) - -/* UNIX: - Replace the current process with one executing the command in ARGV. - STDIN_FD and STDOUT_FD are used as the process's stdin and stdout; ENVP is - the environment of the new program. This function does not return. */ -void -child_execute_job (int stdin_fd, int stdout_fd, char **argv, char **envp) -{ - if (stdin_fd != 0) - (void) dup2 (stdin_fd, 0); - if (stdout_fd != 1) - (void) dup2 (stdout_fd, 1); - if (stdin_fd != 0) - (void) close (stdin_fd); - if (stdout_fd != 1) - (void) close (stdout_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 err = 0; - int exit_code = EXIT_FAILURE; - - /* make sure CreateProcess() has Path it needs */ - sync_Path_environment(); - - /* launch command */ - hPID = process_easy(argv, envp); - - /* make sure launch ok */ - if (hPID == INVALID_HANDLE_VALUE) - { - int i; - fprintf(stderr, - _("process_easy() failed 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(); - while (hWaitPID) - { - /* was an error found on this process? */ - 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 - fprintf(stderr, - _("make reaped child pid %ld, still waiting for pid %ld\n"), - (DWORD)hWaitPID, (DWORD)hPID); - } - - /* 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: - 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 (); - 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 = (char **) alloca ((1 + argc + 1) * sizeof (char *)); - new_argv[0] = 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) - 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 :-( */ - 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). */ - -static char ** -construct_command_argv_internal (char *line, char **restp, char *shell, - char *ifs, char **batch_filename_ptr) -{ -#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 char sh_chars_dos[] = "*?[];|<>%^&()"; - static 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 char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^"; - static 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", - 0 }; - - char *sh_chars; - char **sh_cmds; -#elif defined (__EMX__) - static char sh_chars_dos[] = "*?[];|<>%^&()"; - static 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 char sh_chars_os2[] = "*?[];|<>%^()\"'&"; - static 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 char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^~'"; - static 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 }; - char *sh_chars; - char **sh_cmds; - -#elif defined (_AMIGA) - static char sh_chars[] = "#;\"|<>()?*$`"; - static 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) - static char sh_chars_dos[] = "\"|&<>"; - static char *sh_cmds_dos[] = { "break", "call", "cd", "chcp", "chdir", "cls", - "copy", "ctty", "date", "del", "dir", "echo", - "erase", "exit", "for", "goto", "if", "if", "md", - "mkdir", "path", "pause", "prompt", "rd", "rem", - "ren", "rename", "rmdir", "set", "shift", "time", - "type", "ver", "verify", "vol", ":", 0 }; - static char sh_chars_sh[] = "#;\"*?[]&|<>(){}$`^"; - static 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 }; - char* sh_chars; - char** sh_cmds; -#elif defined(__riscos__) - static char sh_chars[] = ""; - static char *sh_cmds[] = { 0 }; -#else /* must be UNIX-ish */ - static char sh_chars[] = "#;\"*?[]&|<>(){}$`^~!"; - static char *sh_cmds[] = { ".", ":", "break", "case", "cd", "continue", - "eval", "exec", "exit", "export", "for", "if", - "login", "logout", "read", "readonly", "set", - "shift", "switch", "test", "times", "trap", - "umask", "wait", "while", 0 }; -#endif - register int i; - register char *p; - register char *ap; - char *end; - 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; - - /* 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 : "")); - - if (s1) - free (s1); - if (s2) - free (s2); - } - if (slow_flag) - goto slow; -#else /* not WINDOWS32 */ -#if defined (__MSDOS__) || defined (__EMX__) - else if (stricmp (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 != 0) - for (ap = ifs; *ap != '\0'; ++ap) - if (*ap != ' ' && *ap != '\t' && *ap != '\n') - goto slow; - - i = strlen (line) + 1; - - /* More than 1 arg per character is impossible. */ - new_argv = (char **) xmalloc (i * sizeof (char *)); - - /* All the args can fit in a buffer as big as LINE is. */ - ap = new_argv[0] = argstr = (char *) xmalloc (i); - end = ap + i; - - /* 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; - } - /* If there's a TAB here, skip it. */ - if (p[1] == '\t') - ++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; - else - *ap++ = *p; - } - else if (strchr (sh_chars, *p) != 0) - /* Not inside a string, but it's a special char. */ - 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 is a tab after a backslash-newline, remove it. */ - if (p[1] == '\t') - ++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; - } - 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; -# ifdef __EMX__ - /* 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 ((char *)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 ((char *)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 = (char *)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 = (char **) 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 -c LINE", with all special chars in LINE escaped. - Then recurse, expanding this command line to get the final - argument list. */ - - unsigned int shell_len = strlen (shell); -#ifndef VMS - static char minus_c[] = " -c "; -#else - static char minus_c[] = ""; -#endif - unsigned int line_len = strlen (line); - - char *new_line = (char *) alloca (shell_len + (sizeof (minus_c) - 1) - + (line_len * 2) + 1); - char *command_ptr = NULL; /* used for batch_mode_shell mode */ - -# ifdef __EMX__ /* is this necessary? */ - if (!unixy_shell) - minus_c[1] = '/'; /* " /c " */ -# endif - - ap = new_line; - bcopy (shell, ap, shell_len); - ap += shell_len; - bcopy (minus_c, ap, sizeof (minus_c) - 1); - ap += sizeof (minus_c) - 1; - command_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, but throw out - the next char if it's a TAB. 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++) = '\\'; - *(ap++) = '\\'; - *(ap++) = '\n'; - } - - ++p; - if (p[1] == '\t') - ++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 (ap == new_line + shell_len + sizeof (minus_c) - 1) - /* Line was empty. */ - 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) { - /* 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 = (char **) xmalloc(2 * sizeof (char *)); - new_argv[0] = xstrdup (""); - new_argv[1] = NULL; - } else if ((no_default_sh_exe || batch_mode_shell) && batch_filename_ptr) { - int temp_fd; - FILE* batch = NULL; - int id = GetCurrentProcessId(); - PATH_VAR(fbuf); - - /* create a file name */ - sprintf(fbuf, "make%d", id); - *batch_filename_ptr = create_batch_file (fbuf, unixy_shell, &temp_fd); - - DB (DB_JOBS, (_("Creating temporary batch file %s\n"), - *batch_filename_ptr)); - - /* 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); - - /* create argv */ - new_argv = (char **) xmalloc(3 * sizeof (char *)); - if (unixy_shell) { - new_argv[0] = xstrdup (shell); - new_argv[1] = *batch_filename_ptr; /* only argv[0] gets freed later */ - } else { - new_argv[0] = xstrdup (*batch_filename_ptr); - new_argv[1] = NULL; - } - new_argv[2] = NULL; - } else -#endif /* WINDOWS32 */ - if (unixy_shell) - new_argv = construct_command_argv_internal (new_line, (char **) NULL, - (char *) 0, (char *) 0, - (char **) 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 */ - while (*q != '\0') - { - if (q[0] == '\\' && q[1] == '\n') - { - q += 2; /* remove '\\' and '\n' */ - if (q[0] == '\t') - q++; /* remove 1st tab in the next line */ - } - 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 = (char **) xmalloc (4 * sizeof (char *)); - /* Exactly strlen(shell) + strlen("/c") + strlen(line) + 3 times - the trailing '\0' */ - new_argv[0] = (char *) malloc (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 = (char **) xmalloc (sizeof (char *)); - line_len = strlen (new_line) - shell_len - sizeof (minus_c) + 1; - new_argv[0] = xmalloc (line_len + 1); - strncpy (new_argv[0], - new_line + shell_len + sizeof (minus_c) - 1, line_len); - new_argv[0][line_len] = '\0'; - } -#else - else - fatal (NILF, _("%s (line %d) Bad shell context (!unixy && !batch_mode_shell)\n"), - __FILE__, __LINE__); -#endif - } -#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, - char **batch_filename_ptr) -{ - char *shell, *ifs; - 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 = (char **)malloc (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__ */ - - ifs = allocated_variable_expand_for_file ("$(IFS)", file); - - warn_undefined_variables_flag = save; - } - - argv = construct_command_argv_internal (line, restp, shell, ifs, batch_filename_ptr); - - free (shell); - 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 /* !HAPE_DUP2 && !_AMIGA */ - -/* On VMS systems, include special VMS functions. */ - -#ifdef VMS -#include "vmsjobs.c" -#endif diff --git a/src/bin/make/job.h b/src/bin/make/job.h deleted file mode 100644 index 436b979d73..0000000000 --- a/src/bin/make/job.h +++ /dev/null @@ -1,105 +0,0 @@ -/* Definitions for managing subprocesses in GNU Make. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#ifndef SEEN_JOB_H -#define SEEN_JOB_H - -#ifdef HAVE_FCNTL_H -# include -#else -# include -#endif - -/* How to set close-on-exec for a file descriptor. */ - -#if !defined F_SETFD -# define CLOSE_ON_EXEC(_d) -#else -# ifndef FD_CLOEXEC -# define FD_CLOEXEC 1 -# endif -# define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC) -#endif - -/* 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 **command_lines; /* Array of variable-expanded cmd lines. */ - unsigned int command_line; /* Index into above. */ - char *command_ptr; /* Ptr into command_lines[command_line]. */ - - pid_t pid; /* Child process's ID number. */ -#ifdef VMS - int efn; /* Completion event flag number */ - int cstatus; /* Completion status */ -#endif - char *sh_batch_file; /* Script file for shell commands */ - 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; - -extern void new_job PARAMS ((struct file *file)); -extern void reap_children PARAMS ((int block, int err)); -extern void start_waiting_jobs PARAMS ((void)); - -extern char **construct_command_argv PARAMS ((char *line, char **restp, struct file *file, char** batch_file)); -#ifdef VMS -extern int child_execute_job PARAMS ((char *argv, struct child *child)); -#elif defined(__EMX__) -extern int child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp)); -#else -extern void child_execute_job PARAMS ((int stdin_fd, int stdout_fd, char **argv, char **envp)); -#endif -#ifdef _AMIGA -extern void exec_command PARAMS ((char **argv)); -#elif defined(__EMX__) -extern int exec_command PARAMS ((char **argv, char **envp)); -#else -extern void exec_command PARAMS ((char **argv, char **envp)); -#endif - -extern unsigned int job_slots_used; - -extern void block_sigs PARAMS ((void)); -#ifdef POSIX -extern void unblock_sigs PARAMS ((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 /* SEEN_JOB_H */ diff --git a/src/bin/make/main.c b/src/bin/make/main.c deleted file mode 100644 index 483babfcc2..0000000000 --- a/src/bin/make/main.c +++ /dev/null @@ -1,3129 +0,0 @@ -/* Argument parsing and main program of GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "dep.h" -#include "filedef.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" -#endif -#ifdef __EMX__ -# include -# include -#endif -#ifdef HAVE_FCNTL_H -# include -#endif - -#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) -# define SET_STACK_SIZE -#endif - -#ifdef SET_STACK_SIZE -# include -#endif - -#ifdef _AMIGA -int __stack = 20000; /* Make sure we have 20K of stack space */ -#endif - -extern void init_dir PARAMS ((void)); -extern void remote_setup PARAMS ((void)); -extern void remote_cleanup PARAMS ((void)); -extern RETSIGTYPE fatal_error_signal PARAMS ((int sig)); - -extern void print_variable_data_base PARAMS ((void)); -extern void print_dir_data_base PARAMS ((void)); -extern void print_rule_data_base PARAMS ((void)); -extern void print_file_data_base PARAMS ((void)); -extern void print_vpath_data_base PARAMS ((void)); - -#if defined HAVE_WAITPID || defined HAVE_WAIT3 -# define HAVE_WAIT_NOHANG -#endif - -#ifndef HAVE_UNISTD_H -extern int chdir (); -#endif -#ifndef STDC_HEADERS -# ifndef sun /* Sun has an incorrect decl in a header. */ -extern void exit PARAMS ((int)) __attribute__ ((noreturn)); -# endif -extern double atof (); -#endif - -static void clean_jobserver PARAMS ((int status)); -static void print_data_base PARAMS ((void)); -static void print_version PARAMS ((void)); -static void decode_switches PARAMS ((int argc, char **argv, int env)); -static void decode_env_switches PARAMS ((char *envar, unsigned int len)); -static void define_makeflags PARAMS ((int all, int makefile)); -static char *quote_for_env PARAMS ((char *out, char *in)); -static void initialize_global_hash_tables PARAMS ((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 switch. */ - positive_int, /* A positive integer. */ - floating, /* A floating-point number (double). */ - ignore /* Ignored. */ - } type; - - char *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. */ - - char *noarg_value; /* Pointer to value used if no argument is given. */ - char *default_value;/* Pointer to default value. */ - - 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 string arguments. */ - -struct stringlist - { - char **list; /* Nil-terminated list of strings. */ - unsigned int idx; /* Index into above. */ - unsigned int max; /* Number of pointers allocated. */ - }; - - -/* The recognized command switches. */ - -/* 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; - -/* Print debugging info (--debug). */ - -static struct stringlist *db_flags; -static int debug_flag = 0; - -int db_level = 0; - -#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. */ - -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 keep going even if remaking some file fails (-k). */ - -int keep_going_flag; -int default_keep_going_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 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; - -/* Nonzero means print version information. */ - -int print_version_flag = 0; - -/* List of makefiles given with -f switches. */ - -static struct stringlist *makefiles = 0; - -/* 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. */ - -static struct stringlist *jobserver_fds = 0; - -int job_fds[2] = { -1, -1 }; -int job_rfd = -1; - -/* 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; - -/* If nonzero, we should just print usage and exit. */ - -static int print_usage_flag = 0; - -/* If nonzero, we should print a warning message - for each reference to an undefined variable. */ - -int warn_undefined_variables_flag; - -/* 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; - -/* Remember the original value of the SHELL variable, from the environment. */ - -struct variable shell_var; - - -/* 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_("\ - -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 commands.\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_("\ - -n, --just-print, --dry-run, --recon\n\ - Don't actually run any commands; 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_("\ - -p, --print-data-base Print make's internal database.\n"), - N_("\ - -q, --question Run no commands; 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 commands.\n"), - N_("\ - -S, --no-keep-going, --stop\n\ - Turns off -k.\n"), - N_("\ - -t, --touch Touch targets instead of remaking them.\n"), - N_("\ - -v, --version Print the version number of make and exit.\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"), - NULL - }; - -/* The table of command switches. */ - -static const struct command_switch switches[] = - { - { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 }, - { 'B', flag, (char *) &always_make_set, 1, 1, 0, 0, 0, "always-make" }, - { 'C', string, (char *) &directories, 0, 0, 0, 0, 0, "directory" }, - { 'd', flag, (char *) &debug_flag, 1, 1, 0, 0, 0, 0 }, - { CHAR_MAX+1, string, (char *) &db_flags, 1, 1, 0, "basic", 0, "debug" }, -#ifdef WINDOWS32 - { 'D', flag, (char *) &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" }, -#endif - { 'e', flag, (char *) &env_overrides, 1, 1, 0, 0, 0, - "environment-overrides", }, - { 'f', string, (char *) &makefiles, 0, 0, 0, 0, 0, "file" }, - { 'h', flag, (char *) &print_usage_flag, 0, 0, 0, 0, 0, "help" }, - { 'i', flag, (char *) &ignore_errors_flag, 1, 1, 0, 0, 0, - "ignore-errors" }, - { 'I', string, (char *) &include_directories, 1, 1, 0, 0, 0, - "include-dir" }, - { 'j', positive_int, (char *) &job_slots, 1, 1, 0, (char *) &inf_jobs, - (char *) &default_job_slots, "jobs" }, - { CHAR_MAX+2, string, (char *) &jobserver_fds, 1, 1, 0, 0, 0, - "jobserver-fds" }, - { 'k', flag, (char *) &keep_going_flag, 1, 1, 0, 0, - (char *) &default_keep_going_flag, "keep-going" }, -#ifndef NO_FLOAT - { 'l', floating, (char *) &max_load_average, 1, 1, 0, - (char *) &default_load_average, (char *) &default_load_average, - "load-average" }, -#else - { 'l', positive_int, (char *) &max_load_average, 1, 1, 0, - (char *) &default_load_average, (char *) &default_load_average, - "load-average" }, -#endif - { 'L', flag, (char *) &check_symlink_flag, 1, 1, 0, 0, 0, - "check-symlink-times" }, - { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 }, - { 'n', flag, (char *) &just_print_flag, 1, 1, 1, 0, 0, "just-print" }, - { 'o', string, (char *) &old_files, 0, 0, 0, 0, 0, "old-file" }, - { 'p', flag, (char *) &print_data_base_flag, 1, 1, 0, 0, 0, - "print-data-base" }, - { 'q', flag, (char *) &question_flag, 1, 1, 1, 0, 0, "question" }, - { 'r', flag, (char *) &no_builtin_rules_flag, 1, 1, 0, 0, 0, - "no-builtin-rules" }, - { 'R', flag, (char *) &no_builtin_variables_flag, 1, 1, 0, 0, 0, - "no-builtin-variables" }, - { 's', flag, (char *) &silent_flag, 1, 1, 0, 0, 0, "silent" }, - { 'S', flag_off, (char *) &keep_going_flag, 1, 1, 0, 0, - (char *) &default_keep_going_flag, "no-keep-going" }, - { 't', flag, (char *) &touch_flag, 1, 1, 1, 0, 0, "touch" }, - { 'v', flag, (char *) &print_version_flag, 1, 1, 0, 0, 0, "version" }, - { 'w', flag, (char *) &print_directory_flag, 1, 1, 0, 0, 0, - "print-directory" }, - { CHAR_MAX+3, flag, (char *) &inhibit_print_directory_flag, 1, 1, 0, 0, 0, - "no-print-directory" }, - { 'W', string, (char *) &new_files, 0, 0, 0, 0, 0, "what-if" }, - { CHAR_MAX+4, flag, (char *) &warn_undefined_variables_flag, 1, 1, 0, 0, 0, - "warn-undefined-variables" }, - { 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; - -/* The name we were invoked with. */ - -char *program; - -/* Our current directory before processing any -C options. */ - -char *directory_before_chdir; - -/* Our current directory after processing all -C options. */ - -char *starting_directory; - -/* Value of the MAKELEVEL variable at startup (or 0). */ - -unsigned int makelevel; - -/* First file defined in the makefile whose name does not - start with `.'. This is the default to remake if the - command line does not specify. */ - -struct file *default_goal_file; - -/* Pointer to the value of the .DEFAULT_GOAL special - variable. */ -char ** default_goal_name; - -/* 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 magic `.POSIX' target. - This turns on pedantic compliance with POSIX.2. */ - -int posix_pedantic; - -/* Nonzero if we have seen the '.SECONDEXPANSION' target. - This turns on secondary expansion of prerequisites. */ - -int second_expansion; - -/* 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; - -/* 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 !defined HAVE_BSD_SIGNAL && !defined bsd_signal -# if !defined HAVE_SIGACTION -# define bsd_signal signal -# else -typedef RETSIGTYPE (*bsd_signal_ret_t) (); - -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 - -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 struct file * -enter_command_line_file (char *name) -{ - if (name[0] == '\0') - fatal (NILF, _("empty string invalid as file name")); - - if (name[0] == '~') - { - char *expanded = tilde_expand (name); - if (expanded != 0) - name = expanded; /* Memory leak; I don't care. */ - } - - /* 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] != '\0') - { - name += 2; - while (*name == '/') - /* Skip following slashes: ".//foo" is "foo", not "/foo". */ - ++name; - } - - if (*name == '\0') - { - /* It was all slashes! Move back to the dot and truncate - it after the first slash, so it becomes just "./". */ - do - --name; - while (name[0] != '.'); - name[2] = '\0'; - } - - return enter_file (xstrdup (name)); -} - -/* 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) -{ - char **pp; - - if (debug_flag) - db_level = DB_ALL; - - if (!db_flags) - return; - - 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 'v': - db_level |= DB_BASIC | DB_VERBOSE; - break; - default: - fatal (NILF, _("unknown debug level specification `%s'"), p); - } - - while (*(++p) != '\0') - if (*p == ',' || *p == ' ') - break; - - if (*p == '\0') - break; - - ++p; - } - } -} - -#ifdef WINDOWS32 -/* - * 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%lx)\n"), - prg, exrec->ExceptionCode, (DWORD)exrec->ExceptionAddress); - fprintf(stderr, errmsg); - exit(255); - } - - sprintf(errmsg, - _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = %lx\n"), - prg, exrec->ExceptionCode, exrec->ExceptionFlags, - (DWORD)exrec->ExceptionAddress); - - if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION - && exrec->NumberParameters >= 2) - sprintf(&errmsg[strlen(errmsg)], - (exrec->ExceptionInformation[0] - ? _("Access violation: write operation at address %lx\n") - : _("Access violation: read operation at address %lx\n")), - 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 propogate /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 (char *token) -{ - int sh_found = 0; - char *search_token; - char *tokend; - PATH_VAR(sh_path); - extern char *default_shell; - - if (!token) - search_token = default_shell; - else - search_token = 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] == '\\'))) - && !strcmpi (tokend, "cmd")) - || ((tokend - 4 == search_token - || (tokend - 4 > search_token - && (tokend[-5] == '/' || tokend[-5] == '\\'))) - && !strcmpi (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 (file_exists_p(search_token)) { - /* 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'; - - if (dir_file_exists_p(p, search_token)) { - sprintf(sh_path, "%s/%s", p, search_token); - 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 && dir_file_exists_p(p, search_token)) { - sprintf(sh_path, "%s/%s", p, search_token); - 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 - - return (sh_found); -} -#endif /* WINDOWS32 */ - -#ifdef __MSDOS__ - -static void -msdos_return_to_initial_directory (void) -{ - if (directory_before_chdir) - chdir (directory_before_chdir); -} -#endif - -extern char *mktemp PARAMS ((char *template)); -extern int mkstemp PARAMS ((char *template)); - -FILE * -open_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 -} - - -#ifdef _AMIGA -int -main (int argc, char **argv) -#else -int -main (int argc, char **argv, char **envp) -#endif -{ - static char *stdin_nm = 0; - struct file *f; - int i; - int makefile_status = MAKE_SUCCESS; - char **p; - struct dep *read_makefiles; - PATH_VAR (current_directory); - unsigned int restarts = 0; -#ifdef WINDOWS32 - char *unix_path = NULL; - char *windows32_path = NULL; - - SetUnhandledExceptionFilter(handle_runtime_exceptions); - - /* start off assuming we have no shell */ - unixy_shell = 0; - no_default_sh_exe = 1; -#endif - -#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 = rlim.rlim_max; - setrlimit (RLIMIT_STACK, &rlim); - } - } -#endif - -#ifdef HAVE_ATEXIT - atexit (close_stdout); -#endif - - /* Needed for OS/2 */ - initialize_main(&argc, &argv); - - default_goal_file = 0; - reading_file = 0; - -#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, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - 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) -#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 - - /* Make 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, (char *) 0, _IOLBF, BUFSIZ); -# endif /* setvbuf reversed. */ -#elif HAVE_SETLINEBUF - setlinebuf (stdout); -#endif /* setlinebuf missing. */ - - /* Figure out where this program lives. */ - - if (argv[0] == 0) - argv[0] = ""; - if (argv[0][0] == '\0') - program = "make"; - else - { -#ifdef VMS - program = strrchr (argv[0], ']'); -#else - program = strrchr (argv[0], '/'); -#endif -#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 */ - int argv0_len; - program = strrchr (argv[0], '\\'); - if (program) - { - 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) - program = argv[0]; - 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 - 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 (".VARIABLES", 10, "", o_default, 0)->special = 1; - /* define_variable (".TARGETS", 8, "", o_default, 0)->special = 1; */ - - /* Set up .FEATURES */ - define_variable (".FEATURES", 9, - "target-specific order-only second-expansion else-if", - o_default, 0); -#ifndef NO_ARCHIVES - do_variable_definition (NILF, ".FEATURES", "archives", - o_default, f_append, 0); -#endif -#ifdef MAKE_JOBSERVER - do_variable_definition (NILF, ".FEATURES", "jobserver", - o_default, f_append, 0); -#endif -#ifdef MAKE_SYMLINKS - do_variable_definition (NILF, ".FEATURES", "check-symlink", - o_default, f_append, 0); -#endif - - /* 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 - for (i = 0; envp[i] != 0; ++i) - { - int do_not_define = 0; - char *ep = envp[i]; - - while (*ep != '\0' && *ep != '=') - ++ep; -#ifdef WINDOWS32 - if (!unix_path && strneq(envp[i], "PATH=", 5)) - unix_path = ep+1; - else if (!strnicmp(envp[i], "Path=", 5)) { - do_not_define = 1; /* it gets defined after loop exits */ - if (!windows32_path) - windows32_path = ep+1; - } -#endif - /* The result of pointer arithmetic is cast to unsigned int for - machines where ptrdiff_t is a different size that doesn't widen - the same. */ - if (!do_not_define) - { - struct variable *v; - - v = define_variable (envp[i], (unsigned int) (ep - envp[i]), - ep + 1, o_env, 1); - /* Force exportation of every variable culled from the environment. - We used to rely on target_environment's v_default code to do this. - But that does not work for the case where an environment variable - is redefined in a makefile with `override'; it should then still - be exported, because it was originally in the environment. */ - v->export = v_export; - - /* Another wrinkle is that 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__ - v->export = v_noexport; -#endif - shell_var.name = "SHELL"; - shell_var.value = xstrdup (ep + 1); - } - - /* If MAKE_RESTARTS is set, remember it but don't export it. */ - if (streq (v->name, "MAKE_RESTARTS")) - { - v->export = v_noexport; - restarts = (unsigned int) atoi (ep + 1); - } - } - } -#ifdef WINDOWS32 - /* If we didn't find a correctly spelled PATH we define PATH as - * either the first mispelled value or an empty string - */ - if (!unix_path) - define_variable("PATH", 4, - 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 ("MAKEFLAGS")); -#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, argv, 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_debug_flags (); - - /* 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. */ - if (print_version_flag || print_data_base_flag || db_level) - { - print_version (); - - /* `make --version' is supposed to just print the version and exit. */ - if (print_version_flag) - die (0); - } - -#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] = concat (current_directory, "/", argv[0]); -#else /* !__MSDOS__ */ - if (current_directory[0] != '\0' - && argv[0] != 0 && argv[0][0] != '/' && strchr (argv[0], '/') != 0) - argv[0] = concat (current_directory, "/", argv[0]); -#endif /* !__MSDOS__ */ -#endif /* WINDOWS32 */ -#endif - - /* The extra indirection through $(MAKE_COMMAND) is done - for hysterical raisins. */ - (void) define_variable ("MAKE_COMMAND", 12, argv[0], o_default, 0); - (void) define_variable ("MAKE", 4, "$(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 = (char *) 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. */ - (void) define_variable ("-*-command-variables-*-", 23, - 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. */ - (void) define_variable ("MAKEOVERRIDES", 13, - "${-*-command-variables-*-}", o_env, 1); - } - - /* If there were -C flags, move ourselves about. */ - if (directories != 0) - for (i = 0; directories->list[i] != 0; ++i) - { - char *dir = directories->list[i]; - char *expanded = 0; - if (dir[0] == '~') - { - expanded = tilde_expand (dir); - if (expanded != 0) - dir = expanded; - } -#ifdef WINDOWS32 - /* WINDOWS32 chdir() doesn't work if the directory has a trailing '/' - But allow -C/ just in case someone wants that. */ - { - char *p = dir + strlen (dir) - 1; - while (p > dir && (p[0] == '/' || p[0] == '\\')) - --p; - p[1] = '\0'; - } -#endif - if (chdir (dir) < 0) - pfatal_with_name (dir); - if (expanded) - free (expanded); - } - -#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 */ - /* Figure out the level of recursion. */ - { - struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME)); - if (v != 0 && v->value[0] != '\0' && v->value[0] != '-') - makelevel = (unsigned int) atoi (v->value); - else - makelevel = 0; - } - - /* 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 ? (char **) 0 - : include_directories->list); - - /* Figure out where we are now, after chdir'ing. */ - if (directories == 0) - /* We didn't move, so we're still in the same place. */ - starting_directory = current_directory; - else - { -#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 - error (NILF, "getwd: %s", current_directory); -#endif - starting_directory = 0; - } - else - starting_directory = current_directory; - } - - (void) define_variable ("CURDIR", 6, current_directory, o_file, 0); - - /* Read any stdin makefiles into temporary files. */ - - if (makefiles != 0) - { - register 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, *tmpdir; - - if (stdin_nm) - 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 = (char *) alloca (strlen (tmpdir) - + sizeof (DEFAULT_TMPFILE) + 1); - 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 = open_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)")); - } - (void) fclose (outfile); - - /* Replace the name that read_all_makefiles will - see with the name of the temporary file. */ - makefiles->list[i] = xstrdup (stdin_nm); - - /* Make sure the temporary file will not be remade. */ - f = enter_file (stdin_nm); - f->updated = 1; - f->update_status = 0; - 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. */ - { - extern RETSIGTYPE child_handler PARAMS ((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 - so makefiles can look at them. */ - - define_makeflags (0, 0); - - /* Define the default variables. */ - define_default_variables (); - - default_file = enter_file (".DEFAULT"); - - { - struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0); - default_goal_name = &v->value; - } - - /* Read all the makefiles. */ - - read_makefiles - = read_all_makefiles (makefiles == 0 ? (char **) 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 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__ */ - - /* Decode switches again, in case the variables were set by the makefile. */ - decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS")); -#if 0 - decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS")); -#endif - -#if defined (__MSDOS__) || defined (__EMX__) - if (job_slots != 1 -# ifdef __EMX__ - && _osmode != OS2_MODE /* turn off -j if we are in DOS mode */ -# endif - ) - { - error (NILF, - _("Parallel jobs (-j) are not supported on this platform.")); - error (NILF, _("Resetting to single job (-j1) mode.")); - job_slots = 1; - } -#endif - -#ifdef MAKE_JOBSERVER - /* If the jobserver-fds option is seen, make sure that -j is reasonable. */ - - if (jobserver_fds) - { - char *cp; - unsigned int ui; - - for (ui=1; ui < jobserver_fds->idx; ++ui) - if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui])) - fatal (NILF, _("internal error: multiple --jobserver-fds options")); - - /* Now parse the fds string and make sure it has the proper format. */ - - cp = jobserver_fds->list[0]; - - if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2) - fatal (NILF, - _("internal error: invalid --jobserver-fds string `%s'"), cp); - - /* 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 (job_slots > 0) - error (NILF, - _("warning: -jN forced in submake: disabling jobserver mode.")); - - /* 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 ((job_rfd = dup (job_fds[0])) < 0) - { - if (errno != EBADF) - pfatal_with_name (_("dup jobserver")); - - error (NILF, - _("warning: jobserver unavailable: using -j1. Add `+' to parent make rule.")); - job_slots = 1; - } - - if (job_slots > 0) - { - close (job_fds[0]); - close (job_fds[1]); - job_fds[0] = job_fds[1] = -1; - free (jobserver_fds->list); - free (jobserver_fds); - jobserver_fds = 0; - } - } - - /* 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) - { - char c = '+'; - - if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0) - pfatal_with_name (_("creating jobs pipe")); - - /* 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; - - while (--job_slots) - { - int r; - - EINTRLOOP (r, write (job_fds[1], &c, 1)); - if (r != 1) - pfatal_with_name (_("init jobserver pipe")); - } - - /* Fill in the jobserver_fds struct for our children. */ - - jobserver_fds = (struct stringlist *) - xmalloc (sizeof (struct stringlist)); - jobserver_fds->list = (char **) xmalloc (sizeof (char *)); - jobserver_fds->list[0] = xmalloc ((sizeof ("1024")*2)+1); - - sprintf (jobserver_fds->list[0], "%d,%d", job_fds[0], job_fds[1]); - jobserver_fds->idx = 1; - jobserver_fds->max = 1; - } -#endif - -#ifndef MAKE_SYMLINKS - if (check_symlink_flag) - { - 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) - for (p = old_files->list; *p != 0; ++p) - { - f = enter_command_line_file (*p); - f->last_mtime = f->mtime_before_update = OLD_MTIME; - f->updated = 1; - f->update_status = 0; - f->command_state = cs_finished; - } - - if (!restarts && new_files != 0) - { - for (p = new_files->list; *p != 0; ++p) - { - f = enter_command_line_file (*p); - f->last_mtime = f->mtime_before_update = NEW_MTIME; - } - } - - /* Initialize the remote job module. */ - remote_setup (); - - if (read_makefiles != 0) - { - /* Update any makefiles if necessary. */ - - FILE_TIMESTAMP *makefile_mtimes = 0; - unsigned int mm_idx = 0; - char **nargv = argv; - int nargc = argc; - int orig_db_level = db_level; - int 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) - { - register 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 = (FILE_TIMESTAMP *) - xrealloc ((char *) 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 1: - /* 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 -1: - /* Did nothing. */ - break; - - case 2: - /* 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 == 0) - { - /* 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. */ - 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)) - { - /* 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, - _("Included makefile `%s' was not found."), - dep_name (d)); - else - { - /* A normal makefile. We must die later. */ - error (NILF, _("Makefile `%s' was not found"), - dep_name (d)); - 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 (2); - break; - } - - case 0: - re_exec: - /* Updated successfully. Re-exec ourselves. */ - - remove_intermediates (0); - - if (print_data_base_flag) - print_data_base (); - - log_working_directory (0); - - 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 */ - { - char *p = &argv[i][2]; - if (*p == '\0') - argv[++i] = makefiles->list[j]; - else - argv[i] = concat ("-f", makefiles->list[j], ""); - ++j; - } - } - - /* Add -o option for the stdin temporary file, if necessary. */ - if (stdin_nm) - { - nargv = (char **) xmalloc ((nargc + 2) * sizeof (char *)); - bcopy ((char *) argv, (char *) nargv, argc * sizeof (char *)); - nargv[nargc++] = concat ("-o", stdin_nm, ""); - nargv[nargc] = 0; - } - - if (directories != 0 && directories->idx > 0) - { - char bad; - if (directory_before_chdir != 0) - { - if (chdir (directory_before_chdir) < 0) - { - perror_with_name ("chdir", ""); - bad = 1; - } - else - bad = 0; - } - else - bad = 1; - if (bad) - fatal (NILF, _("Couldn't change back to original directory.")); - } - - ++restarts; - - if (ISDB (DB_BASIC)) - { - char **p; - printf (_("Re-executing[%u]:"), restarts); - for (p = nargv; *p != 0; ++p) - printf (" %s", *p); - putchar ('\n'); - } - -#ifndef _AMIGA - for (p = environ; *p != 0; ++p) - { - if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH) - && (*p)[MAKELEVEL_LENGTH] == '=') - { - /* The SGI compiler apparently can't understand - the concept of storing the result of a function - in something other than a local variable. */ - char *sgi_loses; - sgi_loses = (char *) alloca (40); - *p = sgi_loses; - sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel); - } - if (strneq (*p, "MAKE_RESTARTS=", 14)) - { - char *sgi_loses; - sgi_loses = (char *) alloca (40); - *p = sgi_loses; - sprintf (*p, "MAKE_RESTARTS=%u", restarts); - restarts = 0; - } - } -#else /* AMIGA */ - { - char buffer[256]; - - sprintf (buffer, "%u", makelevel); - SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY); - - sprintf (buffer, "%u", 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=%u", 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 status; - pid = child_execute_job (0, 1, nargv, environ); - - /* is this loop really necessary? */ - do { - pid = wait (&status); - } while (pid <= 0); - /* use the exit code of the child process */ - exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); - } -#else - exec_command (nargv, environ); -#endif - /* NOTREACHED */ - - default: -#define BOGUS_UPDATE_STATUS 0 - assert (BOGUS_UPDATE_STATUS); - break; - } - - db_level = orig_db_level; - - /* Free the makefile mtimes (if we allocated any). */ - if (makefile_mtimes) - free ((char *) 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) - { - for (p = new_files->list; *p != 0; ++p) - { - f = enter_command_line_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); - - { - int status; - - /* If there were no command-line goals, use the default. */ - if (goals == 0) - { - if (**default_goal_name != '\0') - { - if (default_goal_file == 0 || - strcmp (*default_goal_name, default_goal_file->name) != 0) - { - default_goal_file = lookup_file (*default_goal_name); - - /* In case user set .DEFAULT_GOAL to a non-existent target - name let's just enter this name into the table and let - the standard logic sort it out. */ - if (default_goal_file == 0) - { - struct nameseq *ns; - char *p = *default_goal_name; - - ns = multi_glob ( - parse_file_seq (&p, '\0', sizeof (struct nameseq), 1), - sizeof (struct nameseq)); - - /* .DEFAULT_GOAL should contain one target. */ - if (ns->next != 0) - fatal (NILF, _(".DEFAULT_GOAL contains more than one target")); - - default_goal_file = enter_file (ns->name); - - ns->name = 0; /* It was reused by enter_file(). */ - free_ns_chain (ns); - } - } - - goals = alloc_dep (); - goals->file = default_goal_file; - } - } - else - lastgoal->next = 0; - - - if (!goals) - { - if (read_makefiles == 0) - fatal (NILF, _("No targets specified and no makefile found")); - - fatal (NILF, _("No targets")); - } - - /* Update the goals. */ - - DB (DB_BASIC, (_("Updating goal targets....\n"))); - - switch (update_goal_chain (goals)) - { - case -1: - /* Nothing happened. */ - case 0: - /* Updated successfully. */ - status = makefile_status; - break; - case 1: - /* We are under -q and would run some commands. */ - status = MAKE_TROUBLE; - break; - case 2: - /* Updating failed. POSIX.2 specifies exit status >1 for this; - but in VMS, there is only success and failure. */ - status = MAKE_FAILURE; - break; - default: - abort (); - } - - /* If we detected some clock skew, generate one last warning */ - if (clock_skew_detected) - error (NILF, - _("warning: Clock skew detected. Your build may be incomplete.")); - - /* Exit. */ - die (status); - } - - /* NOTREACHED */ - return 0; -} - -/* 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 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; -} - -static void -handle_non_switch_argument (char *arg, int env) -{ - /* Non-option argument. It might be a variable definition. */ - 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 = (struct command_variable *) 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_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 *v; - char *value; - - v = lookup_variable (STRING_SIZE_TUPLE ("MAKECMDGOALS")); - if (v == 0) - value = f->name; - else - { - /* Paste the old and new values together */ - unsigned int oldlen, newlen; - - oldlen = strlen (v->value); - newlen = strlen (f->name); - value = (char *) alloca (oldlen + 1 + newlen + 1); - bcopy (v->value, value, oldlen); - value[oldlen] = ' '; - bcopy (f->name, &value[oldlen + 1], newlen + 1); - } - define_variable ("MAKECMDGOALS", 12, 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 \n")); -} - -/* Decode switches from ARGC and ARGV. - They came from the environment if ENV is nonzero. */ - -static void -decode_switches (int argc, 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) - { - /* Parse the next argument. */ - c = getopt_long (argc, argv, options, long_options, (int *) 0); - 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 (optarg, 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: - if (!doit) - break; - - if (optarg == 0) - optarg = cs->noarg_value; - else if (*optarg == '\0') - { - error (NILF, _("the `-%c' option requires a non-empty string argument"), - cs->c); - bad = 1; - } - - sl = *(struct stringlist **) cs->value_ptr; - if (sl == 0) - { - sl = (struct stringlist *) - xmalloc (sizeof (struct stringlist)); - sl->max = 5; - sl->idx = 0; - sl->list = (char **) xmalloc (5 * sizeof (char *)); - *(struct stringlist **) cs->value_ptr = sl; - } - else if (sl->idx == sl->max - 1) - { - sl->max += 5; - sl->list = (char **) - xrealloc ((char *) sl->list, - sl->max * sizeof (char *)); - } - sl->list[sl->idx++] = optarg; - 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 (optarg == 0 && argc > optind) - { - const char *cp; - for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp) - ; - if (cp[0] == '\0') - optarg = argv[optind++]; - } - - if (!doit) - break; - - if (optarg != 0) - { - int i = atoi (optarg); - const char *cp; - - /* Yes, I realize we're repeating this in some cases. */ - for (cp = optarg; ISDIGIT (cp[0]); ++cp) - ; - - if (i < 1 || cp[0] != '\0') - { - error (NILF, _("the `-%c' option requires a positive integral 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 (optarg == 0 && optind < argc - && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.')) - optarg = argv[optind++]; - - if (doit) - *(double *) cs->value_ptr - = (optarg != 0 ? atof (optarg) - : *(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 ? 2 : 0); - } -} - -/* 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 (char *envar, unsigned int len) -{ - char *varref = (char *) alloca (2 + len + 2); - char *value, *p; - int argc; - char **argv; - - /* Get the variable's value. */ - varref[0] = '$'; - varref[1] = '('; - bcopy (envar, &varref[2], 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 = (char **) alloca ((1 + len + 1) * sizeof (char *)); - - /* Allocate a buffer to copy the value into while we split it into words - and unquote it. We must use permanent storage for this because - decode_switches may store pointers into the passed argument words. */ - p = (char *) xmalloc (2 * len); - - /* getopt will look at the arguments starting at ARGV[1]. - Prepend a spacer word. */ - argv[0] = 0; - argc = 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; - - if (argv[1][0] != '-' && strchr (argv[1], '=') == 0) - /* The first word doesn't start with a dash and isn't a variable - definition. Add a dash and pass it along to decode_switches. We - need permanent storage for this in case decode_switches saves - pointers into the value. */ - argv[1] = concat ("-", argv[1], ""); - - /* 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, 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 void -define_makeflags (int all, int makefile) -{ - static const char ref[] = "$(MAKEOVERRIDES)"; - static const char posixref[] = "$(-*-command-variables-*-)"; - register const struct command_switch *cs; - char *flagstring; - register char *p; - unsigned int words; - struct variable *v; - - /* 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; - char *arg; - }; - struct flag *flags = 0; - unsigned int flagslen = 0; -#define ADD_FLAG(ARG, LEN) \ - do { \ - struct flag *new = (struct flag *) alloca (sizeof (struct flag)); \ - new->cs = cs; \ - new->arg = (ARG); \ - new->next = flags; \ - flags = new; \ - if (new->arg == 0) \ - ++flagslen; /* Just a single flag letter. */ \ - else \ - flagslen += 1 + 1 + 1 + 1 + 3 * (LEN); /* " -x foo" */ \ - 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) - { - default: - abort (); - - 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)) - 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 if (cs->c == 'j') - /* Special case for `-j'. */ - ADD_FLAG ("1", 1); - else - { - char *buf = (char *) 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 = (char *) alloca (100); - sprintf (buf, "%g", *(double *) cs->value_ptr); - ADD_FLAG (buf, strlen (buf)); - } - } - break; -#endif - - case string: - if (all) - { - struct stringlist *sl = *(struct stringlist **) cs->value_ptr; - if (sl != 0) - { - /* Add the elements in reverse order, because - all the flags get reversed below; and the order - matters for some switches (like -I). */ - register unsigned int i = sl->idx; - while (i-- > 0) - ADD_FLAG (sl->list[i], strlen (sl->list[i])); - } - } - break; - } - - flagslen += 4 + sizeof posixref; /* Four more for the possible " -- ". */ - -#undef ADD_FLAG - - /* Construct the value in FLAGSTRING. - We allocate enough space for a preceding dash and trailing null. */ - flagstring = (char *) alloca (1 + flagslen + 1); - bzero (flagstring, 1 + flagslen + 1); - p = flagstring; - words = 1; - *p++ = '-'; - while (flags != 0) - { - /* Add the flag letter or name to the string. */ - if (short_option (flags->cs->c)) - *p++ = flags->cs->c; - else - { - if (*p != '-') - { - *p++ = ' '; - *p++ = '-'; - } - *p++ = '-'; - strcpy (p, flags->cs->long_name); - p += strlen (p); - } - if (flags->arg != 0) - { - /* A flag that takes an optional argument which in this case is - omitted is specified by ARG being "". We must distinguish - because a following flag appended without an intervening " -" - is considered the arg for the first. */ - if (flags->arg[0] != '\0') - { - /* Add its argument too. */ - *p++ = !short_option (flags->cs->c) ? '=' : ' '; - p = quote_for_env (p, flags->arg); - } - ++words; - /* Write a following space and dash, for the next flag. */ - *p++ = ' '; - *p++ = '-'; - } - else if (!short_option (flags->cs->c)) - { - ++words; - /* Long options must each go in their own word, - so we write the following space and dash. */ - *p++ = ' '; - *p++ = '-'; - } - flags = flags->next; - } - - /* Define MFLAGS before appending variable definitions. */ - - if (p == &flagstring[1]) - /* No flags. */ - flagstring[0] = '\0'; - else if (p[-1] == '-') - { - /* Kill the final space and dash. */ - p -= 2; - *p = '\0'; - } - else - /* Terminate the string. */ - *p = '\0'; - - /* Since MFLAGS is not parsed for flags, there is no reason to - override any makefile redefinition. */ - (void) define_variable ("MFLAGS", 6, flagstring, o_env, 1); - - if (all && command_variables != 0) - { - /* Now write a reference to $(MAKEOVERRIDES), which contains all the - command-line variable definitions. */ - - if (p == &flagstring[1]) - /* No flags written, so elide the leading dash already written. */ - p = flagstring; - else - { - /* Separate the variables from the switches with a "--" arg. */ - if (p[-1] != '-') - { - /* We did not already write a trailing " -". */ - *p++ = ' '; - *p++ = '-'; - } - /* There is a trailing " -"; fill it out to " -- ". */ - *p++ = '-'; - *p++ = ' '; - } - - /* Copy in the string. */ - if (posix_pedantic) - { - bcopy (posixref, p, sizeof posixref - 1); - p += sizeof posixref - 1; - } - else - { - bcopy (ref, p, sizeof ref - 1); - p += sizeof ref - 1; - } - } - else if (p == &flagstring[1]) - { - words = 0; - --p; - } - else if (p[-1] == '-') - /* Kill the final space and dash. */ - p -= 2; - /* Terminate the string. */ - *p = '\0'; - - v = define_variable ("MAKEFLAGS", 9, - /* If there are switches, omit the leading dash - unless it is a single long option with two - leading dashes. */ - &flagstring[(flagstring[0] == '-' - && flagstring[1] != '-') - ? 1 : 0], - /* 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. Of course, an override or command - definition will still take precedence. */ - o_file, 1); - if (! all) - /* The first time we are called, set MAKEFLAGS to always be exported. - We should not do this again on the second call, because that is - after reading makefiles which might have done `unexport MAKEFLAGS'. */ - v->export = v_export; -} - -/* Print version information. */ - -static void -print_version (void) -{ - static int printed_version = 0; - - char *precede = print_data_base_flag ? "# " : ""; - - if (printed_version) - /* Do it only once. */ - return; - - /* 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 ("%sGNU Make %s\n\ -%sCopyright (C) 2006 Free Software Foundation, Inc.\n", - precede, version_string, precede); - - printf (_("%sThis is free software; see the source for copying conditions.\n\ -%sThere is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ -%sPARTICULAR PURPOSE.\n"), - precede, precede, precede); - - if (!remote_description || *remote_description == '\0') - printf (_("\n%sThis program built for %s\n"), precede, make_host); - else - printf (_("\n%sThis program built for %s (%s)\n"), - precede, make_host, remote_description); - - printed_version = 1; - - /* Flush stdout so the user doesn't have to wait to see the - version information while things are thought about. */ - fflush (stdout); -} - -/* Print a bunch of information about this and that. */ - -static void -print_data_base () -{ - time_t when; - - when = time ((time_t *) 0); - printf (_("\n# Make data base, printed on %s"), ctime (&when)); - - print_variable_data_base (); - print_dir_data_base (); - print_rule_data_base (); - 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) -{ - char token = '+'; - - /* 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. */ - - if (job_fds[0] != -1 && jobserver_tokens) - { - if (status != 2) - error (NILF, - "INTERNAL: Exiting with %u jobserver tokens (should be 0)!", - jobserver_tokens); - else - while (jobserver_tokens--) - { - int r; - - EINTRLOOP (r, write (job_fds[1], &token, 1)); - if (r != 1) - perror_with_name ("write", ""); - } - } - - - /* 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; - - /* Close the write side, so the read() won't hang. */ - close (job_fds[1]); - - while (read (job_fds[0], &token, 1) == 1) - ++tcnt; - - if (tcnt != master_job_slots) - error (NILF, - "INTERNAL: Exiting with %u jobserver tokens available; should be %u!", - tcnt, master_job_slots); - - close (job_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); - - /* 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 (); - - clean_jobserver (status); - - /* 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) - chdir (directory_before_chdir); - - log_working_directory (0); - } - - exit (status); -} - -/* Write a message indicating that we've just entered or - left (according to ENTERING) the current directory. */ - -void -log_working_directory (int entering) -{ - static int entered = 0; - - /* Print nothing without the flag. Don't print the entering message - again if we already have. Don't print the leaving message if we - haven't printed the entering message. */ - if (! print_directory_flag || entering == entered) - return; - - entered = entering; - - if (print_data_base_flag) - fputs ("# ", stdout); - - /* Use entire sentences to give the translators a fighting chance. */ - - if (makelevel == 0) - if (starting_directory == 0) - if (entering) - printf (_("%s: Entering an unknown directory\n"), program); - else - printf (_("%s: Leaving an unknown directory\n"), program); - else - if (entering) - printf (_("%s: Entering directory `%s'\n"), - program, starting_directory); - else - printf (_("%s: Leaving directory `%s'\n"), - program, starting_directory); - else - if (starting_directory == 0) - if (entering) - printf (_("%s[%u]: Entering an unknown directory\n"), - program, makelevel); - else - printf (_("%s[%u]: Leaving an unknown directory\n"), - program, makelevel); - else - if (entering) - printf (_("%s[%u]: Entering directory `%s'\n"), - program, makelevel, starting_directory); - else - printf (_("%s[%u]: Leaving directory `%s'\n"), - program, makelevel, starting_directory); - - /* Flush stdout to be sure this comes before any stderr output. */ - fflush (stdout); -} diff --git a/src/bin/make/make.h b/src/bin/make/make.h deleted file mode 100644 index 994f4f225c..0000000000 --- a/src/bin/make/make.h +++ /dev/null @@ -1,611 +0,0 @@ -/* 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* 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). */ -#include -#undef HAVE_CONFIG_H -#define HAVE_CONFIG_H 1 - -/* AIX requires this to be the first thing in the file. */ -#ifndef __GNUC__ -# if HAVE_ALLOCA_H -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -# endif -# endif -# endif -#endif - - -/* Use prototypes if available. */ -#if defined (__cplusplus) || defined (__STDC__) -# undef PARAMS -# define PARAMS(protos) protos -#else /* Not C++ or ANSI C. */ -# undef PARAMS -# define PARAMS(protos) () -#endif /* C++ or ANSI C. */ - -/* Specify we want GNU source code. This must be defined before any - system headers are included. */ - -#define _GNU_SOURCE 1 - - -#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 = (char *) alloca (GET_PATH_MAX) -extern unsigned int get_path_max PARAMS ((void)); -#endif - -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif - -/* Nonzero if the integer type T is signed. */ -#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 -/* 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 -extern char *malloc PARAMS ((int)); -extern char *realloc PARAMS ((char *, int)); -extern void free PARAMS ((char *)); - -extern void abort PARAMS ((void)) __attribute__ ((noreturn)); -extern void exit PARAMS ((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 0 -#endif - -#ifdef ANSI_STRING - -# ifndef bcmp -# define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) -# endif -# ifndef bzero -# define bzero(s, n) memset ((s), 0, (n)) -# endif -# if defined(HAVE_MEMMOVE) && !defined(bcopy) -# define bcopy(s, d, n) memmove ((d), (s), (n)) -# endif - -#else /* Not ANSI_STRING. */ - -# ifndef HAVE_STRCHR -# define strchr(s, c) index((s), (c)) -# define strrchr(s, c) rindex((s), (c)) -# endif - -# ifndef bcmp -extern int bcmp PARAMS ((const char *, const char *, int)); -# endif -# ifndef bzero -extern void bzero PARAMS ((char *, int)); -#endif -# ifndef bcopy -extern void bcopy PARAMS ((const char *b1, char *b2, int)); -# endif - -/* SCO Xenix has a buggy macro definition in . */ -#undef strerror -#if !defined(__DECC) -extern char *strerror PARAMS ((int errnum)); -#endif - -#endif /* !ANSI_STRING. */ -#undef ANSI_STRING - -#if HAVE_INTTYPES_H -# include -#endif -#define FILE_TIMESTAMP uintmax_t - -#if !defined(HAVE_STRSIGNAL) -extern char *strsignal PARAMS ((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) - -#ifndef iAPX286 -# define streq(a, b) \ - ((a) == (b) || \ - (*(a) == *(b) && (*(a) == '\0' || !strcmp ((a) + 1, (b) + 1)))) -# ifdef HAVE_CASE_INSENSITIVE_FS -/* This is only used on Windows/DOS platforms, so we assume strcmpi(). */ -# define strieq(a, b) \ - ((a) == (b) \ - || (tolower((unsigned char)*(a)) == tolower((unsigned char)*(b)) \ - && (*(a) == '\0' || !strcmpi ((a) + 1, (b) + 1)))) -# else -# define strieq(a, b) streq(a, b) -# endif -#else -/* Buggy compiler can't handle this. */ -# define streq(a, b) (strcmp ((a), (b)) == 0) -# define strieq(a, b) (strcmp ((a), (b)) == 0) -#endif -#define strneq(a, b, l) (strncmp ((a), (b), (l)) == 0) -#ifdef VMS -extern int strcmpi (const char *,const char *); -#endif - -#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. */ -#if defined(HAVE_DOS_PATHS) -# define PATH_SEPARATOR_CHAR ';' -#elif defined(VMS) -# define PATH_SEPARATOR_CHAR ',' -#else -# define PATH_SEPARATOR_CHAR ':' -#endif - -/* This is needed for getcwd() and chdir(). */ -#if defined(_MSC_VER) || defined(__BORLANDC__) -# include -#endif - -#ifdef WINDOWS32 -# include -# include -# define pipe(p) _pipe(p, 512, O_BINARY) -# define kill(pid,sig) w32_kill(pid,sig) - -extern void sync_Path_environment(void); -extern int kill(int pid, int sig); -extern char *end_of_token_w32(char *s, char stopchar); -extern int find_and_set_default_shell(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 */ - -struct floc - { - const char *filenm; - unsigned long lineno; - }; -#define NILF ((struct floc *)0) - -#define STRING_SIZE_TUPLE(_s) (_s), (sizeof (_s)-1) - - -/* 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 - -#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H -extern void message (int prefix, const char *fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); -extern void error (const struct floc *flocp, const char *fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); -extern void fatal (const struct floc *flocp, const char *fmt, ...) - __attribute__ ((noreturn, __format__ (__printf__, 2, 3))); -#else -extern void message (); -extern void error (); -extern void fatal (); -#endif - -extern void die PARAMS ((int)) __attribute__ ((noreturn)); -extern void log_working_directory PARAMS ((int)); -extern void pfatal_with_name PARAMS ((const char *)) __attribute__ ((noreturn)); -extern void perror_with_name PARAMS ((const char *, const char *)); -extern char *savestring PARAMS ((const char *, unsigned int)); -extern char *concat PARAMS ((const char *, const char *, const char *)); -extern char *xmalloc PARAMS ((unsigned int)); -extern char *xrealloc PARAMS ((char *, unsigned int)); -extern char *xstrdup PARAMS ((const char *)); -extern char *find_next_token PARAMS ((char **, unsigned int *)); -extern char *next_token PARAMS ((const char *)); -extern char *end_of_token PARAMS ((const char *)); -extern void collapse_continuations PARAMS ((char *)); -extern char *lindex PARAMS ((const char *, const char *, int)); -extern int alpha_compare PARAMS ((const void *, const void *)); -extern void print_spaces PARAMS ((unsigned int)); -extern char *find_percent PARAMS ((char *)); -extern FILE *open_tmpfile PARAMS ((char **, const char *)); - -#ifndef NO_ARCHIVES -extern int ar_name PARAMS ((char *)); -extern void ar_parse_name PARAMS ((char *, char **, char **)); -extern int ar_touch PARAMS ((char *)); -extern time_t ar_member_date PARAMS ((char *)); -#endif - -extern int dir_file_exists_p PARAMS ((char *, char *)); -extern int file_exists_p PARAMS ((char *)); -extern int file_impossible_p PARAMS ((char *)); -extern void file_impossible PARAMS ((char *)); -extern char *dir_name PARAMS ((char *)); -extern void hash_init_directories PARAMS ((void)); - -extern void define_default_variables PARAMS ((void)); -extern void set_default_suffixes PARAMS ((void)); -extern void install_default_suffix_rules PARAMS ((void)); -extern void install_default_implicit_rules PARAMS ((void)); - -extern void build_vpath_lists PARAMS ((void)); -extern void construct_vpath_list PARAMS ((char *pattern, char *dirpath)); -extern int vpath_search PARAMS ((char **file, FILE_TIMESTAMP *mtime_ptr)); -extern int gpath_search PARAMS ((char *file, unsigned int len)); - -extern void construct_include_path PARAMS ((char **arg_dirs)); - -extern void user_access PARAMS ((void)); -extern void make_access PARAMS ((void)); -extern void child_access PARAMS ((void)); - -extern void close_stdout PARAMS ((void)); - -extern char *strip_whitespace PARAMS ((const char **begpp, const char **endpp)); - -/* String caching */ -extern void strcache_init PARAMS ((void)); -extern void strcache_print_stats PARAMS ((const char *prefix)); -extern int strcache_iscached PARAMS ((const char *str)); -extern const char *strcache_add PARAMS ((const char *str)); -extern const char *strcache_add_len PARAMS ((const char *str, int len)); -extern int strcache_setbufsize PARAMS ((int size)); - -#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) - -extern long int atol (); -# ifndef VMS -extern long int lseek (); -# endif - -#endif /* Not GNU C library or POSIX. */ - -#ifdef HAVE_GETCWD -# if !defined(VMS) && !defined(__DECC) -extern char *getcwd (); -# endif -#else -extern char *getwd (); -# define getcwd(buf, len) getwd (buf) -#endif - -extern const struct floc *reading_file; -extern const struct floc **expanding_var; - -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; - -/* can we run commands via 'sh -c xxx' or must we use batch files? */ -extern int batch_mode_shell; - -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 - -extern char *program; -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 -# define MAKE_SUCCESS 1 -# define MAKE_TROUBLE 2 -# define MAKE_FAILURE 3 -#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 !HAVE_STRCASECMP -# define strcasecmp stricmp -# endif - -# 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; \ - while (((_v)=_c)==0 && errno==EINTR); }while(0) - diff --git a/src/bin/make/make.rdef b/src/bin/make/make.rdef deleted file mode 100644 index dc9560b782..0000000000 --- a/src/bin/make/make.rdef +++ /dev/null @@ -1,11 +0,0 @@ -resource app_version -{ - major = 3, - middle = 81, - minor = 0, - variety = 5, - internal = 0, - short_info = "3.81", - long_info = "3.81 ©2006 The Free Software Foundation, Inc." -}; - diff --git a/src/bin/make/misc.c b/src/bin/make/misc.c deleted file mode 100644 index 07f3c016af..0000000000 --- a/src/bin/make/misc.c +++ /dev/null @@ -1,897 +0,0 @@ -/* Miscellaneous generic support functions for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "dep.h" -#include "debug.h" - -/* Variadic functions. We go through contortions to allow proper function - prototypes for both ANSI and pre-ANSI C compilers, and also for those - which support stdarg.h vs. varargs.h, and finally those which have - vfprintf(), etc. and those who have _doprnt... or nothing. - - This fancy stuff all came from GNU fileutils, except for the VA_PRINTF and - VA_END macros used here since we have multiple print functions. */ - -#if USE_VARIADIC -# if HAVE_STDARG_H -# 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 -/* We can't use any variadic interface! */ -# 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 - - -/* 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) -{ - register char *in, *out, *p; - register int backslash; - register unsigned int bs_write; - - 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. */ - backslash = 0; - 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 the newline is quoted, discard following whitespace - and any preceding whitespace; leave just one space. */ - if (backslash) - { - in = next_token (in); - 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 newly-allocated string whose contents - concatenate those of s1, s2, s3. */ - -char * -concat (const char *s1, const char *s2, const char *s3) -{ - unsigned int len1, len2, len3; - char *result; - - len1 = *s1 != '\0' ? strlen (s1) : 0; - len2 = *s2 != '\0' ? strlen (s2) : 0; - len3 = *s3 != '\0' ? strlen (s3) : 0; - - result = (char *) xmalloc (len1 + len2 + len3 + 1); - - if (*s1 != '\0') - bcopy (s1, result, len1); - if (*s2 != '\0') - bcopy (s2, result + len1, len2); - if (*s3 != '\0') - bcopy (s3, result + len1 + len2, len3); - *(result + len1 + len2 + len3) = '\0'; - - return result; -} - -/* Print a message on stdout. */ - -void -#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H -message (int prefix, const char *fmt, ...) -#else -message (prefix, fmt, va_alist) - int prefix; - const char *fmt; - va_dcl -#endif -{ -#if USE_VARIADIC - va_list args; -#endif - - log_working_directory (1); - - if (fmt != 0) - { - if (prefix) - { - if (makelevel == 0) - printf ("%s: ", program); - else - printf ("%s[%u]: ", program, makelevel); - } - VA_START (args, fmt); - VA_PRINTF (stdout, fmt, args); - VA_END (args); - putchar ('\n'); - } - - fflush (stdout); -} - -/* Print an error message. */ - -void -#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H -error (const struct floc *flocp, const char *fmt, ...) -#else -error (flocp, fmt, va_alist) - const struct floc *flocp; - const char *fmt; - va_dcl -#endif -{ -#if USE_VARIADIC - va_list args; -#endif - - log_working_directory (1); - - if (flocp && flocp->filenm) - fprintf (stderr, "%s:%lu: ", flocp->filenm, flocp->lineno); - else if (makelevel == 0) - fprintf (stderr, "%s: ", program); - else - fprintf (stderr, "%s[%u]: ", program, makelevel); - - VA_START(args, fmt); - VA_PRINTF (stderr, fmt, args); - VA_END (args); - - putc ('\n', stderr); - fflush (stderr); -} - -/* Print an error message and exit. */ - -void -#if HAVE_ANSI_COMPILER && USE_VARIADIC && HAVE_STDARG_H -fatal (const struct floc *flocp, const char *fmt, ...) -#else -fatal (flocp, fmt, va_alist) - const struct floc *flocp; - const char *fmt; - va_dcl -#endif -{ -#if USE_VARIADIC - va_list args; -#endif - - log_working_directory (1); - - if (flocp && flocp->filenm) - fprintf (stderr, "%s:%lu: *** ", flocp->filenm, flocp->lineno); - else if (makelevel == 0) - fprintf (stderr, "%s: *** ", program); - else - fprintf (stderr, "%s[%u]: *** ", program, makelevel); - - VA_START(args, fmt); - VA_PRINTF (stderr, fmt, args); - VA_END (args); - - fputs (_(". Stop.\n"), stderr); - - die (2); -} - -#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 - -/* Print an error message from errno. */ - -void -perror_with_name (const char *str, const char *name) -{ - error (NILF, _("%s%s: %s"), str, name, strerror (errno)); -} - -/* Print an error message from errno and exit. */ - -void -pfatal_with_name (const char *name) -{ - fatal (NILF, _("%s: %s"), name, strerror (errno)); - - /* NOTREACHED */ -} - -/* 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 xrealloc -#undef xstrdup - -char * -xmalloc (unsigned int size) -{ - /* Make sure we don't allocate 0, for pre-ANSI libraries. */ - char *result = (char *) malloc (size ? size : 1); - if (result == 0) - fatal (NILF, _("virtual memory exhausted")); - return result; -} - - -char * -xrealloc (char *ptr, unsigned int size) -{ - char *result; - - /* Some older implementations of realloc() don't conform to ANSI. */ - if (! size) - size = 1; - result = ptr ? realloc (ptr, size) : malloc (size); - if (result == 0) - fatal (NILF, _("virtual memory exhausted")); - return result; -} - - -char * -xstrdup (const char *ptr) -{ - char *result; - -#ifdef HAVE_STRDUP - result = strdup (ptr); -#else - result = (char *) malloc (strlen (ptr) + 1); -#endif - - if (result == 0) - fatal (NILF, _("virtual memory exhausted")); - -#ifdef HAVE_STRDUP - return result; -#else - return strcpy(result, ptr); -#endif -} - -#endif /* HAVE_DMALLOC_H */ - -char * -savestring (const char *str, unsigned int length) -{ - register char *out = (char *) xmalloc (length + 1); - if (length > 0) - bcopy (str, out, length); - out[length] = '\0'; - return out; -} - - -/* 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 (*s != '\0' && !isblank ((unsigned char)*s)) - ++s; - return (char *)s; -} - -#ifdef WINDOWS32 -/* - * Same as end_of_token, but take into account a stop character - */ -char * -end_of_token_w32 (char *s, char stopchar) -{ - register char *p = s; - register int backslash = 0; - - while (*p != '\0' && *p != stopchar - && (backslash || !isblank ((unsigned char)*p))) - { - if (*p++ == '\\') - { - backslash = !backslash; - while (*p == '\\') - { - backslash = !backslash; - ++p; - } - } - else - backslash = 0; - } - - return p; -} -#endif - -/* 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. */ - -char * -find_next_token (char **ptr, unsigned int *lengthptr) -{ - char *p = next_token (*ptr); - char *end; - - if (*p == '\0') - return 0; - - *ptr = end = end_of_token (p); - if (lengthptr != 0) - *lengthptr = end - p; - return p; -} - - -/* Allocate a new `struct dep' with all fields initialized to 0. */ - -struct dep * -alloc_dep () -{ - struct dep *d = (struct dep *) xmalloc (sizeof (struct dep)); - bzero ((char *) d, sizeof (struct dep)); - return d; -} - - -/* Free `struct dep' along with `name' and `stem'. */ - -void -free_dep (struct dep *d) -{ - if (d->name != 0) - free (d->name); - - if (d->stem != 0) - free (d->stem); - - free ((char *)d); -} - -/* Copy a chain of `struct dep', making a new chain - with the same contents as the old one. */ - -struct dep * -copy_dep_chain (const struct dep *d) -{ - register struct dep *c; - struct dep *firstnew = 0; - struct dep *lastnew = 0; - - while (d != 0) - { - c = (struct dep *) xmalloc (sizeof (struct dep)); - bcopy ((char *) d, (char *) c, sizeof (struct dep)); - - if (c->name != 0) - c->name = xstrdup (c->name); - if (c->stem != 0) - c->stem = xstrdup (c->stem); - - 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'. Each nameseq->name is freed - as well. For `struct dep' chains use free_dep_chain. */ - -void -free_ns_chain (struct nameseq *n) -{ - register struct nameseq *tmp; - - while (n != 0) - { - if (n->name != 0) - free (n->name); - - tmp = n; - - n = n->next; - - free (tmp); - } - -} -#ifdef iAPX286 -/* The losing compiler on this machine can't handle this macro. */ - -char * -dep_name (struct dep *dep) -{ - return dep->name == 0 ? dep->file->name : dep->name; -} -#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 - - -/* 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. */ - -void -close_stdout (void) -{ - int prev_fail = ferror (stdout); - int fclose_fail = fclose (stdout); - - if (prev_fail || fclose_fail) - { - if (fclose_fail) - error (NILF, _("write error: %s"), strerror (errno)); - else - error (NILF, _("write error")); - exit (EXIT_FAILURE); - } -} diff --git a/src/bin/make/read.c b/src/bin/make/read.c deleted file mode 100644 index f6e89861eb..0000000000 --- a/src/bin/make/read.c +++ /dev/null @@ -1,3138 +0,0 @@ -/* Reading and parsing of makefiles for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#include - -#include - -#include "dep.h" -#include "filedef.h" -#include "job.h" -#include "commands.h" -#include "variable.h" -#include "rule.h" -#include "debug.h" -#include "hash.h" - - -#ifndef WINDOWS32 -#ifndef _AMIGA -#ifndef VMS -#include -#else -struct passwd *getpwnam PARAMS ((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. */ - struct floc floc; /* Info on the file in fp (if any). */ - }; - -/* 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 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 char **include_directories; - -/* Maximum length of an element of the above. */ - -static unsigned int max_incl_len; - -/* The filename and pointer to line number of the - makefile currently being read in. */ - -const struct floc *reading_file = 0; - -/* The chain of makefiles read by read_makefile. */ - -static struct dep *read_makefiles = 0; - -static int eval_makefile PARAMS ((char *filename, int flags)); -static int eval PARAMS ((struct ebuffer *buffer, int flags)); - -static long readline PARAMS ((struct ebuffer *ebuf)); -static void do_define PARAMS ((char *name, unsigned int namelen, - enum variable_origin origin, - struct ebuffer *ebuf)); -static int conditional_line PARAMS ((char *line, int len, const struct floc *flocp)); -static void record_files PARAMS ((struct nameseq *filenames, char *pattern, char *pattern_percent, - struct dep *deps, unsigned int cmds_started, char *commands, - unsigned int commands_idx, int two_colon, - const struct floc *flocp)); -static void record_target_var PARAMS ((struct nameseq *filenames, char *defn, - enum variable_origin origin, - int enabled, - const struct floc *flocp)); -static enum make_word_type get_next_mword PARAMS ((char *buffer, char *delim, - char **startp, unsigned int *length)); -static void remove_comments PARAMS ((char *line)); -static char *find_char_unquote PARAMS ((char *string, int stop1, - int stop2, int blank, int ignorevars)); - -/* Read in all the makefiles and return the chain of their names. */ - -struct dep * -read_all_makefiles (char **makefiles) -{ - unsigned int num_makefiles = 0; - - /* Create *_LIST variables, to hold the makefiles, targets, and variables - we will be reading. */ - - define_variable ("MAKEFILE_LIST", sizeof ("MAKEFILE_LIST")-1, "", o_file, 0); - - 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 (&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; - register struct dep *d; - - if (! eval_makefile (*makefiles, 0)) - perror_with_name ("", *makefiles); - - /* Find the right element of read_makefiles. */ - d = read_makefiles; - while (d->next != tail) - d = d->next; - - /* Use the storage read_makefile allocates. */ - *makefiles = dep_name (d); - ++num_makefiles; - ++makefiles; - } - - /* If there were no -f switches, try the default names. */ - - if (num_makefiles == 0) - { - static 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 */ - { "GNUmakefile", "makefile", "Makefile", 0 }; -#endif /* AMIGA */ -#endif /* VMS */ - register 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_makefiles' 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 (*p); - d->file->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; - - bzero ((char *) new, 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. */ - if (conditionals->ignoring) - free (conditionals->ignoring); - if (conditionals->seen_else) - free (conditionals->seen_else); - - /* Restore state. */ - conditionals = saved; -} - -static int -eval_makefile (char *filename, int flags) -{ - struct dep *deps; - struct ebuffer ebuf; - const struct floc *curfile; - char *expanded = 0; - char *included = 0; - int makefile_errno; - int r; - - ebuf.floc.filenm = strcache_add (filename); - ebuf.floc.lineno = 1; - - if (ISDB (DB_VERBOSE)) - { - 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 = tilde_expand (filename); - if (expanded != 0) - filename = expanded; - } - - ebuf.fp = fopen (filename, "r"); - /* Save the error code so we print the right message later. */ - makefile_errno = errno; - - /* 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 != '/') - { - register unsigned int i; - for (i = 0; include_directories[i] != 0; ++i) - { - included = concat (include_directories[i], "/", filename); - ebuf.fp = fopen (included, "r"); - if (ebuf.fp) - { - filename = included; - break; - } - free (included); - } - /* If we're not using it, we already freed it above. */ - if (filename != included) - included = 0; - } - - /* 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 (xstrdup (filename)); - filename = deps->file->name; - deps->changed = flags; - if (flags & RM_DONTCARE) - deps->file->dontcare = 1; - - if (expanded) - free (expanded); - if (included) - free (included); - - /* 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; - } - - /* Add this makefile to the list. */ - do_variable_definition (&ebuf.floc, "MAKEFILE_LIST", filename, o_file, - f_append, 0); - - /* Evaluate the makefile */ - - ebuf.size = 200; - ebuf.buffer = ebuf.bufnext = ebuf.bufstart = xmalloc (ebuf.size); - - curfile = reading_file; - reading_file = &ebuf.floc; - - r = eval (&ebuf, !(flags & RM_NO_DEFAULT_GOAL)); - - reading_file = curfile; - - fclose (ebuf.fp); - - free (ebuf.bufstart); - alloca (0); - return r; -} - -int -eval_buffer (char *buffer) -{ - struct ebuffer ebuf; - struct conditionals *saved; - struct conditionals new; - const struct floc *curfile; - int r; - - /* Evaluate the buffer */ - - ebuf.size = strlen (buffer); - ebuf.buffer = ebuf.bufnext = ebuf.bufstart = buffer; - ebuf.fp = NULL; - - ebuf.floc = *reading_file; - - curfile = reading_file; - reading_file = &ebuf.floc; - - saved = install_conditionals (&new); - - r = eval (&ebuf, 1); - - restore_conditionals (saved); - - reading_file = curfile; - - alloca (0); - return r; -} - - -/* 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 int -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; - struct dep *deps = 0; - long nlines = 0; - int two_colon = 0; - char *pattern = 0, *pattern_percent; - struct floc *fstart; - struct floc fi; - -#define record_waiting_files() \ - do \ - { \ - if (filenames != 0) \ - { \ - fi.lineno = tgts_started; \ - record_files (filenames, pattern, pattern_percent, deps, \ - cmds_started, commands, commands_idx, two_colon, \ - &fi); \ - } \ - filenames = 0; \ - commands_idx = 0; \ - no_targets = 0; \ - if (pattern) { free(pattern); 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 _without_ ending any rule that we happen to be working - with at the moment. If you see a "goto rule_complete", then the - statement we just parsed also finishes the previous rule. */ - - commands = xmalloc (200); - - while (1) - { - unsigned int linelen; - char *line; - int len; - char *p; - char *p2; - - /* 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; - - /* If this line is empty, skip it. */ - line = ebuf->buffer; - if (line[0] == '\0') - continue; - - linelen = strlen (line); - - /* Check for a shell command line first. - If it is not one, we can stop treating tab specially. */ - if (line[0] == '\t') - { - 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 tab character. - 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; - - /* Append this command line to the line being accumulated. */ - if (commands_idx == 0) - cmds_started = ebuf->floc.lineno; - - if (linelen + 1 + commands_idx > commands_len) - { - commands_len = (linelen + 1 + commands_idx) * 2; - commands = xrealloc (commands, commands_len); - } - bcopy (line, &commands[commands_idx], linelen); - commands_idx += linelen; - commands[commands_idx++] = '\n'; - - continue; - } - } - - /* This line is not a shell command line. Don't worry about tabs. - 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; - if (collapsed) - free ((char *)collapsed); - collapsed = (char *) xmalloc (collapsed_length); - } - strcpy (collapsed, line); - /* Collapse continuation lines. */ - collapse_continuations (collapsed); - remove_comments (collapsed); - - /* Compare a word, both length and contents. */ -#define word1eq(s) (len == sizeof(s)-1 && strneq (s, p, sizeof(s)-1)) - p = collapsed; - while (isspace ((unsigned char)*p)) - ++p; - - if (*p == '\0') - /* This line is completely empty--ignore it. */ - continue; - - /* Find the end of the first token. Note we don't need to worry about - * ":" here since we compare tokens by length (so "export" will never - * be equal to "export:"). - */ - for (p2 = p+1; *p2 != '\0' && !isspace ((unsigned char)*p2); ++p2) - ; - len = p2 - p; - - /* Find the start of the second token. If it looks like a target or - variable definition it can't be a preprocessor token so skip - them--this allows variables/targets named `ifdef', `export', etc. */ - while (isspace ((unsigned char)*p2)) - ++p2; - - if ((p2[0] == ':' || p2[0] == '+' || p2[0] == '=') && p2[1] == '\0') - { - /* It can't be a preprocessor token so skip it if we're ignoring */ - if (ignoring) - continue; - - goto skip_conditionals; - } - - /* We must first check for conditional and `define' directives before - ignoring anything, since they control what we will do with - following lines. */ - - if (!in_ignored_define) - { - int i = conditional_line (p, len, fstart); - if (i != -2) - { - if (i == -1) - fatal (fstart, _("invalid syntax in conditional")); - - ignoring = i; - continue; - } - } - - if (word1eq ("endef")) - { - if (!in_ignored_define) - fatal (fstart, _("extraneous `endef'")); - in_ignored_define = 0; - continue; - } - - if (word1eq ("define")) - { - if (ignoring) - in_ignored_define = 1; - else - { - if (*p2 == '\0') - fatal (fstart, _("empty variable name")); - - /* Let the variable name be the whole rest of the line, - with trailing blanks stripped (comments have already been - removed), so it could be a complex variable/function - reference that might contain blanks. */ - p = strchr (p2, '\0'); - while (isblank ((unsigned char)p[-1])) - --p; - do_define (p2, p - p2, o_file, ebuf); - } - continue; - } - - if (word1eq ("override")) - { - if (*p2 == '\0') - error (fstart, _("empty `override' directive")); - - if (strneq (p2, "define", 6) - && (isblank ((unsigned char)p2[6]) || p2[6] == '\0')) - { - if (ignoring) - in_ignored_define = 1; - else - { - p2 = next_token (p2 + 6); - if (*p2 == '\0') - fatal (fstart, _("empty variable name")); - - /* Let the variable name be the whole rest of the line, - with trailing blanks stripped (comments have already been - removed), so it could be a complex variable/function - reference that might contain blanks. */ - p = strchr (p2, '\0'); - while (isblank ((unsigned char)p[-1])) - --p; - do_define (p2, p - p2, o_override, ebuf); - } - } - else if (!ignoring - && !try_variable_definition (fstart, p2, o_override, 0)) - error (fstart, _("invalid `override' directive")); - - continue; - } - - if (ignoring) - /* Ignore the line. We continue here so conditionals - can appear in the middle of a rule. */ - continue; - - if (word1eq ("export")) - { - /* 'export' by itself causes everything to be exported. */ - if (*p2 == '\0') - export_all_variables = 1; - else - { - struct variable *v; - - v = try_variable_definition (fstart, p2, o_file, 0); - if (v != 0) - v->export = v_export; - else - { - unsigned int len; - char *ap; - - /* Expand the line so we can use indirect and constructed - variable names in an export command. */ - p2 = ap = allocated_variable_expand (p2); - - for (p = find_next_token (&p2, &len); p != 0; - p = find_next_token (&p2, &len)) - { - v = lookup_variable (p, len); - if (v == 0) - v = define_variable_loc (p, len, "", o_file, 0, - fstart); - v->export = v_export; - } - - free (ap); - } - } - goto rule_complete; - } - - if (word1eq ("unexport")) - { - if (*p2 == '\0') - export_all_variables = 0; - else - { - unsigned int len; - struct variable *v; - char *ap; - - /* Expand the line so we can use indirect and constructed - variable names in an unexport command. */ - p2 = ap = allocated_variable_expand (p2); - - for (p = find_next_token (&p2, &len); p != 0; - p = find_next_token (&p2, &len)) - { - v = lookup_variable (p, len); - if (v == 0) - v = define_variable_loc (p, len, "", o_file, 0, fstart); - - v->export = v_noexport; - } - - free (ap); - } - goto rule_complete; - } - - skip_conditionals: - if (word1eq ("vpath")) - { - char *pattern; - unsigned int len; - p2 = variable_expand (p2); - p = find_next_token (&p2, &len); - if (p != 0) - { - pattern = savestring (p, len); - p = find_next_token (&p2, &len); - /* No searchpath means remove all previous - selective VPATH's with the same pattern. */ - } - else - /* No pattern means remove all previous selective VPATH's. */ - pattern = 0; - construct_vpath_list (pattern, p); - if (pattern != 0) - free (pattern); - - goto rule_complete; - } - - 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'); - - 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. */ - p2 = p; - files = multi_glob (parse_file_seq (&p2, '\0', - sizeof (struct nameseq), - 1), - sizeof (struct nameseq)); - 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; - char *name = files->name; - int r; - - free ((char *)files); - files = next; - - r = eval_makefile (name, (RM_INCLUDED | RM_NO_TILDE - | (noerror ? RM_DONTCARE : 0))); - if (!r && !noerror) - error (fstart, "%s: %s", name, strerror (errno)); - free (name); - } - - /* Restore conditional state. */ - restore_conditionals (save); - - goto rule_complete; - } - - if (try_variable_definition (fstart, p, o_file, 0)) - /* This line has been dealt with. */ - goto rule_complete; - - /* 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] == '\t') - fatal(fstart, _("commands commence 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; - enum variable_origin v_origin; - int exported; - char *cmdleft, *semip, *lb_next; - unsigned int len, 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, ';', '#', 0, 1); - 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, &len); - switch (wtype) - { - case w_eol: - if (cmdleft != 0) - fatal(fstart, _("missing rule before commands")); - /* 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, len); - - while (1) - { - lb_next += len; - if (cmdleft == 0) - { - /* Look for a semicolon in the expanded line. */ - cmdleft = find_char_unquote (p2, ';', 0, 0, 0); - - 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-compatiblity. 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, ':', 0, 0, 0); -#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, ':', 0, 0, 0); -#endif - if (colonp != 0) - break; - - wtype = get_next_mword(lb_next, NULL, &lb_next, &len); - if (wtype == w_eol) - break; - - p2 += strlen(p2); - *(p2++) = ' '; - p2 = variable_expand_string(p2, lb_next, len); - /* 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') - /* There's no need to be ivory-tower about this: check for - one of the most common bugs found in makefiles... */ - fatal (fstart, _("missing separator%s"), - !strneq(line, " ", 8) ? "" - : _(" (did you mean TAB instead of 8 spaces?)")); - continue; - } - - /* Make the colon the end-of-string so we know where to stop - looking for targets. */ - *colonp = '\0'; - filenames = multi_glob (parse_file_seq (&p2, '\0', - sizeof (struct nameseq), - 1), - sizeof (struct nameseq)); - *p2 = ':'; - - 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); - (void) variable_buffer_output (p2+plen, - lb_next, strlen (lb_next)+1); - p2 = variable_buffer + l; - } - - /* See if it's an "override" or "export" keyword; if so see if what - comes after it looks like a variable definition. */ - - wtype = get_next_mword (p2, NULL, &p, &len); - - v_origin = o_file; - exported = 0; - if (wtype == w_static) - { - if (word1eq ("override")) - { - v_origin = o_override; - wtype = get_next_mword (p+len, NULL, &p, &len); - } - else if (word1eq ("export")) - { - exported = 1; - wtype = get_next_mword (p+len, NULL, &p, &len); - } - } - - if (wtype != w_eol) - wtype = get_next_mword (p+len, NULL, NULL, NULL); - - if (wtype == w_varassign) - { - /* If there was a semicolon found, add it back, plus anything - after it. */ - if (semip) - { - unsigned int l = p - variable_buffer; - *(--semip) = ';'; - variable_buffer_output (p2 + strlen (p2), - semip, strlen (semip)+1); - p = variable_buffer + l; - } - record_target_var (filenames, p, v_origin, exported, 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, '=', 0, 0, 0); - - /* 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, ';', 0, 0, 0); - if (cmdleft != 0) - *(cmdleft++) = '\0'; - } - } - - /* Is this a static pattern rule: `target: %targ: %dep; ...'? */ - p = strchr (p2, ':'); - while (p != 0 && p[-1] == '\\') - { - register char *q = &p[-1]; - register 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, ':', sizeof (struct nameseq), 1); - ++p2; - if (target == 0) - fatal (fstart, _("missing target pattern")); - else if (target->next != 0) - fatal (fstart, _("multiple target patterns")); - pattern = target->name; - pattern_percent = find_percent (pattern); - if (pattern_percent == 0) - fatal (fstart, _("target pattern contains no `%%'")); - free ((char *)target); - } - else - pattern = 0; - - /* Strip leading and trailing whitespaces. */ - beg = p2; - end = beg + strlen (beg) - 1; - strip_whitespace (&beg, &end); - - if (beg <= end && *beg != '\0') - { - /* Put all the prerequisites here; they'll be parsed later. */ - deps = alloc_dep (); - deps->name = savestring (beg, end - beg + 1); - } - else - deps = 0; - - commands_idx = 0; - if (cmdleft != 0) - { - /* Semicolon means rest of line is a command. */ - unsigned int len = strlen (cmdleft); - - cmds_started = fstart->lineno; - - /* Add this command line to the buffer. */ - if (len + 2 > commands_len) - { - commands_len = (len + 2) * 2; - commands = (char *) xrealloc (commands, commands_len); - } - bcopy (cmdleft, commands, len); - commands_idx += len; - 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 some of the logic - here. */ - - if (**default_goal_name == '\0' && set_default) - { - char* name; - struct dep *d; - struct nameseq *t = filenames; - - for (; t != 0; t = t->next) - { - int reject = 0; - 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) - { - register unsigned int len = strlen (dep_name (d2)); - if (!strneq (name, dep_name (d2), len)) - continue; - if (streq (name + len, 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. */ - rule_complete: - record_waiting_files (); - } - -#undef word1eq - - if (conditionals->if_cmds) - fatal (fstart, _("missing `endif'")); - - /* At eof, record the last rule. */ - record_waiting_files (); - - if (collapsed) - free ((char *) collapsed); - free ((char *) commands); - - return 1; -} - - -/* Remove comments from LINE. - This is done by copying the text at LINE onto itself. */ - -static void -remove_comments (char *line) -{ - char *comment; - - comment = find_char_unquote (line, '#', 0, 0, 0); - - if (comment != 0) - /* Cut off the line at the #. */ - *comment = '\0'; -} - -/* 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 void -do_define (char *name, unsigned int namelen, - enum variable_origin origin, struct ebuffer *ebuf) -{ - struct floc defstart; - long nlines = 0; - int nlevels = 1; - unsigned int length = 100; - char *definition = (char *) xmalloc (length); - unsigned int idx = 0; - char *p; - - /* Expand the variable name. */ - char *var = (char *) alloca (namelen + 1); - bcopy (name, var, namelen); - var[namelen] = '\0'; - var = variable_expand (var); - - defstart = ebuf->floc; - - while (1) - { - unsigned int len; - char *line; - - nlines = readline (ebuf); - ebuf->floc.lineno += nlines; - - /* If there is nothing left to eval, we're done. */ - if (nlines < 0) - break; - - 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] != '\t') - { - 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); - if (*next_token (p) != '\0') - error (&ebuf->floc, - _("Extraneous text after `endef' directive")); - - if (--nlevels == 0) - { - /* Define the variable. */ - if (idx == 0) - definition[0] = '\0'; - else - definition[idx - 1] = '\0'; - - /* Always define these variables in the global set. */ - define_variable_global (var, strlen (var), definition, - origin, 1, &defstart); - free (definition); - return; - } - } - } - - /* Otherwise add this line to the variable definition. */ - len = strlen (line); - if (idx + len + 1 > length) - { - length = (idx + len) * 2; - definition = (char *) xrealloc (definition, length + 1); - } - - bcopy (line, &definition[idx], len); - idx += len; - /* Separate lines with a newline. */ - definition[idx++] = '\n'; - } - - /* No `endef'!! */ - fatal (&defstart, _("missing `endef', unterminated `define'")); - - /* NOTREACHED */ - return; -} - -/* 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 struct floc *flocp) -{ - 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 == sizeof(s)-1 && strneq (s, line, sizeof(s)-1)) -#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 EXTRANEOUS() error (flocp, _("Extraneous text after `%s' directive"), cmdname) - - /* An 'endif' cannot contain extra text, and reduces the if-depth by 1 */ - if (cmdtype == c_endif) - { - if (*line != '\0') - EXTRANEOUS (); - - if (!conditionals->if_cmds) - fatal (flocp, _("extraneous `%s'"), cmdname); - - --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) - fatal (flocp, _("extraneous `%s'"), cmdname); - - o = conditionals->if_cmds - 1; - - if (conditionals->seen_else[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; *p != '\0' && !isspace ((unsigned char)*p); ++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) - EXTRANEOUS (); - 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 = (char *) xmalloc (conditionals->allocated); - conditionals->seen_else = (char *) xmalloc (conditionals->allocated); - } - - o = conditionals->if_cmds++; - if (conditionals->if_cmds > conditionals->allocated) - { - conditionals->allocated += 5; - conditionals->ignoring = (char *) - xrealloc (conditionals->ignoring, conditionals->allocated); - conditionals->seen_else = (char *) - 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 len; - 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. */ - len = strlen (s2); - s1 = (char *) alloca (len + 1); - bcopy (s2, s1, len + 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 == ')') - { - register 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') - EXTRANEOUS (); - - 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; -} - -/* Remove duplicate dependencies in CHAIN. */ - -static unsigned long -dep_hash_1 (const void *key) -{ - return_STRING_HASH_1 (dep_name ((struct dep const *) key)); -} - -static unsigned long -dep_hash_2 (const void *key) -{ - return_STRING_HASH_2 (dep_name ((struct dep const *) key)); -} - -static int -dep_hash_cmp (const void *x, const void *y) -{ - struct dep *dx = (struct dep *) x; - struct dep *dy = (struct dep *) y; - int cmp = strcmp (dep_name (dx), dep_name (dy)); - - /* If the names are the same but ignore_mtimes are not equal, one of these - is an order-only prerequisite and one isn't. That means that we should - remove the one that isn't and keep the one that is. */ - - if (!cmp && dx->ignore_mtime != dy->ignore_mtime) - dx->ignore_mtime = dy->ignore_mtime = 0; - - return cmp; -} - - -void -uniquize_deps (struct dep *chain) -{ - struct hash_table deps; - register struct dep **depp; - - hash_init (&deps, 500, dep_hash_1, dep_hash_2, dep_hash_cmp); - - /* Make sure that no dependencies are repeated. This does not - really matter for the purpose of updating targets, but it - might make some names be listed twice for $^ and $?. */ - - depp = &chain; - while (*depp) - { - struct dep *dep = *depp; - struct dep **dep_slot = (struct dep **) hash_find_slot (&deps, dep); - if (HASH_VACANT (*dep_slot)) - { - hash_insert_at (&deps, dep, dep_slot); - depp = &dep->next; - } - else - { - /* Don't bother freeing duplicates. - It's dangerous and little benefit accrues. */ - *depp = dep->next; - } - } - - hash_free (&deps, 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, int exported, - const struct 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; - register char *name = filenames->name; - char *fname; - char *percent; - struct pattern_var *p; - - nextf = filenames->next; - free ((char *) filenames); - - /* If it's a pattern target, then add it to the pattern-specific - variable list. */ - percent = find_percent (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 = parse_variable_definition (&p->variable, defn); - assert (v != 0); - - if (v->flavor == f_simple) - v->value = allocated_variable_expand (v->value); - else - v->value = xstrdup (v->value); - - fname = p->target; - } - 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 (name); - else if (f->double_colon) - f = f->double_colon; - - initialize_file_variables (f, 1); - fname = f->name; - - current_variable_set_list = f->variables; - v = try_variable_definition (flocp, defn, origin, 1); - if (!v) - error (flocp, _("Malformed target-specific variable definition")); - current_variable_set_list = global; - } - - /* Set up the variable to be *-specific. */ - v->origin = origin; - v->per_target = 1; - v->export = exported ? 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 (origin != o_override) - { - struct variable *gv; - int len = strlen(v->name); - - gv = lookup_variable (v->name, len); - if (gv && (gv->origin == o_env_override || gv->origin == o_command)) - { - if (v->value != 0) - free (v->value); - v->value = xstrdup (gv->value); - v->origin = gv->origin; - v->recursive = gv->recursive; - v->append = 0; - } - } - - /* Free name if not needed further. */ - if (name != fname && (name < fname || name > fname + strlen (fname))) - free (name); - } -} - -/* 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, char *pattern, char *pattern_percent, - struct dep *deps, unsigned int cmds_started, char *commands, - unsigned int commands_idx, int two_colon, - const struct floc *flocp) -{ - struct nameseq *nextf; - int implicit = 0; - unsigned int max_targets = 0, target_idx = 0; - char **targets = 0, **target_percents = 0; - struct commands *cmds; - - /* 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) - fatal (flocp, _("prerequisites cannot be defined in command scripts")); - - if (commands_idx > 0) - { - cmds = (struct commands *) xmalloc (sizeof (struct commands)); - cmds->fileinfo.filenm = flocp->filenm; - cmds->fileinfo.lineno = cmds_started; - cmds->commands = savestring (commands, commands_idx); - cmds->command_lines = 0; - } - else - cmds = 0; - - for (; filenames != 0; filenames = nextf) - { - char *name = filenames->name; - struct file *f; - struct dep *this = 0; - char *implicit_percent; - - nextf = filenames->next; - free (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; - else if (streq (name, ".SECONDEXPANSION")) - second_expansion = 1; - - implicit_percent = find_percent (name); - implicit |= implicit_percent != 0; - - if (implicit && pattern != 0) - fatal (flocp, _("mixed implicit and static pattern rules")); - - if (implicit && implicit_percent == 0) - fatal (flocp, _("mixed implicit and normal rules")); - - if (implicit) - { - if (targets == 0) - { - max_targets = 5; - targets = (char **) xmalloc (5 * sizeof (char *)); - target_percents = (char **) xmalloc (5 * sizeof (char *)); - target_idx = 0; - } - else if (target_idx == max_targets - 1) - { - max_targets += 5; - targets = (char **) xrealloc ((char *) targets, - max_targets * sizeof (char *)); - target_percents - = (char **) xrealloc ((char *) target_percents, - max_targets * sizeof (char *)); - } - targets[target_idx] = name; - target_percents[target_idx] = implicit_percent; - ++target_idx; - continue; - } - - /* If this is a static pattern rule: - `targets: target%pattern: dep%pattern; cmds', - make sure the pattern matches this target name. */ - if (pattern && !pattern_matches (pattern, pattern_percent, name)) - error (flocp, _("target `%s' doesn't match the target pattern"), name); - else if (deps) - { - /* If there are multiple filenames, 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; - this->need_2nd_expansion = (second_expansion - && strchr (this->name, '$')); - } - - if (!two_colon) - { - /* Single-colon. Combine these dependencies - with others in file's existing record, if any. */ - f = enter_file (name); - - if (f->double_colon) - 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) - 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) - { - error (&cmds->fileinfo, - _("warning: overriding commands for target `%s'"), - f->name); - error (&f->cmds->fileinfo, - _("warning: ignoring old commands for target `%s'"), - f->name); - } - - f->is_target = 1; - - /* 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 if (this != 0) - { - /* Add the file's old deps and the new ones in THIS together. */ - - if (f->deps != 0) - { - struct dep **d_ptr = &f->deps; - - while ((*d_ptr)->next != 0) - d_ptr = &(*d_ptr)->next; - - if (cmds != 0) - /* This is the rule with commands, so put its deps - last. The rationale behind this is that $< expands to - the first dep in the chain, and commands use $< - expecting to get the dep that rule specifies. However - the second expansion algorithm reverses the order thus - we need to make it last here. */ - (*d_ptr)->next = this; - else - { - /* This is the rule without commands. Put its - dependencies at the end but before dependencies from - the rule with commands (if any). This way everything - appears in makefile order. */ - - if (f->cmds != 0) - { - this->next = *d_ptr; - *d_ptr = this; - } - else - (*d_ptr)->next = this; - } - } - else - f->deps = this; - - /* This is a hack. I need a way to communicate to snap_deps() - that the last dependency line in this file came with commands - (so that logic in snap_deps() can put it in front and all - this $< -logic works). I cannot simply rely on file->cmds - being not 0 because of the cases like the following: - - foo: bar - foo: - ... - - I am going to temporarily "borrow" UPDATING member in - `struct file' for this. */ - - if (cmds != 0) - f->updating = 1; - } - } - 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) - fatal (flocp, - _("target file `%s' has both : and :: entries"), f->name); - f = enter_file (name); - /* 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->is_target = 1; - f->deps = this; - f->cmds = cmds; - } - - /* 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 (pattern) - { - static char *percent = "%"; - char *buffer = variable_expand (""); - char *o = patsubst_expand (buffer, name, pattern, percent, - pattern_percent+1, percent+1); - f->stem = savestring (buffer, o - buffer); - if (this) - { - this->staticpattern = 1; - this->stem = xstrdup (f->stem); - } - } - - /* Free name if not needed further. */ - if (f != 0 && name != f->name - && (name < f->name || name > f->name + strlen (f->name))) - { - free (name); - name = f->name; - } - - /* If this target is a default target, update DEFAULT_GOAL_FILE. */ - if (streq (*default_goal_name, name) - && (default_goal_file == 0 - || ! streq (default_goal_file->name, name))) - default_goal_file = f; - } - - if (implicit) - { - targets[target_idx] = 0; - target_percents[target_idx] = 0; - if (deps) - deps->need_2nd_expansion = second_expansion; - create_pattern_rule (targets, target_percents, two_colon, deps, cmds, 1); - free ((char *) target_percents); - } -} - -/* 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 stop1, int stop2, int blank, - int ignorevars) -{ - unsigned int string_len = 0; - register char *p = string; - - if (ignorevars) - ignorevars = '$'; - - while (1) - { - if (stop2 && blank) - while (*p != '\0' && *p != ignorevars && *p != stop1 && *p != stop2 - && ! isblank ((unsigned char) *p)) - ++p; - else if (stop2) - while (*p != '\0' && *p != ignorevars && *p != stop1 && *p != stop2) - ++p; - else if (blank) - while (*p != '\0' && *p != ignorevars && *p != stop1 - && ! isblank ((unsigned char) *p)) - ++p; - else - while (*p != '\0' && *p != ignorevars && *p != stop1) - ++p; - - if (*p == '\0') - break; - - /* If we stopped due to a variable reference, skip over its contents. */ - if (*p == ignorevars) - { - 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. */ - register 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. */ - bcopy (&p[i / 2], &p[i], (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; -} - -/* Search PATTERN for an unquoted %. */ - -char * -find_percent (char *pattern) -{ - return find_char_unquote (pattern, '%', 0, 0, 0); -} - -/* Parse a string into a sequence of filenames represented as a - chain of struct nameseq's in reverse order and return that chain. - - 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. - - If STRIP is nonzero, strip `./'s off the beginning. */ - -struct nameseq * -parse_file_seq (char **stringp, int stopchar, unsigned int size, int strip) -{ - struct nameseq *new = 0; - struct nameseq *new1, *lastnew1; - char *p = *stringp; - char *q; - char *name; - -#ifdef VMS -# define VMS_COMMA ',' -#else -# define VMS_COMMA 0 -#endif - - while (1) - { - /* Skip whitespace; see if any more names are left. */ - p = next_token (p); - if (*p == '\0') - break; - if (*p == stopchar) - break; - - /* Yes, find end of next name. */ - q = p; - p = find_char_unquote (q, stopchar, VMS_COMMA, 1, 0); -#ifdef VMS - /* convert comma separated list to space separated */ - if (p && *p == ',') - *p =' '; -#endif -#ifdef _AMIGA - if (stopchar == ':' && p && *p == ':' - && !(isspace ((unsigned char)p[1]) || !p[1] - || isspace ((unsigned char)p[-1]))) - { - p = find_char_unquote (p+1, stopchar, VMS_COMMA, 1, 0); - } -#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 (stopchar == ':') - while (p != 0 && !isspace ((unsigned char)*p) && - (p[1] == '\\' || p[1] == '/') && isalpha ((unsigned char)p[-1])) - p = find_char_unquote (p + 1, stopchar, VMS_COMMA, 1, 0); -#endif - if (p == 0) - p = q + strlen (q); - - if (strip) -#ifdef VMS - /* Skip leading `[]'s. */ - while (p - q > 2 && q[0] == '[' && q[1] == ']') -#else - /* Skip leading `./'s. */ - while (p - q > 2 && q[0] == '.' && q[1] == '/') -#endif - { - q += 2; /* Skip "./". */ - while (q < p && *q == '/') - /* Skip following slashes: ".//foo" is "foo", not "/foo". */ - ++q; - } - - /* Extract the filename just found, and skip it. */ - - if (q == p) - /* ".///" was stripped to "". */ -#ifdef VMS - continue; -#else -#ifdef _AMIGA - name = savestring ("", 0); -#else - name = savestring ("./", 2); -#endif -#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. - * Savestring called because q may be read-only string constant. - */ - { - char *qbase = xstrdup (q); - char *pbase = qbase + (p-q); - char *q1 = qbase; - char *q2 = q1; - char *p1 = pbase; - - while (q1 != pbase) - { - if (*q1 == '\\' && *(q1+1) == ':') - { - q1++; - p1--; - } - *q2++ = *q1++; - } - name = savestring (qbase, p1 - qbase); - free (qbase); - } -#else - name = savestring (q, p - q); -#endif - - /* Add it to the front of the chain. */ - new1 = (struct nameseq *) xmalloc (size); - new1->name = name; - new1->next = new; - new = new1; - } - -#ifndef NO_ARCHIVES - - /* Look for multi-word archive references. - They are indicated by a elt ending with an unmatched `)' and - an elt further down the chain (i.e., previous in the file list) - with an unmatched `(' (e.g., "lib(mem"). */ - - new1 = new; - lastnew1 = 0; - while (new1 != 0) - if (new1->name[0] != '(' /* Don't catch "(%)" and suchlike. */ - && new1->name[strlen (new1->name) - 1] == ')' - && strchr (new1->name, '(') == 0) - { - /* NEW1 ends with a `)' but does not contain a `('. - Look back for an elt with an opening `(' but no closing `)'. */ - - struct nameseq *n = new1->next, *lastn = new1; - char *paren = 0; - while (n != 0 && (paren = strchr (n->name, '(')) == 0) - { - lastn = n; - n = n->next; - } - if (n != 0 - /* 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). */ - && n->name[0] != '(') - { - /* N is the first element in the archive group. - Its name looks like "lib(mem" (with no closing `)'). */ - - char *libname; - - /* Copy "lib(" into LIBNAME. */ - ++paren; - libname = (char *) alloca (paren - n->name + 1); - bcopy (n->name, libname, paren - n->name); - libname[paren - n->name] = '\0'; - - if (*paren == '\0') - { - /* N was just "lib(", part of something like "lib( a b)". - Edit it out of the chain and free its storage. */ - lastn->next = n->next; - free (n->name); - free ((char *) n); - /* LASTN->next is the new stopping elt for the loop below. */ - n = lastn->next; - } - else - { - /* Replace N's name with the full archive reference. */ - name = concat (libname, paren, ")"); - free (n->name); - n->name = name; - } - - if (new1->name[1] == '\0') - { - /* NEW1 is just ")", part of something like "lib(a b )". - Omit it from the chain and free its storage. */ - if (lastnew1 == 0) - new = new1->next; - else - lastnew1->next = new1->next; - lastn = new1; - new1 = new1->next; - free (lastn->name); - free ((char *) lastn); - } - else - { - /* Replace also NEW1->name, which already has closing `)'. */ - name = concat (libname, new1->name, ""); - free (new1->name); - new1->name = name; - new1 = new1->next; - } - - /* Trace back from NEW1 (the end of the list) until N - (the beginning of the list), rewriting each name - with the full archive reference. */ - - while (new1 != n) - { - name = concat (libname, new1->name, ")"); - free (new1->name); - new1->name = name; - lastnew1 = new1; - new1 = new1->next; - } - } - else - { - /* No frobnication happening. Just step down the list. */ - lastnew1 = new1; - new1 = new1->next; - } - } - else - { - lastnew1 = new1; - new1 = new1->next; - } - -#endif - - *stringp = p; - return new; -} - -/* 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; - char *bol = eol; - char *p; - - /* Find the next newline. At EOS, stop. */ - eol = p = 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. */ - 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; - p[-1] = '\n'; - } -#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 = (char *) 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; - wtype = w_dcolon; - break; - - case '=': - ++p; - wtype = w_varassign; - break; - } - break; - - 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 (char **arg_dirs) -{ - register unsigned int i; -#ifdef VAXC /* just don't ask ... */ - stat_t stbuf; -#else - struct stat stbuf; -#endif - /* Table to hold the dirs. */ - - register unsigned int defsize = (sizeof (default_include_directories) - / sizeof (default_include_directories[0])); - register unsigned int max = 5; - register char **dirs = (char **) xmalloc ((5 + defsize) * sizeof (char *)); - register unsigned int idx = 0; - -#ifdef __MSDOS__ - defsize++; -#endif - - /* First consider any dirs specified with -I switches. - Ignore dirs that don't exist. */ - - if (arg_dirs != 0) - while (*arg_dirs != 0) - { - char *dir = *arg_dirs++; - int e; - - if (dir[0] == '~') - { - char *expanded = tilde_expand (dir); - if (expanded != 0) - dir = expanded; - } - - EINTRLOOP (e, stat (dir, &stbuf)); - if (e == 0 && S_ISDIR (stbuf.st_mode)) - { - if (idx == max - 1) - { - max += 5; - dirs = (char **) - xrealloc ((char *) dirs, (max + defsize) * sizeof (char *)); - } - dirs[idx++] = dir; - } - else if (dir != arg_dirs[-1]) - free (dir); - } - - /* Now add at the end the standard default dirs. */ - -#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) - { - char *defdir = (char *) xmalloc (strlen (djdir->value) + 8 + 1); - - strcat (strcpy (defdir, djdir->value), "/include"); - dirs[idx++] = defdir; - } - } -#endif - - for (i = 0; default_include_directories[i] != 0; ++i) - { - int e; - - EINTRLOOP (e, stat (default_include_directories[i], &stbuf)); - if (e == 0 && S_ISDIR (stbuf.st_mode)) - dirs[idx++] = default_include_directories[i]; - } - - dirs[idx] = 0; - - /* Now compute the maximum length of any name in it. Also add each - dir to the .INCLUDE_DIRS variable. */ - - max_incl_len = 0; - for (i = 0; i < idx; ++i) - { - unsigned int len = strlen (dirs[i]); - /* If dir name is written with a trailing slash, discard it. */ - if (dirs[i][len - 1] == '/') - /* We can't just clobber a null in because it may have come from - a literal string and literal strings may not be writable. */ - dirs[i] = savestring (dirs[i], len - 1); - if (len > max_incl_len) - max_incl_len = len; - - /* Append to .INCLUDE_DIRS. */ - do_variable_definition (NILF, ".INCLUDE_DIRS", dirs[i], - 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 * -tilde_expand (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 = concat (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 concat (pwent->pw_dir, "/", userend + 1); - } - else if (userend != 0) - *userend = '/'; - } -#endif /* !AMIGA && !WINDOWS32 */ -#endif /* !VMS */ - return 0; -} - -/* 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. */ - -struct nameseq * -multi_glob (struct nameseq *chain, unsigned int size) -{ - extern void dir_setup_glob (); - register struct nameseq *new = 0; - register struct nameseq *old; - struct nameseq *nexto; - glob_t gl; - - dir_setup_glob (&gl); - - for (old = chain; old != 0; old = nexto) - { -#ifndef NO_ARCHIVES - char *memname; -#endif - - nexto = old->next; - - if (old->name[0] == '~') - { - char *newname = tilde_expand (old->name); - if (newname != 0) - { - free (old->name); - old->name = newname; - } - } - -#ifndef NO_ARCHIVES - if (ar_name (old->name)) - { - /* OLD->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. */ - char *arname; - ar_parse_name (old->name, &arname, &memname); - free (old->name); - old->name = arname; - } - else - memname = 0; -#endif /* !NO_ARCHIVES */ - - switch (glob (old->name, GLOB_NOCHECK|GLOB_ALTDIRFUNC, NULL, &gl)) - { - case 0: /* Success. */ - { - register int i = gl.gl_pathc; - while (i-- > 0) - { -#ifndef NO_ARCHIVES - if (memname != 0) - { - /* Try to glob on MEMNAME within the archive. */ - struct nameseq *found - = ar_glob (gl.gl_pathv[i], memname, size); - if (found == 0) - { - /* No matches. Use MEMNAME as-is. */ - unsigned int alen = strlen (gl.gl_pathv[i]); - unsigned int mlen = strlen (memname); - struct nameseq *elt - = (struct nameseq *) xmalloc (size); - if (size > sizeof (struct nameseq)) - bzero (((char *) elt) + sizeof (struct nameseq), - size - sizeof (struct nameseq)); - elt->name = (char *) xmalloc (alen + 1 + mlen + 2); - bcopy (gl.gl_pathv[i], elt->name, alen); - elt->name[alen] = '('; - bcopy (memname, &elt->name[alen + 1], mlen); - elt->name[alen + 1 + mlen] = ')'; - elt->name[alen + 1 + mlen + 1] = '\0'; - elt->next = new; - new = elt; - } - else - { - /* Find the end of the FOUND chain. */ - struct nameseq *f = found; - while (f->next != 0) - f = f->next; - - /* Attach the chain being built to the end of the FOUND - chain, and make FOUND the new NEW chain. */ - f->next = new; - new = found; - } - - free (memname); - } - else -#endif /* !NO_ARCHIVES */ - { - struct nameseq *elt = (struct nameseq *) xmalloc (size); - if (size > sizeof (struct nameseq)) - bzero (((char *) elt) + sizeof (struct nameseq), - size - sizeof (struct nameseq)); - elt->name = xstrdup (gl.gl_pathv[i]); - elt->next = new; - new = elt; - } - } - globfree (&gl); - free (old->name); - free ((char *)old); - break; - } - - case GLOB_NOSPACE: - fatal (NILF, _("virtual memory exhausted")); - break; - - default: - old->next = new; - new = old; - break; - } - } - - return new; -} diff --git a/src/bin/make/remake.c b/src/bin/make/remake.c deleted file mode 100644 index a7527347af..0000000000 --- a/src/bin/make/remake.c +++ /dev/null @@ -1,1576 +0,0 @@ -/* Basic dependency engine for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.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 PARAMS ((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 seperate `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 int update_file PARAMS ((struct file *file, unsigned int depth)); -static int update_file_1 PARAMS ((struct file *file, unsigned int depth)); -static int check_dep PARAMS ((struct file *file, unsigned int depth, FILE_TIMESTAMP this_mtime, int *must_make_ptr)); -static int touch_file PARAMS ((struct file *file)); -static void remake_file PARAMS ((struct file *file)); -static FILE_TIMESTAMP name_mtime PARAMS ((char *name)); -static int library_search PARAMS ((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. */ - -int -update_goal_chain (struct dep *goals) -{ - int t = touch_flag, q = question_flag, n = just_print_flag; - unsigned int j = job_slots; - int status = -1; - -#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 (); - - /* Wait for a child to die. */ - - reap_children (1, 0); - - 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; - int x; - 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; - - x = update_file (file, rebuilding_makefiles ? 1 : 0); - 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; - - /* If we updated a file and STATUS was not already 1, set it to - 1 if updating failed, or to 0 if updating succeeded. Leave - STATUS as it is if no updating was done. */ - - stop = 0; - if ((x != 0 || file->updated) && status < 1) - { - if (file->update_status != 0) - { - /* 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 = 0; - 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; - - 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 zero, 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 == 0 && !g->changed - /* Never give a message under -s or -q. */ - && !silent_flag && !question_flag) - message (1, ((file->phony || file->cmds == 0) - ? _("Nothing to be done for `%s'.") - : _("`%s' is up to date.")), - file->name); - - /* This goal is finished. Remove it from the chain. */ - if (lastgoal == 0) - goals = g->next; - else - lastgoal->next = g->next; - - /* Free the storage. */ - free ((char *) 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; - job_slots = j; - } - - return status; -} - -/* If FILE is not up to date, execute the commands for it. - Return 0 if successful, 1 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 int -update_file (struct file *file, unsigned int depth) -{ - register int status = 0; - register 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) - { - 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) - { - f->considered = considered; - - status |= update_file_1 (f, depth); - 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 (status != 0 && !keep_going_flag) - return status; - - 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 = 0; - break; - } - } - - /* 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) - status |= update_file (d->file, depth + 1); - } - - return status; -} - -/* Show a message stating the target failed to build. */ - -static void -complain (const struct file *file) -{ - const char *msg_noparent - = _("%sNo rule to make target `%s'%s"); - const char *msg_parent - = _("%sNo rule to make target `%s', needed by `%s'%s"); - - if (!keep_going_flag) - { - if (file->parent == 0) - fatal (NILF, msg_noparent, "", file->name, ""); - - fatal (NILF, msg_parent, "", file->name, file->parent->name, ""); - } - - if (file->parent == 0) - error (NILF, msg_noparent, "*** ", file->name, "."); - else - error (NILF, msg_parent, "*** ", file->name, file->parent->name, "."); -} - -/* Consider a single `struct file' and update it as appropriate. */ - -static int -update_file_1 (struct file *file, unsigned int depth) -{ - register FILE_TIMESTAMP this_mtime; - int noexist, must_make, deps_changed; - int dep_status = 0; - register struct dep *d, *lastd; - int running = 0; - - DBF (DB_VERBOSE, _("Considering target file `%s'.\n")); - - if (file->updated) - { - if (file->update_status > 0) - { - DBF (DB_VERBOSE, - _("Recently tried and failed to update file `%s'.\n")); - - /* If the file we tried to make is marked dontcare 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->dontcare && !rebuilding_makefiles) - { - file->dontcare = 0; - complain (file); - } - - return file->update_status; - } - - DBF (DB_VERBOSE, _("File `%s' was considered already.\n")); - 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")); - return 0; - case cs_finished: - DBF (DB_VERBOSE, _("Finished updating file `%s'.\n")); - return file->update_status; - default: - abort (); - } - - ++depth; - - /* Notice recursive update of the same file. */ - start_updating (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")); - 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) - 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 commands 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. */ - - lastd = 0; - d = file->deps; - while (d != 0) - { - 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)) - { - 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; - } - - - dep_status |= check_dep (d->file, depth, this_mtime, &maybe_make); - - /* 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 != 0 && !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. - This causes the Linux kernel build to break. We'll defer this - fix until GNU make 3.82 to give them time to update. */ - 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) - { - 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; - } - - - dep_status |= update_file (d->file, depth); - - /* 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 != 0 && !keep_going_flag) - break; - - if (!running) - d->changed = ((file->phony && file->cmds != 0) - || file_mtime (d->file) != mtime); - } - } - - finish_updating (file); - - DBF (DB_VERBOSE, _("Finished prerequisites of target file `%s'.\n")); - - if (running) - { - set_command_state (file, cs_deps_running); - --depth; - DBF (DB_VERBOSE, _("The prerequisites of `%s' are being made.\n")); - return 0; - } - - /* If any dependency failed, give up now. */ - - if (dep_status != 0) - { - file->update_status = dep_status; - notice_finished_file (file); - - --depth; - - DBF (DB_VERBOSE, _("Giving up on target file `%s'.\n")); - - if (depth == 0 && keep_going_flag - && !just_print_flag && !question_flag) - error (NILF, - _("Target `%s' not remade because of errors."), file->name); - - 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 commands 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. */ - - while (file) - { - file->name = file->hname; - file = file->prev; - } - - 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); - - if (file->command_state != cs_finished) - { - DBF (DB_VERBOSE, _("Commands of `%s' are being run.\n")); - return 0; - } - - switch (file->update_status) - { - case 2: - DBF (DB_BASIC, _("Failed to remake target file `%s'.\n")); - break; - case 0: - DBF (DB_BASIC, _("Successfully remade target file `%s'.\n")); - break; - case 1: - DBF (DB_BASIC, _("Target file `%s' needs remade under -q.\n")); - break; - default: - assert (file->update_status >= 0 && file->update_status <= 2); - break; - } - - file->updated = 1; - 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 -1 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: - -1 if this target was not remade; - 0 if 0 or more commands (+ or ${MAKE}) were run and won; - 1 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 == 0) - { - 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 = 0; - /* 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) - { - 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 != -1) - /* 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. */ - (void) f_mtime (d->file, 0); - } - else if (file->update_status == -1) - /* Nothing was done for FILE, but it needed nothing done. - So mark it now as "succeeded". */ - file->update_status = 0; -} - -/* 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 int -check_dep (struct file *file, unsigned int depth, - FILE_TIMESTAMP this_mtime, int *must_make_ptr) -{ - struct dep *d; - int dep_status = 0; - - ++depth; - start_updating (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); - 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; - } - - /* If the intermediate file actually exists - and is newer, then we should remake from it. */ - check_renamed (file); - mtime = file_mtime (file); - check_renamed (file); - if (mtime != NONEXISTENT_MTIME && mtime > this_mtime) - *must_make_ptr = 1; - /* 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. */ - else - { - struct dep *lastd; - - lastd = 0; - d = file->deps; - while (d != 0) - { - int maybe_make; - - if (is_updating (d->file)) - { - error (NILF, _("Circular %s <- %s dependency dropped."), - file->name, d->file->name); - if (lastd == 0) - { - file->deps = d->next; - free_dep (d); - d = file->deps; - } - else - { - lastd->next = d->next; - free_dep (d); - d = lastd->next; - } - continue; - } - - d->file->parent = file; - maybe_make = *must_make_ptr; - dep_status |= check_dep (d->file, depth, this_mtime, - &maybe_make); - if (! d->ignore_mtime) - *must_make_ptr = maybe_make; - check_renamed (d->file); - if (dep_status != 0 && !keep_going_flag) - break; - - if (d->file->command_state == cs_running - || d->file->command_state == cs_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); - - lastd = d; - d = d->next; - } - } - } - - finish_updating (file); - return dep_status; -} - -/* Touch FILE. Return zero if successful, one if not. */ - -#define TOUCH_ERROR(call) return (perror_with_name (call, file->name), 1) - -static int -touch_file (struct file *file) -{ - if (!silent_flag) - message (0, "touch %s", file->name); - -#ifndef NO_ARCHIVES - if (ar_name (file->name)) - return ar_touch (file->name); - 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; - 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 0; -} - -/* 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 (struct file *file) -{ - if (file->cmds == 0) - { - if (file->phony) - /* Phony target. Pretend it succeeded. */ - file->update_status = 0; - else if (file->is_target) - /* This is a nonexistent target file we cannot make. - Pretend it was successfully remade. */ - file->update_status = 0; - else - { - /* This is a dependency file we cannot remake. Fail. */ - if (!rebuilding_makefiles || !file->dontcare) - complain (file); - file->update_status = 2; - } - } - else - { - chop_commands (file->cmds); - - /* The normal case: start some commands. */ - if (!touch_flag || file->cmds->any_recurse) - { - execute_file_commands (file); - return; - } - - /* This tells notice_finished_file it is ok to touch the file. */ - file->update_status = 0; - } - - /* 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 arname_used = 0; - 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 (arname); - arname_used = 1; - } - 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; - - if (!arname_used) - { - free (arname); - arname_used = 1; - } - - arname = arfile->hname; - arlen = strlen (arname); - memlen = strlen (memname); - - /* free (file->name); */ - - name = (char *) xmalloc (arlen + 1 + memlen + 2); - bcopy (arname, name, arlen); - name[arlen] = '('; - bcopy (memname, name + arlen + 1, 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, name); - else - rehash_file (file, name); - check_renamed (file); - } - - if (!arname_used) - free (arname); - free (memname); - - file->low_resolution_time = 1; - - if (mtime == NONEXISTENT_MTIME) - /* The archive doesn't exist, so its members don't exist either. */ - return NONEXISTENT_MTIME; - - member_date = ar_member_date (file->hname); - mtime = (member_date == (time_t) -1 - ? NONEXISTENT_MTIME - : file_timestamp_cons (file->hname, member_date, 0)); - } - else -#endif - { - mtime = name_mtime (file->name); - - if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath) - { - /* If name_mtime failed, search VPATH. */ - char *name = file->name; - if (vpath_search (&name, &mtime) - /* Last resort, is it a library (-lxxx)? */ - || (name[0] == '-' && name[1] == 'l' - && library_search (&name, &mtime))) - { - 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 - 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)); - error (NILF, _("Warning: File `%s' has modification time %.2g s in the future"), - file->name, from_now); -#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->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 (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 int -library_search (char **lib, FILE_TIMESTAMP *mtime_ptr) -{ - static 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 - }; - - static char *libpatterns = NULL; - - char *libname = &(*lib)[2]; /* Name without the `-l'. */ - FILE_TIMESTAMP mtime; - - /* Loop variables for the libpatterns value. */ - char *p, *p2; - unsigned int len; - - char *file, **dp; - - /* If we don't have libpatterns, get it. */ - if (!libpatterns) - { - int save = warn_undefined_variables_flag; - warn_undefined_variables_flag = 0; - - libpatterns = xstrdup (variable_expand ("$(strip $(.LIBPATTERNS))")); - - warn_undefined_variables_flag = save; - } - - /* Loop through all the patterns in .LIBPATTERNS, and search on each 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; - char *libbuf = variable_expand (""); - - /* Expand the pattern using LIBNAME 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, then remove the - pattern so it's ignored next time. */ - error (NILF, _(".LIBPATTERNS element `%s' is not a pattern"), p); - for (; len; --len, ++p) - *p = ' '; - *p = c; - continue; - } - p4 = variable_buffer_output (libbuf, p, p3-p); - p4 = variable_buffer_output (p4, libname, strlen (libname)); - 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) - { - *lib = xstrdup (libbuf); - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return 1; - } - - /* Now try VPATH search on that. */ - - file = libbuf; - if (vpath_search (&file, mtime_ptr)) - { - *lib = file; - return 1; - } - - /* 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; - } - buflen = strlen (libbuf); - buf = xmalloc(libdir_maxlen + buflen + 2); - } - else if (buflen < strlen (libbuf)) - { - buflen = strlen (libbuf); - buf = xrealloc (buf, libdir_maxlen + buflen + 2); - } - - for (dp = dirs; *dp != 0; ++dp) - { - sprintf (buf, "%s/%s", *dp, libbuf); - mtime = name_mtime (buf); - if (mtime != NONEXISTENT_MTIME) - { - *lib = xstrdup (buf); - if (mtime_ptr != 0) - *mtime_ptr = mtime; - return 1; - } - } - } - - return 0; -} diff --git a/src/bin/make/remote-stub.c b/src/bin/make/remote-stub.c deleted file mode 100644 index 0417c2b03c..0000000000 --- a/src/bin/make/remote-stub.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Template for the remote job exportation interface to GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "filedef.h" -#include "job.h" -#include "commands.h" - - -char *remote_description = 0; - -/* 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; -} diff --git a/src/bin/make/rule.c b/src/bin/make/rule.c deleted file mode 100644 index e988db5bbf..0000000000 --- a/src/bin/make/rule.c +++ /dev/null @@ -1,586 +0,0 @@ -/* Pattern and suffix rule internals for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" -#include "dep.h" -#include "filedef.h" -#include "job.h" -#include "commands.h" -#include "variable.h" -#include "rule.h" - -static void freerule PARAMS ((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; - register struct rule *rule, *lastrule; - - num_pattern_rules = max_pattern_targets = max_pattern_deps = 0; - max_pattern_dep_length = 0; - - name = 0; - namelen = 0; - rule = pattern_rules; - lastrule = 0; - while (rule != 0) - { - unsigned int ndeps = 0; - register struct dep *dep; - struct rule *next = rule->next; - unsigned int ntargets; - - ++num_pattern_rules; - - ntargets = 0; - while (rule->targets[ntargets] != 0) - ++ntargets; - - if (ntargets > max_pattern_targets) - max_pattern_targets = ntargets; - - for (dep = rule->deps; dep != 0; dep = dep->next) - { - unsigned int len = strlen (dep->name); - -#ifdef VMS - char *p = strrchr (dep->name, ']'); - char *p2; - if (p == 0) - p = strrchr (dep->name, ':'); - p2 = p != 0 ? strchr (dep->name, '%') : 0; -#else - char *p = strrchr (dep->name, '/'); - char *p2 = p != 0 ? strchr (dep->name, '%') : 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 == dep->name) - ++p; - if (p - dep->name > namelen) - { - if (name != 0) - free (name); - namelen = p - dep->name; - name = (char *) xmalloc (namelen + 1); - } - bcopy (dep->name, name, p - dep->name); - name[p - dep->name] = '\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; - - lastrule = rule; - rule = next; - } - - if (name != 0) - 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 (char *target, char *source, struct commands *cmds) -{ - char *targname, *targpercent, *depname; - char **names, **percents; - struct dep *deps; - unsigned int len; - - 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 - targname = savestring ("(%.obj)", 7); -#else - targname = savestring ("(%.o)", 5); -#endif - targpercent = targname + 1; - } - else - { - /* Construct the target name. */ - len = strlen (target); - targname = xmalloc (1 + len + 1); - targname[0] = '%'; - bcopy (target, targname + 1, len + 1); - targpercent = targname; - } - - names = (char **) xmalloc (2 * sizeof (char *)); - percents = (char **) alloca (2 * sizeof (char *)); - names[0] = targname; - percents[0] = targpercent; - names[1] = percents[1] = 0; - - if (source == 0) - deps = 0; - else - { - /* Construct the dependency name. */ - len = strlen (source); - depname = xmalloc (1 + len + 1); - depname[0] = '%'; - bcopy (source, depname + 1, len + 1); - deps = alloc_dep (); - deps->name = depname; - } - - create_pattern_rule (names, percents, 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) -{ - register struct dep *d, *d2; - register struct file *f; - register char *rulename; - register unsigned int slen, s2len; - - /* Compute maximum length of all the suffixes. */ - - maxsuffix = 0; - for (d = suffix_file->deps; d != 0; d = d->next) - { - register unsigned int namelen = strlen (dep_name (d)); - if (namelen > maxsuffix) - maxsuffix = namelen; - } - - rulename = (char *) alloca ((maxsuffix * 2) + 1); - - for (d = suffix_file->deps; d != 0; d = d->next) - { - /* 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), (char *) 0, (struct commands *) 0); - - f = d->file; - if (f->cmds != 0) - /* Record a pattern for this suffix's null-suffix rule. */ - convert_suffix_rule ("", dep_name (d), f->cmds); - - /* Record a pattern for each of this suffix's two-suffix rules. */ - slen = strlen (dep_name (d)); - bcopy (dep_name (d), rulename, slen); - for (d2 = suffix_file->deps; d2 != 0; d2 = d2->next) - { - s2len = strlen (dep_name (d2)); - - if (slen == s2len && streq (dep_name (d), dep_name (d2))) - continue; - - bcopy (dep_name (d2), rulename + slen, 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 ((char *) 0, /* 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. */ - -int -new_pattern_rule (struct rule *rule, int override) -{ - register struct rule *r, *lastrule; - register 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; rule->targets[i] != 0; ++i) - { - for (j = 0; r->targets[j] != 0; ++j) - if (!streq (rule->targets[i], r->targets[j])) - break; - if (r->targets[j] == 0) - /* All the targets matched. */ - { - register 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) -{ - register struct rule *r; - char *ptr; - - r = (struct rule *) xmalloc (sizeof (struct rule)); - - r->targets = (char **) xmalloc (2 * sizeof (char *)); - r->suffixes = (char **) xmalloc (2 * sizeof (char *)); - r->lens = (unsigned int *) xmalloc (2 * sizeof (unsigned int)); - - r->targets[1] = 0; - r->suffixes[1] = 0; - r->lens[1] = 0; - - r->lens[0] = strlen (p->target); - /* These will all be string literals, but we malloc space for - them anyway because somebody might want to free them later on. */ - r->targets[0] = savestring (p->target, r->lens[0]); - r->suffixes[0] = find_percent (r->targets[0]); - if (r->suffixes[0] == 0) - /* Programmer-out-to-lunch error. */ - abort (); - else - ++r->suffixes[0]; - - ptr = p->dep; - r->deps = (struct dep *) multi_glob (parse_file_seq (&ptr, '\0', - sizeof (struct dep), 1), - sizeof (struct dep)); - - if (new_pattern_rule (r, 0)) - { - r->terminal = terminal; - r->cmds = (struct commands *) 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; - } -} - - -/* 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; - register unsigned int i; - register struct dep *dep; - - for (i = 0; rule->targets[i] != 0; ++i) - free (rule->targets[i]); - - dep = rule->deps; - while (dep) - { - struct dep *t; - - t = dep->next; - /* We might leak dep->name here, but I'm not sure how to fix this: I - think that pointer might be shared (e.g., in the file hash?) */ - dep->name = 0; /* Make sure free_dep does not free name. */ - free_dep (dep); - dep = t; - } - - free ((char *) rule->targets); - free ((char *) rule->suffixes); - free ((char *) 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 ((char *) 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. If TARGET_PERCENTS is not nil, it is an array of - pointers into the elements of TARGETS, where the `%'s are. - 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 is used and must not be freed - until the rule is destroyed. The storage for TARGET_PERCENTS is not used; - it may be freed. */ - -void -create_pattern_rule (char **targets, char **target_percents, - int terminal, struct dep *deps, - struct commands *commands, int override) -{ - unsigned int max_targets, i; - struct rule *r = (struct rule *) xmalloc (sizeof (struct rule)); - - r->cmds = commands; - r->deps = deps; - r->targets = targets; - - max_targets = 2; - r->lens = (unsigned int *) xmalloc (2 * sizeof (unsigned int)); - r->suffixes = (char **) xmalloc (2 * sizeof (char *)); - for (i = 0; targets[i] != 0; ++i) - { - if (i == max_targets - 1) - { - max_targets += 5; - r->lens = (unsigned int *) - xrealloc ((char *) r->lens, max_targets * sizeof (unsigned int)); - r->suffixes = (char **) - xrealloc ((char *) r->suffixes, max_targets * sizeof (char *)); - } - r->lens[i] = strlen (targets[i]); - r->suffixes[i] = (target_percents == 0 ? find_percent (targets[i]) - : target_percents[i]) + 1; - if (r->suffixes[i] == 0) - abort (); - } - - if (i < max_targets - 1) - { - r->lens = (unsigned int *) xrealloc ((char *) r->lens, - (i + 1) * sizeof (unsigned int)); - r->suffixes = (char **) xrealloc ((char *) r->suffixes, - (i + 1) * sizeof (char *)); - } - - if (new_pattern_rule (r, override)) - r->terminal = terminal; -} - -/* Print the data base of rules. */ - -static void /* Useful to call from gdb. */ -print_rule (struct rule *r) -{ - register unsigned int i; - register struct dep *d; - - for (i = 0; r->targets[i] != 0; ++i) - { - fputs (r->targets[i], stdout); - if (r->targets[i + 1] != 0) - putchar (' '); - else - putchar (':'); - } - if (r->terminal) - putchar (':'); - - for (d = r->deps; d != 0; d = d->next) - printf (" %s", dep_name (d)); - putchar ('\n'); - - if (r->cmds != 0) - print_commands (r->cmds); -} - -void -print_rule_data_base (void) -{ - register unsigned int rules, terminal; - register struct rule *r; - - puts (_("\n# Implicit Rules")); - - rules = terminal = 0; - for (r = pattern_rules; r != 0; r = r->next) - { - ++rules; - - putchar ('\n'); - print_rule (r); - - if (r->terminal) - ++terminal; - } - - 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) - fatal (NILF, _("BUG: num_pattern_rules wrong! %u != %u"), - num_pattern_rules, rules); - } -} diff --git a/src/bin/make/rule.h b/src/bin/make/rule.h deleted file mode 100644 index 99fb76e8ea..0000000000 --- a/src/bin/make/rule.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Definitions for using pattern rules in GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* Structure used for pattern rules. */ - -struct rule - { - struct rule *next; - char **targets; /* Targets of the rule. */ - unsigned int *lens; /* Lengths of each target. */ - char **suffixes; /* Suffixes (after `%') of each target. */ - struct dep *deps; /* Dependencies of the rule. */ - struct commands *cmds; /* Commands to execute. */ - char terminal; /* If terminal (double-colon). */ - char in_use; /* If in use by a parent pattern_search. */ - }; - -/* For calling install_pattern_rule. */ -struct pspec - { - 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; - - -extern void install_pattern_rule PARAMS ((struct pspec *p, int terminal)); -extern int new_pattern_rule PARAMS ((struct rule *rule, int override)); -extern void count_implicit_rule_limits PARAMS ((void)); -extern void convert_to_pattern PARAMS ((void)); -extern void create_pattern_rule PARAMS ((char **targets, - char **target_percents, int terminal, - struct dep *deps, - struct commands *commands, - int override)); diff --git a/src/bin/make/signame.c b/src/bin/make/signame.c deleted file mode 100644 index fe7a45f937..0000000000 --- a/src/bin/make/signame.c +++ /dev/null @@ -1,255 +0,0 @@ -/* Convert between signal names and numbers. -Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.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 everytime 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 signal) -{ - 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 (signal > 0 || signal < NSIG) - return (char *) sys_siglist[signal]; - - sprintf (buf, "Signal %d", signal); - return buf; -} - -#endif /* HAVE_STRSIGNAL */ diff --git a/src/bin/make/strcache.c b/src/bin/make/strcache.c deleted file mode 100644 index 6cfae42461..0000000000 --- a/src/bin/make/strcache.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Constant string caching for GNU Make. -Copyright (C) 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#include - -#include "hash.h" - -/* The size (in bytes) of each cache buffer. */ -#define CACHE_BUFFER_SIZE (4096) - - -/* 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. */ - -struct strcache { - struct strcache *next; /* The next block of strings. */ - char *end; /* Pointer to the beginning of the free space. */ - int count; /* # of strings in this buffer (for stats). */ - int bytesfree; /* The amount of the buffer that is free. */ - char buffer[1]; /* The buffer comes after this. */ -}; - -static int bufsize = CACHE_BUFFER_SIZE; -static struct strcache *strcache = NULL; - -static struct strcache * -new_cache() -{ - struct strcache *new; - new = (struct strcache *) xmalloc (sizeof (*new) + bufsize); - new->end = new->buffer; - new->count = 0; - new->bytesfree = bufsize; - - new->next = strcache; - strcache = new; - - return new; -} - -static const char * -add_string(const char *str, int len) -{ - struct strcache *best = NULL; - struct strcache *sp; - const char *res; - - /* If the string we want is too large to fit into a single buffer, then we're - screwed; nothing will ever fit! Change the maximum size of the cache to - be big enough. */ - if (len > bufsize) - bufsize = len * 2; - - /* First, find a cache with enough free space. We always look through all - the blocks and choose the one with the best fit (the one that leaves the - least amount of space free). */ - for (sp = strcache; sp != NULL; sp = sp->next) - if (sp->bytesfree > len && (!best || best->bytesfree > sp->bytesfree)) - best = sp; - - /* If nothing is big enough, make a new cache. */ - if (!best) - best = new_cache(); - - assert (best->bytesfree > len); - - /* Add the string to the best cache. */ - res = best->end; - memcpy (best->end, str, len); - best->end += len; - *(best->end++) = '\0'; - best->bytesfree -= len + 1; - ++best->count; - - 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 const char * -add_hash (const char *str, int len) -{ - /* Look up the string in the hash. If it's there, return it. */ - char **slot = (char **) hash_find_slot (&strings, str); - const char *key = *slot; - - 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->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, int len) -{ - char *key = alloca (len + 1); - memcpy (key, str, len); - key[len] = '\0'; - - return add_hash (key, len); -} - -int -strcache_setbufsize(int size) -{ - if (size > bufsize) - bufsize = size; - return bufsize; -} - -void -strcache_init (void) -{ - hash_init (&strings, 1000, str_hash_1, str_hash_2, str_hash_cmp); -} - - -/* Generate some stats output. */ - -void -strcache_print_stats (const char *prefix) -{ - int numbuffs = 0, numstrs = 0; - int totsize = 0, avgsize, maxsize = 0, minsize = bufsize; - int totfree = 0, avgfree, maxfree = 0, minfree = bufsize; - const struct strcache *sp; - - for (sp = strcache; sp != NULL; sp = sp->next) - { - int bf = sp->bytesfree; - int sz = (sp->end - sp->buffer) + bf; - - ++numbuffs; - numstrs += sp->count; - - totsize += sz; - maxsize = (sz > maxsize ? sz : maxsize); - minsize = (sz < minsize ? sz : minsize); - - totfree += bf; - maxfree = (bf > maxfree ? bf : maxfree); - minfree = (bf < minfree ? bf : minfree); - } - - avgsize = numbuffs ? (int)(totsize / numbuffs) : 0; - avgfree = numbuffs ? (int)(totfree / numbuffs) : 0; - - printf (_("\n%s # of strings in strcache: %d\n"), prefix, numstrs); - printf (_("%s # of strcache buffers: %d\n"), prefix, numbuffs); - printf (_("%s strcache size: total = %d / max = %d / min = %d / avg = %d\n"), - prefix, totsize, maxsize, minsize, avgsize); - printf (_("%s strcache free: total = %d / max = %d / min = %d / avg = %d\n"), - prefix, totfree, maxfree, minfree, avgfree); -} diff --git a/src/bin/make/variable.c b/src/bin/make/variable.c deleted file mode 100644 index f23f7d12fe..0000000000 --- a/src/bin/make/variable.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* Internals of variables for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.h" - -#include - -#include "dep.h" -#include "filedef.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 last struct in the chain, so we can add onto the end. */ - -static struct pattern_var *last_pattern_var; - -/* Create a new pattern-specific variable struct. */ - -struct pattern_var * -create_pattern_var (char *target, char *suffix) -{ - register struct pattern_var *p - = (struct pattern_var *) xmalloc (sizeof (struct pattern_var)); - - if (last_pattern_var != 0) - last_pattern_var->next = p; - else - pattern_vars = p; - last_pattern_var = p; - p->next = 0; - - p->target = target; - p->len = strlen (target); - p->suffix = suffix + 1; - - return p; -} - -/* Look up a target in the pattern-specific variable list. */ - -static struct pattern_var * -lookup_pattern_var (struct pattern_var *start, char *target) -{ - struct pattern_var *p; - unsigned int targlen = strlen(target); - - for (p = start ? start->next : pattern_vars; p != 0; p = p->next) - { - 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 }; -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, - char *value, enum variable_origin origin, - int recursive, struct variable_set *set, - const struct 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) - { - if (v->value != 0) - 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 = (struct variable *) xmalloc (sizeof (struct variable)); - v->name = savestring (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->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; -} - -/* 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 * -handle_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]; - } - - bcopy (v->name, p, 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; - - 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) - return v->special ? handle_special_var (v) : v; - } - -#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 = (struct variable_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; - return; - } - - if (file->parent == 0) - l->next = &global_setlist; - else - { - initialize_file_variables (file->parent, reading); - l->next = file->parent->variables; - } - - /* 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; - } - 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; - l->next = file->pat_variables; - } -} - -/* 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 = (struct variable_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; - - return setlist; -} - -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 ((char *) list->set); - free ((char *) list); -} - -/* 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; - } - - /* Free the one we no longer need. */ - free ((char *) setlist); - hash_map (&set->table, free_variable_name_and_value); - hash_free (&set->table, 1); - free ((char *) 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) -{ -#if defined(WINDOWS32) || defined(__EMX__) - extern char* default_shell; -#else - extern char default_shell[]; -#endif - register struct variable *v; - char buf[200]; - - sprintf (buf, "%u", makelevel); - (void) define_variable (MAKELEVEL_NAME, MAKELEVEL_LENGTH, 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); - (void) define_variable ("MAKE_VERSION", 12, buf, 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); - - /* Make $MAKESHELL override $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 ("SHELL", 5, default_shell, o_default, 0); - - /* 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 ("MAKEFILES", 9, "", 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 ("@D", 2, "$(dir $@)", o_automatic, 1); - define_variable ("%D", 2, "$(dir $%)", o_automatic, 1); - define_variable ("*D", 2, "$(dir $*)", o_automatic, 1); - define_variable ("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 (streq (v->name, "SHELL")) - { - extern struct variable shell_var; - 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 = MAKELEVEL_NAME; - makelevel_key.length = MAKELEVEL_LENGTH; - hash_delete (&table, &makelevel_key); - - result = result_0 = (char **) 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++ = concat (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++ = concat (v->name, "=", v->value); - } - } - - *result = (char *) xmalloc (100); - (void) sprintf (*result, "%s=%u", MAKELEVEL_NAME, makelevel + 1); - *++result = 0; - - hash_free (&table, 0); - - return result_0; -} - -/* 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 struct floc *flocp, const char *varname, - char *value, enum variable_origin origin, - enum variable_flavor flavor, int target_var) -{ - char *p, *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_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; - - 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; - char *val; - - 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 = alloc_value = allocated_variable_expand (val); - - oldlen = strlen (v->value); - vallen = strlen (val); - p = (char *) alloca (oldlen + 1 + vallen + 1); - bcopy (v->value, p, oldlen); - p[oldlen] = ' '; - bcopy (val, &p[oldlen + 1], vallen + 1); - } - } - } - -#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, (char **)0, shellpath)) - { - char *p; - - for (p = shellpath; *p; p++) - { - if (*p == '\\') - *p = '/'; - } - v = define_variable_loc (varname, strlen (varname), - shellpath, origin, flavor == f_recursive, - flocp); - } - else - { - 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 = (char *)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] = (char *)0; - if (__dosexec_find_on_path (shellbase, fake_env, shellpath)) - { - char *p; - - for (p = shellpath; *p; p++) - { - if (*p == '\\') - *p = '/'; - } - 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 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 - v = lookup_variable (varname, strlen (varname)); - } - 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; - - if (alloc_value) - free (alloc_value); - - 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 parse_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 * -parse_variable_definition (struct variable *v, char *line) -{ - register int c; - register char *p = line; - register char *beg; - register char *end; - enum variable_flavor flavor = f_bogus; - char *name; - - while (1) - { - c = *p++; - if (c == '\0' || c == '#') - return 0; - if (c == '=') - { - end = p - 1; - flavor = f_recursive; - break; - } - else if (c == ':') - if (*p == '=') - { - end = p++ - 1; - flavor = f_simple; - break; - } - else - /* A colon other than := is a rule line, not a variable defn. */ - return 0; - else if (c == '+' && *p == '=') - { - end = p++ - 1; - flavor = f_append; - break; - } - else if (c == '?' && *p == '=') - { - end = p++ - 1; - flavor = f_conditional; - break; - } - else if (c == '$') - { - /* This might begin a variable expansion reference. Make sure we - don't misrecognize chars inside the reference as =, := or +=. */ - char closeparen; - int count; - c = *p++; - if (c == '(') - closeparen = ')'; - else if (c == '{') - closeparen = '}'; - else - continue; /* Nope. */ - - /* 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; - } - } - } - } - v->flavor = flavor; - - beg = next_token (line); - while (end > beg && isblank ((unsigned char)end[-1])) - --end; - p = next_token (p); - v->value = p; - - /* Expand the name, so "$(foo)bar = baz" works. */ - name = (char *) alloca (end - beg + 1); - bcopy (beg, name, end - beg); - name[end - beg] = '\0'; - v->name = allocated_variable_expand (name); - - if (v->name[0] == '\0') - 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 parse_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 struct floc *flocp, 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 (!parse_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 = (struct variable *) item; - const char *prefix = (char *) arg; - const char *origin; - - switch (v->origin) - { - 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_automatic: - origin = _("automatic"); - break; - case o_invalid: - default: - abort (); - } - 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 - { - register 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 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, char *prefix) -{ - hash_map_arg (&set->table, print_variable, 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, ""); - - 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, "# "); - } - - if (rules == 0) - puts (_("\n# No pattern-specific variable values.")); - else - printf (_("\n# %u pattern-specific variable values"), rules); - } -} - - -/* Print all the local variables of FILE. */ - -void -print_file_variables (struct file *file) -{ - if (file->variables != 0) - print_variable_set (file->variables->set, "# "); -} - -#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, don't leak memory unnecessarily. - * Free the previous entry before allocating new one. - */ - if (environ_path) - free (environ_path); - - /* - * Create something WINDOWS32 world can grok - */ - convert_Path_to_windows32 (path, ';'); - environ_path = concat ("PATH", "=", path); - putenv (environ_path); - free (path); -} -#endif diff --git a/src/bin/make/variable.h b/src/bin/make/variable.h deleted file mode 100644 index 46b18fad94..0000000000 --- a/src/bin/make/variable.h +++ /dev/null @@ -1,200 +0,0 @@ -/* Definitions for using variables in GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#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_invalid /* Core dump time. */ - }; - -enum variable_flavor - { - f_bogus, /* Bogus (error) */ - f_simple, /* Simple definition (:=) */ - f_recursive, /* Recursive definition (=) */ - f_append, /* Appending definition (+=) */ - f_conditional /* Conditional definition (?=) */ - }; - -/* 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 (3); /* Variable flavor. */ - enum variable_origin - origin ENUM_BITFIELD (3); /* 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. */ - }; - -/* Structure used for pattern-specific variables. */ - -struct pattern_var - { - struct pattern_var *next; - char *target; - unsigned int len; - char *suffix; - struct variable variable; - }; - -extern char *variable_buffer; -extern struct variable_set_list *current_variable_set_list; - -/* expand.c */ -extern char *variable_buffer_output PARAMS ((char *ptr, char *string, unsigned int length)); -extern char *variable_expand PARAMS ((char *line)); -extern char *variable_expand_for_file PARAMS ((char *line, struct file *file)); -extern char *allocated_variable_expand_for_file PARAMS ((char *line, struct file *file)); -#define allocated_variable_expand(line) \ - allocated_variable_expand_for_file (line, (struct file *) 0) -extern char *expand_argument PARAMS ((const char *str, const char *end)); -extern char *variable_expand_string PARAMS ((char *line, char *string, - long length)); -extern void install_variable_buffer PARAMS ((char **bufp, unsigned int *lenp)); -extern void restore_variable_buffer PARAMS ((char *buf, unsigned int len)); - -/* function.c */ -extern int handle_function PARAMS ((char **op, char **stringp)); -extern int pattern_matches PARAMS ((char *pattern, char *percent, char *str)); -extern char *subst_expand PARAMS ((char *o, char *text, char *subst, char *replace, - unsigned int slen, unsigned int rlen, int by_word)); -extern char *patsubst_expand PARAMS ((char *o, char *text, char *pattern, char *replace, - char *pattern_percent, char *replace_percent)); - -/* expand.c */ -extern char *recursively_expand_for_file PARAMS ((struct variable *v, - struct file *file)); -#define recursively_expand(v) recursively_expand_for_file (v, NULL) - -/* variable.c */ -extern struct variable_set_list *create_new_variable_set PARAMS ((void)); -extern void free_variable_set PARAMS ((struct variable_set_list *)); -extern struct variable_set_list *push_new_variable_scope PARAMS ((void)); -extern void pop_variable_scope PARAMS ((void)); -extern void define_automatic_variables PARAMS ((void)); -extern void initialize_file_variables PARAMS ((struct file *file, int read)); -extern void print_file_variables PARAMS ((struct file *file)); -extern void print_variable_set PARAMS ((struct variable_set *set, char *prefix)); -extern void merge_variable_set_lists PARAMS ((struct variable_set_list **to_list, struct variable_set_list *from_list)); -extern struct variable *do_variable_definition PARAMS ((const struct floc *flocp, const char *name, char *value, enum variable_origin origin, enum variable_flavor flavor, int target_var)); -extern struct variable *parse_variable_definition PARAMS ((struct variable *v, char *line)); -extern struct variable *try_variable_definition PARAMS ((const struct floc *flocp, char *line, enum variable_origin origin, int target_var)); -extern void init_hash_global_variable_set PARAMS ((void)); -extern void hash_init_function_table PARAMS ((void)); -extern struct variable *lookup_variable PARAMS ((const char *name, unsigned int length)); -extern struct variable *lookup_variable_in_set PARAMS ((const char *name, - unsigned int length, - const struct variable_set *set)); - -extern struct variable *define_variable_in_set - PARAMS ((const char *name, unsigned int length, char *value, - enum variable_origin origin, int recursive, - struct variable_set *set, const struct 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 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) - -/* Warn that NAME is an undefined variable. */ - -#define warn_undefined(n,l) do{\ - if (warn_undefined_variables_flag) \ - error (reading_file, \ - _("warning: undefined variable `%.*s'"), \ - (int)(l), (n)); \ - }while(0) - -extern char **target_environment PARAMS ((struct file *file)); - -extern struct pattern_var *create_pattern_var PARAMS ((char *target, char *suffix)); - -extern int export_all_variables; - -#define MAKELEVEL_NAME "MAKELEVEL" -#define MAKELEVEL_LENGTH (sizeof (MAKELEVEL_NAME) - 1) diff --git a/src/bin/make/version.c b/src/bin/make/version.c deleted file mode 100644 index 7e718f8719..0000000000 --- a/src/bin/make/version.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Record version and build host architecture for GNU make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -/* 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). */ -#include - -#ifndef MAKE_HOST -# define MAKE_HOST "unknown" -#endif - -char *version_string = VERSION; -char *make_host = MAKE_HOST; - -/* - Local variables: - version-control: never - End: - */ diff --git a/src/bin/make/vpath.c b/src/bin/make/vpath.c deleted file mode 100644 index 0945240383..0000000000 --- a/src/bin/make/vpath.c +++ /dev/null @@ -1,605 +0,0 @@ -/* Implementation of pattern-matching file search paths for GNU Make. -Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, -1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include "make.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. */ - char *pattern; /* The pattern to match. */ - char *percent; /* Pointer into `pattern' where the `%' is. */ - unsigned int patlen;/* Length of the pattern. */ - 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; - -static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr)); - -/* 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; - - /* 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 ("%", 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; - - /* 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 ("%", 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 searchpath 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 SEARCHPATH 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 searchpath - separated by the path element separator (defined in make.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) -{ - register unsigned int elem; - register char *p; - register char **vpath; - register unsigned int maxvpath; - unsigned int maxelem; - char *percent = NULL; - - if (pattern != 0) - { - pattern = xstrdup (pattern); - percent = find_percent (pattern); - } - - if (dirpath == 0) - { - /* Remove matching listings. */ - register 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. */ - free (path->pattern); - free ((char *) path->searchpath); - free ((char *) path); - } - else - lastpath = path; - - path = next; - } - - if (pattern != 0) - free (pattern); - return; - } - -#ifdef WINDOWS32 - convert_vpath_to_windows32(dirpath, ';'); -#endif - - /* 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 = (char **) xmalloc (maxelem * sizeof (char *)); - maxvpath = 0; - - /* Skip over any initial separators and blanks. */ - p = dirpath; - while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) - ++p; - - elem = 0; - while (*p != '\0') - { - char *v; - unsigned int len; - - /* Find the end of this entry. */ - v = p; - while (*p != '\0' && *p != PATH_SEPARATOR_CHAR - && !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__) - /* 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; - - if (len > 1 || *v != '.') - { - v = savestring (v, len); - - /* Verify that the directory actually exists. */ - - if (dir_file_exists_p (v, "")) - { - /* It does. Put it in the list. */ - vpath[elem++] = dir_name (v); - free (v); - if (len > maxvpath) - maxvpath = len; - } - else - /* The directory does not exist. Omit from the list. */ - free (v); - } - - /* 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 = (char **) xrealloc ((char *) vpath, - (elem + 1) * sizeof (char *)); - - /* Put the nil-pointer terminator on the end of the VPATH list. */ - vpath[elem] = 0; - - /* Construct the vpath structure and put it into the linked list. */ - path = (struct vpath *) xmalloc (sizeof (struct vpath)); - path->searchpath = vpath; - path->maxlen = maxvpath; - path->next = vpaths; - vpaths = path; - - /* Set up the members. */ - path->pattern = pattern; - path->percent = percent; - path->patlen = strlen (pattern); - } - else - { - /* There were no entries, so free whatever space we allocated. */ - free ((char *) vpath); - if (pattern != 0) - free (pattern); - } -} - -/* 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 (char *file, unsigned int len) -{ - char **gp; - - if (gpaths && (len <= gpaths->maxlen)) - for (gp = gpaths->searchpath; *gp != NULL; ++gp) - if (strneq (*gp, file, len) && (*gp)[len] == '\0') - return 1; - - return 0; -} - -/* Search the VPATH list whose pattern matches *FILE for a directory - where the name pointed to by FILE exists. If it is found, we set *FILE to - the newly malloc'd name of the existing file, *MTIME_PTR (if MTIME_PTR is - not NULL) to its modtime (or zero if no stat call was done), and return 1. - Otherwise we return 0. */ - -int -vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr) -{ - register struct vpath *v; - - /* If there are no VPATH entries or FILENAME starts at the root, - there is nothing we can do. */ - - if (**file == '/' -#ifdef HAVE_DOS_PATHS - || **file == '\\' - || (*file)[1] == ':' -#endif - || (vpaths == 0 && general_vpath == 0)) - return 0; - - for (v = vpaths; v != 0; v = v->next) - if (pattern_matches (v->pattern, v->percent, *file)) - if (selective_vpath_search (v, file, mtime_ptr)) - return 1; - - if (general_vpath != 0 - && selective_vpath_search (general_vpath, file, mtime_ptr)) - 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 set *FILE to the newly malloc'd - name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to - its modtime (or zero if no stat call was done), and we return 1. - Otherwise we return 0. */ - -static int -selective_vpath_search (struct vpath *path, char **file, - FILE_TIMESTAMP *mtime_ptr) -{ - int not_target; - char *name, *n; - char *filename; - register char **vpath = path->searchpath; - unsigned int maxvpath = path->maxlen; - register unsigned int i; - unsigned int flen, vlen, 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. */ - { - 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; - - /* Allocate 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 = (char *) xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1); - - /* Try each VPATH entry. */ - for (i = 0; vpath[i] != 0; ++i) - { - int exists_in_cache = 0; - - n = name; - - /* Put the next VPATH entry into NAME at N and increment N past it. */ - vlen = strlen (vpath[i]); - bcopy (vpath[i], n, vlen); - n += vlen; - - /* Add the directory prefix already in *FILE. */ - if (name_dplen > 0) - { -#ifndef VMS - *n++ = '/'; -#endif - bcopy (*file, n, name_dplen); - n += name_dplen; - } - -#ifdef HAVE_DOS_PATHS - /* Cause the next if to treat backslash and slash alike. */ - if (n != name && n[-1] == '\\' ) - n[-1] = '/'; -#endif - /* Now add the name-within-directory at the end of NAME. */ -#ifndef VMS - if (n != name && n[-1] != '/') - { - *n = '/'; - bcopy (filename, n + 1, flen + 1); - } - else -#endif - bcopy (filename, n, 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. */ - *n = '\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. */ - *n = '/'; -#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. - Store the name we found into *FILE for the caller. */ - - *file = savestring (name, (n + 1 - name) + flen); - - /* 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; - - free (name); - return 1; - } - } - - free (name); - return 0; -} - -/* Print the data base of VPATH search paths. */ - -void -print_vpath_data_base (void) -{ - register unsigned int nvpaths; - register 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 - { - register char **path = general_vpath->searchpath; - register 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); - } -} diff --git a/src/bin/mkdepend/HISTORY b/src/bin/mkdepend/HISTORY deleted file mode 100644 index 8e194c49e8..0000000000 --- a/src/bin/mkdepend/HISTORY +++ /dev/null @@ -1,110 +0,0 @@ -** 14-Oct-2001, Lars Düning ** - - RELEASE 1.7 - - (main, args) New options '--no-warn-exit' to return a zero exitcode - ('success') when a warning was generated (for use in Makefiles). - - (main, args) New options '--ignore-missing' to ignore missing include - files (apart from printing a diagnostic). - - (Makefile, libglob/Makefile) Added x86->PPC cross-compilation. - -** 01-Mar-2000, Lars Düning ** - - RELEASE 1.6 - - (main, args, nodes) New option '--select' to narrow the dependency - generation to a few selected files. - - (Makefile, libglob/Makefile) Added crosscompilation PPC->x86. - -** 03-Feb-1999, Lars Düning ** - - (main, args) When out of memory, the error message also contains a slightly - cryptic hint where the program failed. - - (Makefile) The 'archive' target also creates a checksum file for the - archive, using the /bin/cksum command. - The .dependencies are included only when no 'clean' or 'clobber' is - requested (this solves the behavior Dianne noticed, that a 'make clean' - first recreates .dependencies only to delete it again). - -** 02-Feb-1999, Lars Düning ** - - (args.*) All information about an include directory is now combined - in one structure. - - (main.c, nodes.*) Rewrote the file identification and searching routines, - the old code failed to discriminate files which are included from - different directories. - - (util.*) New. - - - (getargs.c) A long option matched even when only the first characters - were given. A test for the proper length corrected this. - -** 25-Nov-1998, Lars Düning ** - - (getargs.c) A long option matched even when only the first characters - were given. A test for the proper length corrected this. - -** 01-Nov-1998, Lars Düning ** - - (getargs.c) If a value for an option was missing, the parser printed - the wrong option name in the error message. - -** 25-Oct-1998, Lars Düning ** - - RELEASE 1.4.5 - - (Makefile, libglob/Makefile) Adapted for R4 compilations. - - (Makefile) Improved the dependency generation: dependencies are - kept in the file .dependencies; and the rule is clever enough - to fall back to the compiler facilities if mkdepend is not - on the system. - - (getargs) Separated the commandline parser into here. - - (args) New options '--longhelp' to print a long help text, and - '--version' to print the program version. - '--include' distinguishes between normal and system include paths. - - (main) Default file suffixes now also cover a whole range of - C++ suffixes (.cc, .cpp, .cxx, .cc). - Filenames with embedded spaces are written in quotes. - - (nodes, reader, main) Added support for system includes. - -** 15-Oct-1998, Lars Düning ** - - (main.c) The name for the makefile backup was allocated one character - too short. - -** 04-Jul-1998, Lars Düning ** - - RELEASE 1.4 - RCS-Name is 'Rel-1_4', State is 'Rel'. - - Converted the program to BeOS. I decided to not keep the old Amiga - code - it's available on Aminet and I won't further develop it anyway. - New files: LICENSE. - Changed files: Just about everything else. - - Added libglob/ for filename globbing. - -** 02-Mar-1996, Lars Düning ** - - RELEASE 1.3 - - Oops, when confronted with target/source relations, MkDepend put the - source name into the dependency list as well. Though intentional, this - had the potential to confuse implicit make rules. Now this behaviour - is optional, triggered by specifying '+' with the object extension. - (main.c, args.ch) - - RCS tweaks to the Makefiles. - -** 25-Feb-1996, Lars Düning ** - - RELEASE 1.2 - - main.c (output_tree, output): Added output of includers of a file. - - main.c (readfiles): If a file can't be found, it's users known so far - are printed in the warning notice. - - nodes.c,h: Added .pUsers (List of includers of this file) to the Node - structure, extended routines nodes_depend() and nodes_deplist() - accordingly. - - Put under RCS (the Makefiles still need tweaking for this, though). - -** 04-Feb-1996, Lars Düning ** - - main.c (output, getargs, main): The program is now able to write the - list of dependencies into a separate file as well. - - main.c (output_tree): New to write the dependency tree into a file. - - args.ch, main.c: Exported argument parsing into args.c. - - reader.c (reader_openrw): Immediate writing if no file to read is - opened is now possible. - -** 13-Oct-1995, Lars Düning ** - - RELEASE 1.1 - - reader.c (reader_copymake2): Copies the remainder of the original - Makefile starting with the second tagline. - -** 12-Oct-1995, Lars Düning ** - - main.c (make_objname): %p pattern expanded to %[-][<][]p. - - Makefile, DMakefile: Making the 'archive' missed some files. - -** 18-Sep-1995, Lars Düning ** - - RELEASE 1.0 - diff --git a/src/bin/mkdepend/Jamfile b/src/bin/mkdepend/Jamfile deleted file mode 100644 index 8a52d1bbda..0000000000 --- a/src/bin/mkdepend/Jamfile +++ /dev/null @@ -1,14 +0,0 @@ -SubDir HAIKU_TOP src bin mkdepend ; - -SetSubDirSupportedPlatformsBeOSCompatible ; - -SubDirHdrs [ FDirName $(SUBDIR) .. make glob ] ; - -BinCommand mkdepend : - args.c - getargs.c - main.c - reader.c - nodes.c - util.c -: libglob.a : mkdepend.rdef ; diff --git a/src/bin/mkdepend/LICENSE b/src/bin/mkdepend/LICENSE deleted file mode 100644 index 0fd9d2d9e4..0000000000 --- a/src/bin/mkdepend/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -MkDepend License - -Copyright (c) 1995-2000, Lars Düning. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Modifications of the original software, in parts or as a whole, - must be clearly recognizable as such. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -$Id: LICENSE 1.2 Wed, 01 Mar 2000 21:15:40 -0700 lars $ diff --git a/src/bin/mkdepend/MkDepend.doc b/src/bin/mkdepend/MkDepend.doc deleted file mode 100644 index ea60672356..0000000000 --- a/src/bin/mkdepend/MkDepend.doc +++ /dev/null @@ -1,622 +0,0 @@ -$Id: MkDepend.doc 1.10 Wed, 01 Mar 2000 21:15:40 -0700 lars $ - - MkDepend 1.7 - - Copyright (c) 1995-2001 by Lars Düning - All Rights Reserved. - - - "Good information are hard to get. It is even more difficult to put - it into use." -- Sherlock Holmes - - -Introduction ------------- - Makefiles are very useful in the development of larger program systems, - as they notate the various dependencies and associated needed actions - in a machine-useable notation. Unfortunately it's the most important - dependency between C sources and their includes which have to be - maintained by hand, a most boring and errorprone task. - - MkDepend is one of those programs which attempt to automate this part - of development by scanning source files for includes and repeating this - step recursively until the complete transitive closure of included files - is determined. The found dependencies are then written into an existing - makefile, keeping it up to date, and/or into a separate file (the 'depfile') - for use by the makefile or for documentary purposes. - - The advantage of using MkDepend instead of the built-in dependency - facilities of modern compilers is that (a) MkDepend is faster, - (b) simplifies the maintenance of multiple and/or portable Makefiles, - and (c) you can modify it for your special needs. - - -Usage ------ - MkDepend is a shell-only program, compiled for R4.5 - - - mkdepend {-i|-I|--include [::]} - {-x|--except } - {-S|--select } - {-s|--suffix {,}[+][:] | [+]:} - {-p|--objpat {,}[+]:} - [-f|--file ] - [-d|--dep ] - [-l|--flat] - [-m|--ignore-missing] - [-w|--no-warn-exit] - [-v|--verbose] - [-h|-?|--help|--longhelp] - [-V|--version] - {} - - - All option keywords are case sensitive. The space between the short - form of the keywords and their operands may be omitted. For example - - mkdepend -I/include - mkdepend -i /include - mkdepend -I=/include - mkdepend --include=/include - mkdepend --include /include - - are all equivalent. Several short options may be combined, but only - one of them may take an argument, and it must be the last one. For - example: - - mkdepend -vl - mkdepend -vf Makefile - - are legal, but - - mkdepend -fv Makefile - - will be misunderstood as 'mkdepend -f=v Makefile'. - - The option '--' is special in that it marks the end of all option - recognition. All following arguments are considered filenames even - if they start with '-' or '--'. - - -General Operation ------------------ - - MkDepend is given a 'skeleton' of C source files and searches them for - included files. The includes found are recursively searched for includes - themselves, until the complete transitive closure has been determined. - MkDepend searches the includes first in the current directory, then in - the given paths (if any), imitating the C preprocessor's behaviour. - The files are scanned for include statements of the form - - #include "filename" - #include - - excluding those which are commented out using C-style /* */- or - C++-style //-comments. Every other content of the files is ignored. - - After all includes have been found, the dependencies are written into - a makefile (creating it if necessary). The makefile is searched for - a line - - # --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW --- - - after which MkDepend adds the dependencies, overwriting old ones, then - terminating the dependencies with the line - - # --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE --- - - Text following the second tagline in the makefile is not modified. - - If the first tagline is not found, the tagged dependencies are simply - appended to the file. Existing makefiles are modified by renaming it - to .bak and then re-creating the makefile by copying the - data not to be modified. - - The found dependencies for the 'skeleton' files are written as - - : ... - - Lines are limited to 80 chars, longer entries are folded into several - lines, ending each but the last line with a backslash (\). If a - name contains spaces, it is written within double quotes. - - MkDepend can be taught to know about source/object file relationships - to be used in the entries written. E,g, the entry generated for a typical - C source file would be of the form - - .o : ... - - Includes appear with that path in the list under which MkDepend found - them. To support multi-platform development, replacement texts may - be specified for the paths which are then used instead in the output. - - - For documentary purposes MkDepend may additionally (or instead) write - the dependencies into a separate file, either as flat lists or in - tree form. Here it writes the 'a includes b' relationships in the - form "a <- b" as well as the 'b is included by a' relationsships - in the form "b -> a". - - -Selected-File Operation ------------------------ - - MkDepend can be instructed just look for dependencies involving - some selected include files. This mode is activated by the use - of one or more '-S' arguments; and the output in this mode is - restricted to just the skeleton and the selected file. - - For example, where a normal MkDepend run would generate - - foobar.o : foobar.h yacc.tab.h main.h - - call MkDepend with the argument '-S yacc.tab.h' would reduce this output - to - - foobar.o : yacc.tab.h - - In the Makefile, these selected dependencies are put between - - # --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW --- - # --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE --- - - delimiter lines, so that both kinds of operations can be used on the - same Makefile. - - - In addition, the output of the other dependency files is modified in - a similar way. - - -Arguments ---------- - - - - Any command argument not recognizable as option is considered as - specification of one of the 'skeleton' sources. - Wildcards are recognized. - - Default: *.c - - Example: - - mkdepend *.c *.cc grammar.y - - All files ending in ".c" or ".cc" and the file "grammar.y" - are considered. - - The expansion of the wildcards is done by the shell. - - ------ - - -x - --except - - Files which are not part of the 'skeleton', even if they are specified - as such. The filepattern may contain the typical bash-wildcards, which - are expanded by MkDepend. - - Example: - - mkdepend *.c -x 'test*' - - All files ending in ".c", except those whose name start with "test", - are considered as sources. Note the quotes around "test*" to protect - it from shell name expansion. - - ------ - - -S - --select - - The output of dependency information is restricted to just those - 'skeleton' source which include at least one of the files. - Furthermore, only the named files are printed in the dependency lists. - - The filepattern may contain the typical bash-wildcards, which are - expanded by MkDepend _against the files existing at the time of - program start_. The pattern has to match the full filename - of the included file, including the directory part implicitely given - by any -I argument. - - Example: - - mkdepend *.c -S 'yacc.tab.h' - - Only the files which include "yacc.tab.h" will be listed in the - output. - - ------ - - -I [::]} - --include [::]} - - Specify a directory to be searched for include files. The paths are - searched in the order given on the command line. Unless '-I-' was - specified, the directory the including file is in is searched first. - - If is specified, it replaces the when writing - dependencies to a makefile. - - Usually, the path, made up from all given s, is searched - fully for both ""- and <>-includes. This behaviour changes if the - path is split using the special dirname '-' (like in '-I-'). - - If '-I-' is used, all directories given before the '-I-' are searched - only for ""-includes. The directories given after the '-I-' are - searched for both ""- and <>-includes again. Also the directories of - the including files are no longer searched automatically. - - If a ""-include is not found, MkDepend will print a warning, but - still list the file in the generated dependencies. Missing <>-includes - on the other hand are silently ignored. - - Example: - - mkdepend -I /include -I- -I libglob - - ""-include files are searched in the current directory, in /include - and in libglob. <>-include files are searched only in the - current directory and libglob. - - mkdepend -I '/include/pdlibs::$(PDLIBS)' - - Include files are searched in the current directory and - in /include/pdlibs. A file like "/include/pdlibs/tree.h" will be - written as "$(PDLIBS)tree.h" into the makefile. - Again note the use of quotes to keep the shell from expanding - the text '$(PDLIBS)'. - - Note that the syntax of this option is similar, but not identical to - what most compilers expect. One example of an exception is the GNU - C-Compiler which distinguishes between '-I' and '-i' in meaning. It is - therefore advisable to only use the uppercase '-I' for both compiler - and MkDepend. - - ------ - - -s {,}[+][:] | [+]:} - --suffix {,}[+][:] | [+]:} - - Specify a name relationship between source and object files. - If a source name ends in one of the given s, an Makefile entry - with the object name constructed using the associated . - The given with no associated serves as default - extension used for those which are given without own - . - When constructing the dependency list for a defined source/object - relation, the sourcefile itself is not included in the list, as - usually implicit makerules take care of them. This can be overridden - by specifying the '+' sign (which is associated with the given source - extensions). - - Default: -s :.o -s .c,.cc,.cpp,.cp,.cxx - - Example: - - mkdepend -s :.o -s '.c,.cc' - - Default is ".obj", which is used for files with the - extensions ".c" and ".cc". - - ------ - - -p {,}[+]: - --objpat {,}[+]: - - Similar to SUFFIX, but allows more complicated name relations. - gives the object file name verbatim, using placeholders - for the actual filenames: - - %s: the full sourcename (w/o suffix) - %p: the path part of the sourcename - %[-][<][]p: the path part of the sourcename - : skip the first directories of the path, - defaults to 0. - < : count the directories from the end or the path part. - - : use, don't skip the counted directories. - %n: the base of the sourcename (w/o suffix) - %%: the character '%'. - %x: the character x for every other character. - - Example: - - mkdepend -p .c:obj/%n.o - - For every sourcefile .c, an entry for obj/.o is - created. - - mkdepend -p .c:obj/%1p%n.o 'source/*.c' - - For every sourcefile source/.c, an entry for obj/.o is - created. - - ------ - - -f - --file - - Specify the makefile to modify. If none is specified and the --dep - option is missing as well, MkDepend searches in order for "Makefile", - "makefile", "Makefile.mk", "makefile.mk" and "GNUMakefile". If none - of these exist, 'Makefile' is used and thus created. - - ------ - - -d - --dep - - Specify the depfile to write the dependencies into. - The output hereinto notes just the plain dependencies between the - skeleton and the included files, i.e. ignores any --objpat or --objpat - setting. However, symbolic include paths are used here as well. - MkDepend prints both the 'a is included by b' as well as the - 'b includes a' relationships. The former are tagged with '<-' in - the output, the latter with '->'. - - If --flat is not specified, the dependencies are written in tree - form with indentation representating the nesting. - If --flat is specified, a flat list like that in Makefiles will - be written. - - ------ - - -l - --flat - - Print the plain dependency file (see option --dep) as flat list instead - of tree form. - - ------ - - -m|--ignore-missing - - If an include file is not found, it is NOT added to the dependencies. - However, MkDepend will still print diagnostic. - - ------ - - -w|--no-warn-exit - - If MkDepend generates a warning, it does not return a non-zero exit - code to the caller (useful for use within makefiles). - - ------ - - -v - --verbose - - Print some output during operation, namely the program name and the - file currently under examination. - ------ - - -h - --help - --longhelp - - Print a (short) summary of the commandline arguments and exit the - program. - - ------ - - -V - --version - - Print the program version and exit. - - -Installation ------------- - Copy the executable "mkdepend" into a suitable directory, profitably - into one in your search path. The PPC executable is in the subdirectory - obj.ppc/, the x86 executable in the subdirectory obj.x86/. - - -Using MkDepend --------------- - The straightforward use of MkDepend is of course the call from the - commandline a la 'mkdepend *.c', give or take a few command options. This - would scan all C source files, compute the dependencies and update the - Makefile in the same directory with these dependencies. Easy to use and - as easy to forget to do after an important change (trust me, it happens!). - Also, modifying the Makefile may not be what you want; after all, it adds - quite a bunch of junk to the file which is of no direct interest to you. - - Let's solve the second problem first: the solution is to instruct MkDepend - to write all dependencies into an auxiliary file '.dependencies', which is - done with the '-f' command option. The command now looks like this: - 'mkdepend -f .dependencies *.c'. To make use of this new file, the following - statement must be added to the Makefile on a separate line: - '-include .dependencies'. When make processes this line, it will read the - contents of .dependencies and treat them as if they were written in the - Makefile. The '-' in the command tells make to ignore the whole statement - should .dependencies not exist. - - The solution to the first problem (calling MkDepend automatically whenever - a file changes) is to put the MkDepend call into the Makefile, too. - Fortunately for us, Be's standard make allows a Makefile to change itself - or any included file: if such a change is detected, make will simply - re-read the affected files. Putting MkDepend into a Makefile requires the - following changes/additions to be done (modified according to your special - needs where necessary): - - - the main build rule for $(TARGET) must be changed to include .dependencies - as one of the requisites: - - $(TARGET) : .dependencies $(OBJS) ... - - - since MkDepend is not part of the BeOS distribution, the Makefile must - be able to use the normal compiler as a standin for MkDepend. The variable - DEP_FLAGS is set to the appropriate value to do so: - - ifeq ($(CC), gcc) - DEP_FLAGS = -M - endif - - ifeq ($(CC), mwcc$(CPU)) - DEP_FLAGS = -make - endif - - - the rule to generate the .dependencies file: - - .dependencies: $(SRCS) - $(SHELL) -ec '\ - if [ -n "`type -t mkdepend`" ]; then \ - mkdepend $(SRCS) $(INCLUDES) -p '\''.c:obj.$$(CPU)/%n.o'\'' -f$@; \ - else \ - $(CC) $(DEP_FLAGS) $(INCLUDES) $(SRCS) \ - | tr '\''\011'\'' '\''\040'\'' \ - | sed '\''s;^\([^ :][^ :]*\);$$(OBJ)/\1;g'\'' > $@; \ - fi' - - - gmake automatically makes '.dependencies' when it is missing; however, - if our intent is to 'clean' all auxiliary files, this behaviour is - rather annoying. The solution is to include the .dependencies into - the Makefile only when no cleaning action is requested: - - ifneq (,$(filter clean clobber cleanall clobberall, $MAKECMDGOALS)) - -include .dependencies - endif - - - a rule to point out missing header files (this allows a smoother make - process in case of outdated .dependencies): - - %.h : - @echo "Warning: Can't find $@." - - And that's all. - - The same changes apply if you chose to let mkdepend modify the Makefile - directly, just replace every occurence of '.dependencies' with 'Makefile' - (and of course do not '-include Makefile' in your Makefile). - - For a real-life example take a look at MkDepend's own Makefile. - - -Program Information -------------------- - MkDepend consists of these source files: - - main.c,.h : Program control, data generation routines. - args.c,.h : Argument parsing. - getargs.c,.h : Generic commandline parser. - reader.c,.h : Reading of source files and scanning for #include statements. - Copying and writing of makefiles. - nodes.c,.h : Management of the names and locations of the files analysed. - It is implemented as a binary search tree with an additional - linked list. - util.c,.h : Some helpful functions - ok, right now just one function. - version.h : The version number, automatically updated by PRCS. - - Filename expansion is provided by the static library libglob, which comes - under the GNU Library Public License in the subdirectory libglob/. - - The provided Makefile takes care of all the necessary steps to compile and - link both MkDepend and the libglob. See the head comment of the Makefile - for further information about available targets and cross-compilation. - - MkDepend was developed with Metrowerks C, Gnu C and GNU make; PRCS provides - the source code version management. - - -Bugs/TODO ---------- - Maybe allow the modification of several makefiles with one call. - Maybe omit from the depends list those files that could not be found. - The Makefile should be more generic. - - -History -------- - v 1.6 (01-Mar-2000) - Added the possibility to select certain files for dependency generation. - - v 1.5 (03-Feb-1999) - Added the search for include files in the directory of the including - file; older versions of MkDepend searched in the directory from where - MkDepend was started. - - v 1.4.5 (25-Oct-1998) - R4 support (PPC and x86). - The version number is now handled by PRCS. - New command options '--longhelp' and '--version'. - Default file suffixes now also cover a whole range of - C++ suffixes (.cc, .cpp, .cxx, .cc). - Systemincludes (<>-includes) are now handled; with the help of - the new command option -i-. - Filenames with embedded spaces are quoted when written to a Makefile. - - v 1.4 (04-Jul-1998) : - Moved to BeOS, Amiga support dropped. - New option -?|-h|--help for online help. - - v 1.3 (02-Mar-1996) : - For source/object relations, the source is no longer included in - dependency list, except when demanded by '+'-command option. - - v 1.2 (25-Feb-1996) : - New option -D=DEP/K for separate file with then plain source - dependencies. - New option -L=FLAT/S to write the plain dependencies as flat - list instead of a tree. - - v 1.1 (13-Oct-1995) : - The dependencies may now be placed in midst of a makefile. - Object file name pattern %p expanded to %[-][<][]p . - - v 1.0 (18-Sep-1995) : - Initial release, at that time for Amiga OS. - - -Authors -------- - Lars Düning, 10 Morningside Gardens, Edinburgh, EH10 5LA, United Kingdom - EMail: lars@bearnip.com, or duening@ibr.cs.tu-bs.de (deprecated) - - The file reader was inspired by the input module of lcc by David Hanson - and Christopher Fraser. - - The elaborate %p pattern follows a suggestion by Michael A. Wiedmer - (). - - The initial support for R4/x86 and a nice generic Makefile was provided - by Stephen van Egmond (). - - Dianne Kyra Hackborn () and - Stephen van Egmond provided valuable input. - - -Legalese --------- - The following license is replicated in the file LICENSE. It applies to - all files and derivates thereof which are part of the MkDepend package, - except for those files which explicitely state otherwise. - - - Copyright (c) 1995-1999, Lars Düning. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - - Modifications of the original software, of parts or of the whole, - must be clearly recognizable as such. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/src/bin/mkdepend/MkDepend.txt b/src/bin/mkdepend/MkDepend.txt deleted file mode 100644 index b77cd0741a..0000000000 --- a/src/bin/mkdepend/MkDepend.txt +++ /dev/null @@ -1,21 +0,0 @@ -======================================================================== - File: mkdepend-17.zip - Author: Lars Duening (lars@bearnip.com) - Release: 1.7 (14. Oct 2001) -Compatibility: R5 - Location: contrib/development - Description: Dependencygenerator for Makefiles - Notes: - -MkDepend scans C-source files recursively for includes and -writes the found dependency trees into an existing makefile. -Special features of MkDepend are: - - generates the complete transitive closure of all included files; - - searches the included files in several definable paths, and allows - to represent these pathnames by symbols in the generated Makefile; - - the source/object filename relationships may be flexibly defined; - - quite fast file scanner :-). - -The archive comes with full source and precompiled executables for -both x86 and (cross-compiled) PPC. -======================================================================== diff --git a/src/bin/mkdepend/args.c b/src/bin/mkdepend/args.c deleted file mode 100644 index 9536e8a7ff..0000000000 --- a/src/bin/mkdepend/args.c +++ /dev/null @@ -1,670 +0,0 @@ -/* $Id: args.c 1.9 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Arguments parsing and variables. -** -** Copyright (c) 1996-2001 by Lars Düning. All Rights Reserved. -** This file is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -** Parsed arguments: -** -** {-i|--include [::]} -** [-i-] -** {-x|--except } -** {-S|--select } -** {-s|--suffix {,}[+][:] | [+]:} -** {-p|--objpat {,}[+]: -** [-f|--file ] -** [-d|--dep ] -** [-l|--flat] -** [-m|--ignore-missing] -** [-w|--no-warn-exit] -** [-v|--verbose] -** [-h|-?|--help|--longhelp] -** [-V|--version] -** {} -** -**--------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include - -#include "args.h" -#include "getargs.h" -#include "main.h" -#include "glob.h" -#include "version.h" - -/*-------------------------------------------------------------------------*/ - -/* Program arguments */ - -short bVerbose = FALSE; /* TRUE: Verbose action */ -SArray aFiles = { 0, 0, NULL }; /* Source files */ -SArray aAvoid = { 0, 0, NULL }; /* Source files to avoid */ -SArray aSelect = { 0, 0, NULL }; /* Selected include files to print */ -Include * aIncl = NULL; /* Include directories */ -int iInclSize = 0; /* Number of valid entries in aIncl */ -static int allocIncl = 0; /* Allcoated size of pIncl */ -short bSplitPath = FALSE; /* TRUE: distinguish between normal - * and system include path. */ -SArray aSrcExt = { 0, 0, NULL }; /* Source file extensions */ -static int allocGiveSrc = 0, sizeGiveSrc = 0; - /* Allocated/used size of *bGiveSrc */ -short * bGiveSrc = NULL; /* For each entry in aSrcExt: - * TRUE if the source name shall appear - * in the dependency list, too. */ -SArray aObjExt = { 0, 0, NULL }; /* Associated object file extensions */ -SArray aObjPat = { 0, 0, NULL }; /* Associated object file patterns */ -char * sObjExt = NULL; /* Default object file extension */ -short bDefGSrc = FALSE; /* For sObjExt: TRUE if the source - * name shall appear in the depency - * list, too */ -char * sMake = NULL; /* Name of the Makefile */ -char * sDepfile = NULL; /* Name of the dependency file */ -short bFlat = FALSE; /* TRUE: Depfile in flat format */ -short bNoWarnExit = FALSE; /* TRUE: Don't return RETURN_WARN - * from program */ -short bIgnoreMiss = FALSE; /* TRUE: Ignore missing includes */ - -/*-------------------------------------------------------------------------*/ - -/* Every recognized option has a ordinal number */ - -typedef enum OptNumber { - cUnknown = OPTION_UNKNOWN /* unknown option */ - , cArgument = OPTION_ARGUMENT /* normal argument (for us: filename) */ - , cInclude /* --include */ - , cExcept /* --except */ - , cSelect /* --select */ - , cSuffix /* --suffix */ - , cObjPat /* --objpat */ - , cFile /* --file */ - , cDep /* --dep */ - , cFlat /* --flat */ - , cNoWarn // --no-warn-exit - , cIgnMiss // --ignore-missing - , cHelp /* --help */ - , cLongHelp /* --longhelp */ - , cVerbose /* --verbose */ - , cVersion /* --version */ -} OptNumber; - -/* Comprehensive lists of recognized options */ - -static OptionDesc aOptions[] - = { { 'i', "include", cInclude, TRUE } - , { 'I', NULL, cInclude, TRUE } - , { 'x', "except", cExcept, TRUE } - , { 'S', "select", cSelect, TRUE } - , { 's', "suffix", cSuffix, TRUE } - , { 'p', "objpat", cObjPat, TRUE } - , { 'f', "file", cFile, TRUE } - , { 'd', "dep", cDep, TRUE } - , { 'l', "flat", cFlat, FALSE } - , { 'm', "ignore-missing", cIgnMiss, FALSE } - , { 'w', "no-warn-exit", cNoWarn, FALSE } - , { 'h', "help", cHelp, FALSE } - , { '?', NULL, cHelp, FALSE } - , { '\0', "longhelp", cLongHelp, FALSE } - , { 'v', "verbose", cVerbose, FALSE } - , { 'V', "version", cVersion, FALSE } - }; - -/*-------------------------------------------------------------------------*/ -static void -version (void) - -/* Print the version of the program. */ - -{ - fputs("MkDepend " VERSION " - Makefile Dependency Generator\n" - "\nReleased: " RELEASE_DATE - "\nCompiled: " __DATE__ -#ifdef __TIME__ - " " __TIME__ -#endif - "\n", stdout); -} - -/*-------------------------------------------------------------------------*/ -static void -shortusage (void) - -/* Print the short help information to stdout. */ - -{ - version(); - printf("\nUsage: %s [options] ...\n", aPgmName); - fputs( -"\nOptions are:\n" -"\n" -" -i|--include [::]\n" -" -x|--except \n" -" -S|--select \n" -" -s|--suffix {,}[+][:]\n" -" -s|--suffix [+]:\n" -" -p|--objpat {,}[+]:\n" -" -f|--file \n" -" -d|--dep \n" -" -l|--flat\n" -" -m|--ignore-missing\n" -" -w|--no-warn-exit\n" -" -v|--verbose\n" -" -h|-?|--help|--longhelp\n" -" -V|--version\n" - , stdout); - -} /* shortusage() */ - -/*-------------------------------------------------------------------------*/ -static void -usage (void) - -/* Print the help information to stdout. */ - -{ - version(); - printf("\nUsage: %s [options] ...\n", aPgmName); - fputs( -"\nOptions are:\n" -"\n" -" -i|--include [::]\n" -" Add to the list of searched directories. If given,\n" -" is used in the generated dependencies to denote\n" -" the .\n" -" The special notation '-i-' is used to split the search path into\n" -" a non-system and a common part.\n" -"\n" -" -x|--except \n" -" Except all matching files from the root set.\n" -"\n" -" -S|--select \n" -" Only the dependencies for files including are printed,\n" -" and in those only the included files matching are listed.\n" -" Except all matching files from the root set.\n" -"\n" -" -s|--suffix {,}[+][:]\n" -" Set the recognized source file suffixes (and optionally associated\n" -" object file suffixes).\n" -"\n" -" -s|--suffix [+]:\n" -" Set the default object file suffix.\n" -"\n" -" -p|--objpat {,}[+]:\n" -" Define a complex source/object file name relation.\n" -" The recognizes as meta-symbols:\n" -" %s: the full sourcename (w/o suffix)\n" -" %[-][<][]p: the path part of the sourcename\n" -" : skip first directories of the path,\n" -" defaults to 0.\n" -" < : directories are counted from the end.\n" -" - : use, don't skip the counted directories.\n" -" %n: the base of the sourcename (w/o suffix)\n" -" %%: the character %\n" -" %x: the character 'x' for every other character.\n" -"\n" -" -f|--file \n" -" Update with the found dependencies (default is 'Makefile').\n" -"\n" -" -d|--dep \n" -" Write the found dependencies into .\n" -"\n" -" -l|--flat\n" -" When generating a write the dependencies in flat form.\n" -"\n" -" -m|--ignore-missing\n" -" If an include file is not found, it is NOT added to the dependencies.\n" -"\n" -" -w|--no-warn-exit\n" -" If MkDepend generates a warning, it does not return a non-zero exit\n" -" code to the caller (useful for use within makefiles).\n" -"\n" -" -v|--verbose\n" -" Verbose operation.\n" -"\n" -" -V|--version\n" -" Display the version of the program and exit.\n" -"\n" -" --longhelp\n" -" Display this help and exit.\n" -"\n" -" -h|-?|--help\n" -" Display the short help text and exit.\n" -"\n" - , stdout); - -} - -/*-------------------------------------------------------------------------*/ -static int -givesrc_addflag (short bFlag) - -/* Add to *bGiveSrc. - * Return 0 on success, non-0 on error. - */ - -{ - short * pFlags; - assert(sizeGiveSrc <= allocGiveSrc); - if (sizeGiveSrc+1 > allocGiveSrc) - { - pFlags = (short*)realloc(bGiveSrc, sizeof(short)*(allocGiveSrc+4)); - if (!pFlags) - return 1; - bGiveSrc = pFlags; - allocGiveSrc += 4; - } - bGiveSrc[sizeGiveSrc] = bFlag; - sizeGiveSrc++; - return 0; -} - -/*-------------------------------------------------------------------------*/ -static int -include_addinfo (char * pPath, char * pSymbol, int bSystem) - -/* Add the given data to to *bIncl. - * Return 0 on success, non-0 on error. - */ - -{ - Include * pNew; - - assert(iInclSize <= allocIncl); - if (iInclSize+1 > allocIncl) - { - pNew = realloc(aIncl, sizeof(Include)*(allocIncl+4)); - if (!pNew) - return 1; - aIncl = pNew; - allocIncl += 4; - } - aIncl[iInclSize].pPath = pPath; - aIncl[iInclSize].pSymbol = pSymbol; - aIncl[iInclSize].bSysPath = bSystem; - iInclSize++; - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -array_addfile (SArray *pArray, const char * pName) - -/* Add a copy of <*pName> to the string array . - * Return 0 on success, non-0 on error. - * If pName is NULL, the array is simply extended by a NULL pointer. - */ - -{ - char ** pStrs; - assert(pArray->size <= pArray->alloc); - if (pArray->size+1 > pArray->alloc) - { - pStrs = (char **)realloc(pArray->strs, sizeof(char *)*(pArray->alloc+4)); - if (!pStrs) - return 1; - pArray->strs = pStrs; - pArray->alloc += 4; - } - else - pStrs = pArray->strs; - if (pName) - { - pStrs[pArray->size] = strdup(pName); - if (!pStrs[pArray->size]) - return 1; - } - else - pStrs[pArray->size] = NULL; - pArray->size++; - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -array_addlist (SArray *pArray, int count, const char ** pList) - -/* Add the strings from to string array . - * pList and contained strings may be freed after return. - * Return 0 on success, non-0 else. - */ - -{ - char ** pStrs; - int i; - - assert(pList); - if (!count) - return 0; - assert(pArray->size <= pArray->alloc); - if (pArray->size+count > pArray->alloc) - { - pStrs = (char **)realloc(pArray->strs, sizeof(char *)*(pArray->alloc+count)); - if (!pStrs) - return 1; - pArray->strs = pStrs; - pArray->alloc += count; - } - else - pStrs = pArray->strs; - for (i = 0; i < count; i++) - { - char * pString; - - pString = strdup(pList[i]); - if (!pString) - return 1; - pStrs[pArray->size++] = pString; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -add_expfile (SArray *pArray, const char * pName) - -/* Glob filename <*pName> and add the filenames to string array . - * Return 0 on success, non-0 else. - */ - -{ - glob_t aGlob; - int rc; - - memset(&aGlob, 0, sizeof(aGlob)); - - switch (glob(pName, GLOB_NOSORT|GLOB_BRACE|GLOB_TILDE, NULL, &aGlob)) - { - case GLOB_NOSPACE: - globfree(&aGlob); - exit_nomem(" (add_expfile: glob)"); - break; - - case GLOB_ABORTED: - printf("%s: Error expanding %s\n", aPgmName, pName); - globfree(&aGlob); - set_rc(RETURN_ERROR, TRUE); - break; - - case GLOB_NOMATCH: - globfree(&aGlob); - return 0; - - case 0: - /* No error */ - break; - - default: - globfree(&aGlob); - exit_doserr(RETURN_ERROR); - break; - } - - assert(aGlob.gl_pathc > 0); - - rc = 0; - if (aGlob.gl_pathc > 0) - rc = array_addlist(pArray, aGlob.gl_pathc, (const char **)aGlob.gl_pathv); - - globfree(&aGlob); - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -handler (int eOption, const char * pValue) - -/* Callback function for getargs(). It is called when option - * was recognized, possibly also passing an associated value in . - * Return 0 on success, non-zero else. - */ - -{ - int i; /* All purpose */ - - switch (eOption) - { - case cArgument: - i = array_addfile(&aFiles, pValue); - if (i) - exit_nomem(" (args: add file)"); - break; - - case cInclude: - { - char * pSym, * pMark; - char * pVal; - - /* Special case: check for the '-' marker */ - if (!strcmp(pValue, "-")) - { - bSplitPath = TRUE; - break; - } - - /* Since we're going to hack into pValue, possibly extending it - * by one character, we better make a copy of it. We need it - * anyway to store the data in aIncl[]. - */ - pVal = malloc(strlen(pValue)+2); - if (!pVal) - exit_nomem(" (args: dup include arg)"); - strcpy(pVal, pValue); - - /* Allow for :: notation */ - pSym = NULL; - pMark = pVal+strlen(pVal); - if (pMark != pVal) - { - pMark--; - while (!pSym && pMark >= pVal+1) - { - if (':' != *pMark) - { - pMark--; - continue; - } - if (':' != *(pMark-1)) - { - pMark -= 2; - continue; - } - pSym = pMark+1; - *(pMark-1) = '\0'; - } - } - if (pSym && !strlen(pSym)) - pSym = NULL; - else if (pSym) - { - pSym = strdup(pSym); - if (!pSym) - exit_nomem(" (args: dup include sym)"); - } - - /* Make sure ends in a ':' or '/' */ - pMark = pVal+strlen(pVal); - if (pMark > pVal && ':' != *(pMark-1) && '/' != *(pMark-1)) - { - *pMark = '/'; - *(pMark+1) = '\0'; - } - i = include_addinfo(pVal, pSym, bSplitPath); - if (i) - exit_nomem(" (args: add include info)"); - } - break; - - case cExcept: - i = add_expfile(&aAvoid, pValue); - if (i) - exit_nomem(" (args: add except)"); - break; - - case cSelect: - i = add_expfile(&aSelect, pValue); - if (i) - exit_nomem(" (args: add select)"); - break; - - case cSuffix: - case cObjPat: - { - char * pMark, *pOsfix; - short bGotPlus; - - /* Allow for [+]: notation */ - bGotPlus = FALSE; - pOsfix = NULL; - pMark = (char *)pValue+strlen(pValue); - if (pMark != pValue) - { - pMark--; - while (!pOsfix && pMark >= pValue) - { - if (':' != *pMark) - { - pMark--; - continue; - } - pOsfix = pMark+1; - if (pMark != pValue && *(pMark-1) == '+') - { - bGotPlus = TRUE; - pMark--; - } - *pMark = '\0'; - } - } - if (pOsfix && !strlen(pOsfix)) - pOsfix = NULL; - - /* --objpat needs the [+]: part! */ - if (cObjPat == eOption && !pOsfix) - { - printf("%s: not specified.\n", aPgmName); - set_rc(RETURN_ERROR, TRUE); - } - - /* [+]: alone defines default object suffix */ - if (pOsfix && !strlen(pValue)) - { - if (sObjExt) - free(sObjExt); - sObjExt = strdup(pOsfix); - if (!sObjExt) - exit_nomem(" (args: dup obj suffix)"); - bDefGSrc = bGotPlus; - } - else - { - char * pSfix; - - /* Allow for ,,..., for source suffixes */ - for ( pSfix = (char *)pValue - ; NULL != (pMark = strchr(pSfix, ',')) - ; pSfix = pMark+1 - ) - { - *pMark = '\0'; - if (strlen(pSfix)) - { - if ( array_addfile(&aSrcExt, pSfix) - || givesrc_addflag(bGotPlus) - || (cSuffix == eOption ? array_addfile(&aObjExt, pOsfix) - : array_addfile(&aObjPat, pOsfix) - ) - ) - exit_nomem(" (args: add obj suffix)"); - } - } - if (strlen(pSfix)) - { - if ( array_addfile(&aSrcExt, pSfix) - || givesrc_addflag(bGotPlus) - || (cSuffix == eOption ? array_addfile(&aObjExt, pOsfix) - : array_addfile(&aObjPat, pOsfix) - ) - ) - exit_nomem(" (args: add last obj suffix)"); - } - } - } - break; - - case cFile: - if (sMake) - free(sMake); - sMake = strdup(pValue); - if (!sMake) - exit_nomem(" (args: dup make)"); - break; - - case cDep: - if (sDepfile) - free(sDepfile); - sDepfile = strdup(pValue); - if (!sDepfile) - exit_nomem(" (args: dup dep)"); - break; - - case cFlat: - bFlat = TRUE; - break; - - case cIgnMiss: - bIgnoreMiss = TRUE; - break; - - case cNoWarn: - bNoWarnExit = TRUE; - break; - - case cVerbose: - bVerbose = TRUE; - break; - - case cHelp: - shortusage(); - set_rc(RETURN_WARN, TRUE); - break; - - case cLongHelp: - usage(); - set_rc(RETURN_WARN, TRUE); - break; - - case cVersion: - version(); - set_rc(RETURN_WARN, TRUE); - break; - - default: - /* This shouldn't happen. */ - printf("%s: (getargs) Internal error, eOption is %d\n", aPgmName, eOption); - assert(0); - break; - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ -void -parseargs (int argc, char ** argv) - -/* Get the arguments from the commandline and fill in the exported variables. - * In case of an error, the program is terminated. - */ - -{ - if (getargs(argc, argv, aOptions, handler)) - set_rc(RETURN_ERROR, TRUE); -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/args.h b/src/bin/mkdepend/args.h deleted file mode 100644 index db2b9a832b..0000000000 --- a/src/bin/mkdepend/args.h +++ /dev/null @@ -1,61 +0,0 @@ -/* $Id: args.h 1.6 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Copyright (c) 1999-2001 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - */ - -#ifndef __ARGS_H__ -#define __ARGS_H__ 1 - -/* Dynamic string array */ - -typedef struct _sarray -{ - int size; /* Number of used strings */ - int alloc; /* Number of allocated string pointers */ - char ** strs; /* Array of string pointers */ -} SArray; - -/* Information about one include directory */ - -typedef struct _inclinfo { - char * pPath; /* Pathname of the directory */ - char * pSymbol; /* Symbol to use in Makefiles, NULL if none */ - int bSysPath; /* TRUE for system directories */ -} Include; - -/* Program arguments */ - -extern short bVerbose; /* TRUE: Verbose action */ -extern SArray aFiles; /* Source files */ -extern SArray aAvoid; /* Source files to avoid */ -extern SArray aSelect; /* Selected include files to print */ -extern Include * aIncl; /* Include directory information */ -extern int iInclSize; /* Number of valid entries in aIncl */ -extern short bSplitPath; /* Include path handling */ -extern SArray aSrcExt; /* Source file extensions */ -extern SArray aObjExt; /* Associated object file extensions */ -extern SArray aObjPat; /* Associated object file patterns */ -extern short * bGiveSrc; /* For each entry in aSrcExt: TRUE if the - * source name shall appear in the - * dependency list, too. */ -extern char * sObjExt; /* Default object file extension */ -extern short bDefGSrc; /* For sObjExt: TRUE if the source name - * shall appear in the depency list, too - */ -extern char * sMake; /* Name of the Makefile */ -extern char * sDepfile; /* Name of the dependency file */ -extern short bFlat; /* TRUE: Depfile in flat format */ -extern short bNoWarnExit; /* TRUE: Don't return RETURN_WARN from program */ -extern short bIgnoreMiss; /* TRUE: Ignore missing includes */ - -/* Prototypes */ - -extern void parseargs (int argc, char ** argv); -extern int array_addlist (SArray *, int, const char **); -extern int array_addfile (SArray *, const char *); -extern int add_expfile (SArray *, const char *); - -#endif diff --git a/src/bin/mkdepend/getargs.c b/src/bin/mkdepend/getargs.c deleted file mode 100644 index 891c36c27c..0000000000 --- a/src/bin/mkdepend/getargs.c +++ /dev/null @@ -1,326 +0,0 @@ -/* $Id: getargs.c 1.5 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Commandline argument parser. - * - * Copyright (c) 1998-2000 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - * This code parses the arguments passed to the program in the count - * and the array of strings . The parser distinguishes options, which - * start with a '-', from normal arguments; options are further distinguished - * by their name and may take an additional value. The parser neither - * imposes nor expects any order of options and arguments. - * - * Options are recognized in two forms. In the short form the option must - * be given as a single '-' followed by a single letter. In the long form, - * options start with '--' followed by a string of arbitrary length. - * Short options are case sensitive, long options aren't. - * Examples are: '-r' and '--recursive'. - * - * If an option takes a value, it must follow the option immediately after - * a separating space or '='. Additionally, the value for a short option - * may follow the option without separator. Examples are: '-fMakefile', - * '-f Makefile', '--file=Makefile' and '--file Makefile'. - * - * Short options may be collated into one argument, e.g. '-rtl', but - * of these only the last may take a value. - * - * The option '--' marks the end of options. All following command arguments - * are considered proper arguments even if they start with a '-' or '--'. - *------------------------------------------------------------------------- - * Internally every option recognized by the program is associated with - * an id number, assigned by the user. The parser itself uses the two - * id numbers 'OPTION_UNKNOWN' for unrecognized options, and - * 'OPTION_ARGUMENT' for proper command arguments. - * - * Id numbers are associated with their option strings/letters by the - * the array aOptions, which is passed to the parser function. Every element - * in this array is a structure defining the option's name (string - * or letter), the associated id number, and whether or not the option - * takes a value. An element can hold just one type of option (short or - * long) by setting the description the other option to \0 resp. NULL. - * The order of the elements does not matter. The end of the array is - * marked with an element using OPTION_UNKNOWN as assigned id number. - * - * The parsing is done by calling the function - * - * int getargs( int argc, char ** argv - * , const OptionDesc aOptions[] - * , OptionHandler handler) - * - * The function is passed the argument count and vector as - * they were received from the main() function, the option description - * array and a callback function* . getargs() - * returns 0 if the parsing completed successfully, and non-zero else. - * - * The handler function is called for every successfully recognized option - * and argument. Its prototype is - * - * int handler(int iOption, const char *pValue) - * - * Parameter denotes the recognized option, and pValue points - * to the beginning of the value string if the option takes a value. - * Proper arguments are parsed with eOption==OPTION_ARGUMENT and pValue - * pointing to the argument string. The handler has to return 0 if the - * option/argument was processed correctly, and non-zero else. - * - * Additionally, getargs() puts the basename of the program (as determined - * by argv[0]) into the exported variable - * - * const char *aPgmName - * - * when called the first time. - *------------------------------------------------------------------------- - */ - -#include -#include -#include -#include - -#include "getargs.h" - -const char *aPgmName = NULL; - /* The exported program name. */ - -#define MY_TRUE 1 -#define MY_FALSE 0 - -/*-------------------------------------------------------------------------*/ -int -getargs ( int argc, char ** argv - , OptionDesc aOptions[] - , OptionHandler opt_eval - ) - -/* Get the arguments from the commandline and pass them - * as (number, optional value) to the callback. - * The options are defined by the array , with an OPTION_UNKNOWN - * element marking the last entry. - * - * If opt_eval() returns non-zero, argument scanning is terminated. - * In that case, or if getargs() detects an error itself, getargs() returns - * non-zero. - * A zero return means 'success' in both cases. - * - * Additionally, on the first call getargs() sets aPgmName to the basename - * of the program as derived from argv[0]. - */ - -{ - int i; /* all purpose */ - int nOptions; /* Number of options */ - int iArg; /* Number of argument under inspection */ - int eOption; /* The current recognized option */ - int xOption; /* The index of the recog otion in aOptions */ - short bCont; /* True: find another option in the same argument */ - short bDone; /* True: all options parsed, only args left */ - short bShort; /* True: current argument is a short option */ - char * pArg; /* Next argument character to consider */ - - assert(aOptions != NULL); - assert(opt_eval != NULL); - - /* Determine the program's name */ - if (NULL == aPgmName) - { - char * newName; - - newName = strdup(basename(argv[0])); - if (NULL == newName) - aPgmName = (const char *)argv[0]; - else - aPgmName = (const char *)newName; - } - - /* Make the compiler happy */ - bShort = MY_FALSE; - pArg = NULL; - - /* Count the options */ - for (nOptions = 0; aOptions[nOptions].iNumber != OPTION_UNKNOWN; nOptions++) - /* SKIP */ ; - - /* Scan all arguments */ - bCont = MY_FALSE; - bDone = MY_FALSE; - for (iArg = 1; iArg < argc; !bCont ? iArg++ : iArg) - { - ssize_t iArglen; /* Length of remaining argument */ - char * pValue; /* First character of an option value, or NULL */ - int bTakesValue; /* This option takes a value */ - - /* Make the compiler happy */ - iArglen = 0; - pValue = NULL; - bTakesValue = MY_FALSE; - - if (bDone) - eOption = OPTION_ARGUMENT; - else - /* If this is not a continuation, reinitialise the inspection vars. - * For --opt=val arguments, pValue is set to the first character of val. - */ - if (!bCont) - { - pArg = argv[iArg]; - if ('-' == pArg[0] && '-' == pArg[1]) /* Long option? */ - { - eOption = OPTION_UNKNOWN; - bShort = MY_FALSE; - pArg += 2; - /* Special case: if the argument is just '--', it marks the - * end of all options. - * We set a flag and continue with the next argument. - */ - if ('\0' == *pArg) - { - bDone = MY_TRUE; - continue; - } - pValue = strchr(pArg, '='); - if (pValue != NULL) - { - iArglen = pValue - pArg; - pValue++; - } - else - iArglen = (signed)strlen(pArg); - } - else if ('-' == pArg[0]) /* Short option? */ - { - eOption = OPTION_UNKNOWN; - bShort = MY_TRUE; - pArg++; - iArglen = (signed)strlen(pArg); - pValue = NULL; - } - else /* No option */ - { - eOption = OPTION_ARGUMENT; - pValue = pArg; - iArglen = 0; - } - } - else - eOption = OPTION_UNKNOWN; - - /* If the option is not determined yet, do it. - * Set pValue to the first character of the value if any. - */ - if (OPTION_UNKNOWN == eOption) - { - xOption = 0; - if (bShort) /* search the short option */ - { - for (i = 0; i < nOptions; i++) - if ('\0' != aOptions[i].cOption && *pArg == aOptions[i].cOption) - { - xOption = i; - eOption = aOptions[i].iNumber; - bTakesValue = aOptions[i].bValue; - pArg++; iArglen--; /* Consume this character */ - break; - } - - /* Consume a following '=' if appropriate */ - if (OPTION_UNKNOWN != eOption - && bTakesValue - && iArglen > 0 && '=' == *pArg) - { - pArg++; iArglen--; - } - - /* If there is a value following in the same argument, set pValue to - * it and mark the remaining characters as 'consumed' - */ - if (OPTION_UNKNOWN != eOption && bTakesValue && iArglen > 0) - { - pValue = pArg; - pArg += iArglen; - iArglen = 0; - } - } - else /* search the long option */ - { - for (i = 0; i < nOptions; i++) - if (NULL != aOptions[i].pOption - && (size_t)iArglen == strlen(aOptions[i].pOption) - && !strncasecmp(pArg, aOptions[i].pOption, (unsigned)iArglen)) - { - xOption = i; - eOption = aOptions[i].iNumber; - bTakesValue = aOptions[i].bValue; - break; - } - } - - if (OPTION_UNKNOWN == eOption) - { - fprintf(stderr, "%s: Unknown option '", aPgmName); - if (bShort) - fprintf(stderr, "-%c", *pArg); - else - fprintf(stderr, "--%*.*s", (int)iArglen, (int)iArglen, pArg); - fputs("'.\n", stderr); - return 1; - } - - /* If at this point bTakesValue is true, but pValue is still NULL, - * then the value is in the next argument. Get it if it's there. - */ - if (bTakesValue && pValue == NULL && iArg + 1 < argc) - { - iArg++; - pValue = argv[iArg]; - } - - /* Signal an error if pValue is still NULL or if it's empty. */ - if (bTakesValue && (pValue == NULL || !strlen(pValue))) - { - fprintf(stderr, "%s: Option '", aPgmName); - if (bShort) - putc(aOptions[xOption].cOption, stderr); - else - fputs(aOptions[xOption].pOption, stderr); - fputs("' expects a value.\n", stderr); - return 1; - } - - } /* if (unknown option) */ - - /* Before evaluation of the parsed option, determine 'bCont' */ - bCont = bShort && (iArglen > 0) && !bTakesValue; - - /* --- The option evaluation --- */ - - i = (*opt_eval)(eOption, pValue); - if (i) - return i; - - } /* for (iArg) */ - - return 0; -} /* getargs() */ - -/*-------------------------------------------------------------------------*/ -char * -basename (const char *pName) - -/* Find the basename (filename) in a UNIX-style pathname and return - * a pointer to its first character. - * Example: basename("/boot/home/data/l.txt") returns a pointer to "l.txt". - */ - -{ - char * pBase, * cp; - - pBase = (char *)pName; - for (cp = (char *)pName; *cp; cp++) - if ('/' == *cp) - pBase = cp+1; - return pBase; -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/getargs.h b/src/bin/mkdepend/getargs.h deleted file mode 100644 index 35c0a7e387..0000000000 --- a/src/bin/mkdepend/getargs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: getargs.h 1.2 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved. -** This file is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -*/ - -#ifndef __GETARGS_H__ -#define __GETARGS_H__ 1 - -/* Description of an option */ - -typedef struct OptionDesc { - unsigned char cOption; /* The option character (may be \0) */ - char * pOption; /* The option string (may be NULL) */ - int iNumber; /* The associated option number */ - short bValue; /* True: option takes a value */ -} OptionDesc; - -/* Callback function type for option handling */ - -typedef int (*OptionHandler)(int iOption, const char * pValue); - -/* Predefined values for OptionDesc.eNumber */ - -#define OPTION_UNKNOWN 0 /* Option unknown, or 'end of descriptor array' */ -#define OPTION_ARGUMENT 1 /* Not an option, but a real argument */ - -/* --- Prototypes --- */ -extern char * basename (const char *); -extern int getargs(int, char **, OptionDesc[], OptionHandler); - -/* --- Variables --- */ -extern const char * aPgmName; - -#endif /* __GETARGS_H__ */ diff --git a/src/bin/mkdepend/main.c b/src/bin/mkdepend/main.c deleted file mode 100644 index a3c06ec953..0000000000 --- a/src/bin/mkdepend/main.c +++ /dev/null @@ -1,1503 +0,0 @@ -/* $Id: main.c 1.8 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Main module of MkDepend. - * - * Copyright (c) 1995-2001 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - * The module implements the argument parsing and the control flow. - * - * Usage: - * mkdepend {-i|--include [::]} - * [-i-] - * {-x|--except } - * {-S|--select } - * {-s|--suffix {,}[+][:] | [+]:} - * {-p|--objpat {,}[+]: - * [-f|--file ] - * [-d|--dep ] - * [-l|--flat] - * [-m|--ignore-missing] - * [-w|--no-warn-exit] - * [-v|--verbose] - * [-h|-?|--help|--longhelp] - * [-V|--version] - * {} - * - * The recognizes as meta-symbols: - * %s: the full sourcename (w/o suffix) - * %[-][<][]p: the path part of the sourcename - * : skip first directories of the path, defaults to 0. - * < : directories are counted from the end. - * - : use, don't skip the counted directories. - * %n: the base of the sourcename (w/o suffix) - * %%: the character % - * %x: the character 'x' for every other character. - * - * The '+' in the pattern means that the sourcename itself should also be - * listed as dependency of the targetname. - * - *--------------------------------------------------------------------------- - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "args.h" -#include "getargs.h" -#include "main.h" -#include "reader.h" -#include "nodes.h" -#include "util.h" -#include "version.h" - -/*-------------------------------------------------------------------------*/ -/* Stack structure for the tree output routines */ -typedef struct stacknode - { - struct stacknode * pNext; /* Next stacknode */ - struct stacknode * pPrev; /* Previous stacknode */ - NodeRef * pRef; /* Next node to work on */ - } -StackNode; -/* Misc Variables */ - -char * aVersion = "$VER: MkDepend " VERSION " (" __DATE__ ")"; - /* Amiga-style version string */ - -static struct stat aMakeStat; /* Stat buffer for the Makefile */ -static int bMakeExists; /* TRUE: Old Makefile exists */ - -static int returncode = RETURN_OK; /* Global return code */ - -static StackNode * pStack = NULL; /* Stackbase for tree output routine */ - -/*-----------------------------------------------------------------------*/ -void -set_rc (int code, int bAbort) - -/* Set the global returncode to given that is higher - * than the current one. - * If , exit immediately then. - */ - -{ - if (code > returncode) - returncode = code; - if (bAbort) - exit(returncode); -} - -/*-------------------------------------------------------------------------*/ -void -exit_doserr (int code) - -/* Print a message according to errno, then exit with . - */ - -{ - perror(aPgmName); - set_rc(code, TRUE); -} - -/*-------------------------------------------------------------------------*/ -void -exit_nomem (char * msg) - -/* Print a "Out of Memory." message and exit with RETURN_FAIL. - */ - -{ - printf("%s: Out of memory%s.\n", aPgmName, msg ? msg : ""); - set_rc(RETURN_FAIL, TRUE); -} - -/*-------------------------------------------------------------------------*/ -static int -readerror (Node * pNode, int rc, int bFindError) - -/* Print an error message after the file for couldn't be opened - * for reading resp. if the file could not be found. - * - * Result is the new return code, based on the given . - */ - -{ - size_t slen; /* Linelen so far */ - size_t len; - int bFlag; /* TRUE if at least one name has been printed in this line */ - NodeRef * pRef; - Node * pRNode; - - if (rc < RETURN_ERROR && (!bFindError || !bIgnoreMiss)) - rc = RETURN_WARN; - if (!bFindError) - { - perror(aPgmName); - printf("%s: Warning: Can't read '%s'.\n", aPgmName, pNode->pName); - } - else if (!bIgnoreMiss) - printf("%s: Warning: Can't find '%s'.\n", aPgmName, pNode->pName); - else - printf("%s: Info: Can't find '%s'.\n", aPgmName, pNode->pName); - - pRef = pNode->pUsers; - if (pRef) - { - printf("%s: Included at least by:", aPgmName); - slen = strlen(aPgmName)+25; - bFlag = FALSE; - - for ( ; pRef ; pRef = pRef->pNext) - { - pRNode = pRef->pNode; - len = strlen(pRNode->pName); - if (slen + len + 2 > 75) - { - if (bFlag) - putchar(','); - putchar('\n'); - slen = 0; - bFlag = FALSE; - } - if (!slen) - { - printf("%s: ", aPgmName); - slen = strlen(aPgmName)+5; - } - if (bFlag) - { - putchar(','); - slen++; - } - printf(" %s", pRNode->pName); - slen += len+1; - bFlag = TRUE; - } - if (slen) - putchar('\n'); - } - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -readfiles (void) - -/* Read and analyse all files. - * If a file can't be read, print a message. - * Return 0 if all went well, RETURN_WARN if one of the files could not be - * found, RETURN_ERROR if one of the files could not be read properly. - */ - -{ - int rc; /* Return value */ - Node * pNode; /* Node of the file under examination */ - int srcRead; /* Number of source files read */ - const char * pName; /* Includefile name returned by reader */ - - rc = 0; - srcRead = 0; - - while (NULL != (pNode = nodes_todo()) ) - { - int bSystem; /* TRUE if it's a <> include */ - - if (pNode->flags & NODE_NOTFND) - continue; - - if (!reader_open(pNode->pName)) - { - rc = readerror(pNode, rc, FALSE); - continue; - } /* If (can't open pNode->pName) */ - - if (bVerbose) - { - printf(" reading %-65s\r", pNode->pName); fflush(stdout); - } - - while (NULL != (pName = reader_get(&bSystem)) ) - { - int index; /* index into aIncl[] */ - Node * pChild; /* Node of included file, NULL if not found */ - Node * pChFirst; /* First 'direct' child node */ - - for (index = -1, pChild = NULL, pChFirst = NULL - ; !pChild && index < iInclSize - ; index++) - { - char aName[FILENAME_MAX+1]; - char * pCName; /* aName[] cleaned up */ - char * pCBase; /* Namepart in *pCName */ - - /* Don't look for system includes in non-system directories. */ - if (index >= 0 && bSplitPath && bSystem && !aIncl[index].bSysPath) - continue; - - aName[FILENAME_MAX] = '\0'; - - if (index < 0) - { - /* Special case: look directly for the filename. - * If bSplitPath is given, or if the filename is absolute, - * use it unchanged. Else, use the path of the including - * file as anchor. - */ - - if (bSplitPath || '/' == *pName) - strcpy(aName, pName); - else - { - size_t oFilename; - - oFilename = (unsigned)(pNode->pBase - pNode->pName); - strncpy(aName, pNode->pName, oFilename); - strcpy(aName+oFilename, pName); - } - } - else - { - /* Standard case: build the pathname from the include - * pathname. - */ - - strcpy(aName, aIncl[index].pPath); - strcat(aName, pName); - } - - /* Cleanup the filename and check if it is listed in - * the tree - */ - pCName = util_getpath(aName, &pCBase); - if (!pCName) - { - if (bVerbose) - printf("%-78s\r", ""); - reader_close(); - exit_nomem(" (readfiles: 1. util_getpath)"); - } - - pChild = nodes_findadd(pCName, TRUE); - - if (pChild->flags & NODE_NEW) - { - /* New file: check if it exists and set up the - * node properly - */ - - struct stat aStat; - - pChild->pName = pCName; - pChild->pBase = pCBase; - - if (index >= 0) - { - pChild->pPath = util_getpath(pName, NULL); - pChild->iInclude = index; - } - else if (pNode->iInclude < 0 || pNode->flags & NODE_SOURCE) - { - pChild->pPath = util_getpath(pCName, NULL); - pChild->iInclude = -1; - } - else - { - strcpy(aName, pNode->pPath); - strcat(aName, pName); - pChild->pPath = util_getpath(aName, NULL); - pChild->iInclude = pNode->iInclude; - } - if (!pChild->pPath) - { - if (bVerbose) - printf("%-78s\r", ""); - reader_close(); - exit_nomem(" (readfiles: 2. util_getpath)"); - } - - pChild->flags = (short)(bSystem ? NODE_SYSTEM : 0); - - /* It's ok to not find <>-includes - they just don't have - * to appear in the output then. - */ - if (stat(pCName, &aStat)) - pChild->flags |= NODE_NOTFND | (bSystem ? NODE_IGNORE : 0); - } - - /* The pChFirst is needed if the include can't be found - * so we can keep track from where it is included. - */ - if (index < 0) - pChFirst = pChild; - - /* Test if the file for pChild exists. - */ - if (pChild->flags & NODE_NOTFND) - { - /* Make sure that the file is listed in the warnings - * if appropriate. - */ - if (index >= 0) - pChild->flags |= NODE_IGNORE; - else if ((pChild->flags & NODE_IGNORE) && !bSystem) - pChild->flags ^= NODE_IGNORE; - pChild = NULL; - } - - /* For absolute pNames, only index -1 is tried */ - if ('/' == *pName) - break; - } /* for (index = -1..iInclSize) */ - - assert(pChFirst != NULL); - - if (pChild ? nodes_depend(pChild, pNode) - : nodes_depend(pChFirst, pNode)) - { - if (bVerbose) - printf("%-78s\r", ""); - reader_close(); - exit_nomem(" (readfiles: nodes_depend)"); - } - } /* while(get pName from file */ - - if (bVerbose) - printf("%-78s\r", ""); - if (!reader_eof() || reader_close()) - { - perror(aPgmName); - printf("%s: Error reading '%s'\n", aPgmName, pNode->pName); - rc = RETURN_ERROR; - } - else if (pNode->flags & NODE_SOURCE) - { - srcRead++; - } - } /* while (nodes_todo()) */ - - if (!srcRead) - { - printf("%s: No source file read.\n", aPgmName); - rc = RETURN_ERROR; - } - - /* Walk tree and print all include files not found */ - nodes_initwalk(); - while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) - { - if ((pNode->flags & (NODE_NOTFND|NODE_IGNORE)) == NODE_NOTFND) - { - if (pNode->pUsers) - rc = readerror(pNode, rc, TRUE); - else - pNode->flags |= NODE_IGNORE; - } - } - - if (bVerbose) - fflush(stdout); - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static void -make_objname ( char *pBuf, const char *pName, int slen - , const char * pObjExt, const char *pObjPat - ) - -/* Construct the name of the dependency target. - * - * pBuf : Buffer to construct the name in. - * pName : Name of the sourcefile. - * slen : Length of the sourcefile suffix. - * pObjExt: Object extensions for this sourcefile, may be NULL. - * pObjPat: Object pattern for this sourcefile, may be NULL. - * - * If pObjPat is not NULL, the pattern is used to construct the name. - * If pObjPat is NULL, the pObjExt string is appended to the sourcefile - * name (minus its source suffix) to construct the name. If pObjExt is - * NULL, the default object extension is used. - */ - -{ - size_t nlen, plen; - char * pBasename; - const char * pSrc, * pMark; - char *pDst, ch; - short flags; - long number; - -#define GOT_MINUS (1<<0) -#define GOT_ANGLE (1<<1) -#define GOT_NUMBER (1<<2) -#define NOT_DONE (1<<3) -#define NO_PATTERN (1<<4) - - number = 0; - nlen = strlen(pName)-slen; - if (!pObjPat) - { - strcpy(pBuf, pName); - if (pObjExt) - strcpy(pBuf+nlen, pObjExt); - else - strcpy(pBuf+nlen, sObjExt); - return; - } - pBasename = basename(pName); - plen = (unsigned)(pBasename-pName); - pSrc = pObjPat; - pDst = pBuf; - while ('\0' != (ch = *pSrc++)) - { - if (ch != '%') - { - *pDst++ = ch; - continue; - } - - pMark = pSrc; - flags = 0; - do - { - ch = *pSrc++; - switch(ch) - { - case '-': - if (flags & (GOT_MINUS|GOT_ANGLE|GOT_NUMBER)) - flags = NO_PATTERN; - else - flags |= GOT_MINUS|NOT_DONE; - break; - - case '<': - if (flags & (GOT_ANGLE|GOT_NUMBER)) - flags = NO_PATTERN; - else - flags |= GOT_ANGLE|NOT_DONE; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (flags & GOT_NUMBER) - flags = NO_PATTERN; - else - { - char * pTail; - - number = strtol(pSrc-1, &pTail, 10); - pSrc = pTail; - flags |= GOT_NUMBER|NOT_DONE; - } - break; - - case 's': - strncpy(pDst, pName, nlen); - pDst += nlen; - flags = 0; - break; - - case 'p': - if (pName != pBasename - && (!(flags & GOT_MINUS) || (flags & GOT_NUMBER)) - ) - { - const char * cp; - size_t cplen; - - cp = pName; - cplen = plen; - if (flags & GOT_NUMBER) - { - if (flags & GOT_ANGLE) - { - cp = pName+plen; - number++; - while (number) - { - --cp; - if (*cp == '/' || *cp == ':') - { - number--; - if (!number) - cp++; - } - if (cp == pName) - break; - } - } - else - { - cp = pName; - while (number && cp != pBasename) - { - if (*cp == '/' || *cp == ':') - { - number--; - } - cp++; - } - } - /* cp now points to the character after the - * determined path part. - */ - - if (flags & GOT_MINUS) - { - cplen = (unsigned)(cp - pName); - cp = pName; - } - else - cplen = plen - (cp-pName); - } - if (cplen) - { - strncpy(pDst, cp, cplen); - pDst += cplen; - } - } - flags = 0; - break; - - case 'n': - strncpy(pDst, pBasename, nlen-plen); - pDst += nlen-plen; - flags = 0; - break; - - case '%': - *pDst++ = '%'; - flags = 0; - break; - - default: - flags = NO_PATTERN; - break; - } - } - while (flags & NOT_DONE); - if (flags & NO_PATTERN) - pSrc = pMark; /* to be read again as normal text */ - } - *pDst = '\0'; - -#undef GOT_MINUS -#undef GOT_ANGLE -#undef GOT_NUMBER -#undef NOT_DONE -#undef NO_PATTERN -} - -/*-------------------------------------------------------------------------*/ -static int -output_node_tree (Node * pNode, int bUsers, int bSelect) - -/* Output the collected dependencies (bUsers is FALSE) resp. the collected - * users (bUsers is TRUE) in tree form into the Depfile. - * If is TRUE, only files marked as selected are considered. - * - * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a - * severe error. - */ - -{ - StackNode * pTop; /* Stackbase, next free Stacktop */ - int rc; - Node * pRNode; /* referenced node */ - NodeRef * pRef; /* Next node to work on */ - int level; /* Depth in dependency tree */ - char aObjname[FILENAME_MAX+1]; - int i, len; - - assert(pNode); - - rc = RETURN_OK; - - /* If bSelect is true, but the pNode is not marked as selected, - * there is nothing to print. - */ - if (bSelect && !(pNode->flags & (NODE_SELECT|NODE_ISELECT))) - return rc; - - do - { - pTop = pStack; - - aObjname[FILENAME_MAX] = '\0'; - - /* Print name of the basenode */ - if (!bUsers) - { - if (reader_write(pNode->pName)) - { - rc = RETURN_ERROR; - break; /* outer while */ - } - if (reader_write((pNode->flags & NODE_NOTFND) ? " : (not found)\n" - : " :\n") - ) - { - rc = RETURN_ERROR; - break; /* outer while */ - } - } - - /* Initialize the tree output */ - pTop->pRef = bUsers ? pNode->pUsers : pNode->pDeps; - level = 1; - pRef = pTop->pRef; - - /* Tree output loop - */ - while (1) - { - int bQuoteIt; - - /* On end of this level: pop stack */ - if (!pRef) - { - if (pTop == pStack) - break; - pRef = pTop->pRef; - level--; - pTop = pTop->pPrev; - continue; - } - - /* If the file wasn't found, skip this node. */ - if (pRef->pNode->flags & NODE_IGNORE) - { - pRef = pRef->pNext; - continue; - } - - /* If bSelect is true, but this node is not marked, skip it - */ - if (bSelect && !(pRef->pNode->flags & (NODE_SELECT|NODE_ISELECT))) - { - pRef = pRef->pNext; - continue; - } - - /* Output filename of referenced node */ - pRNode = pRef->pNode; - if (!(pRNode->flags & NODE_SOURCE) && pRNode->iInclude >= 0) - { - if (aIncl[pRNode->iInclude].pSymbol) - strcpy(aObjname, aIncl[pRNode->iInclude].pSymbol); - else - strcpy(aObjname, aIncl[pRNode->iInclude].pPath); - strcat(aObjname, pRNode->pPath); - strcat(aObjname, pRNode->pBase); - } - else - { - strcpy(aObjname, pRNode->pName); - } - assert(aObjname[FILENAME_MAX] == '\0'); - len = (signed)strlen(aObjname); - bQuoteIt = (strchr(aObjname+1, ' ') != NULL); - for (i = 0; i < level-1; i++) - if (reader_writen(" ", 4)) - { - rc = RETURN_ERROR; - break; /* for */ - } - if (!rc && i < level && reader_writen(bUsers ? " -> " : " <- ", 4)) - rc = RETURN_ERROR; - if (!rc && bQuoteIt && reader_writen("'", 1)) - rc = RETURN_ERROR; - if (!rc && reader_writen(aObjname, (size_t)len)) - rc = RETURN_ERROR; - if (!rc && bQuoteIt && reader_writen("'", 1)) - rc = RETURN_ERROR; - if (!rc && (pRNode->flags & NODE_NOTFND) && reader_writen(" (not found)", 12)) - rc = RETURN_ERROR; - if (!rc && reader_writen("\n", 1)) - rc = RETURN_ERROR; - if (rc) - break; /* tree-while() */ - - /* Push this level onto the stack */ - if (!pTop->pNext) - { - StackNode * pNew; - pNew = malloc(sizeof(*pNew)); - if (!pNew) - { - if (bVerbose) - printf("%-78s\r", ""); - printf("%s: Out of memory.\n", aPgmName); - rc = RETURN_ERROR; - break; /* tree-while */ - } - memset(pNew, 0, sizeof(*pNew)); - pTop->pNext = pNew; - pNew->pPrev = pTop; - pTop = pNew; - } - else - { - pTop = pTop->pNext; - } - pTop->pRef = pRef->pNext; - - /* Continue with next deeper level */ - level++; - pRef = bUsers ? pRNode->pUsers : pRNode->pDeps; - } /* end while(1) - tree output loop */ - - } while(0); - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -output_tree (void) - -/* Output the collected dependencies in tree form into the Depfile. - * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a - * severe error. - */ - -{ - int rc; - char * pFile; /* Name of file to create */ - Node * pNode; - - pFile = sDepfile; - assert(pFile); - - rc = RETURN_OK; - do - { - if (!pStack) - { - /* Initialise stack */ - pStack = malloc(sizeof(*pStack)); - if (!pStack) - { - printf("%s: Out of memory\n", aPgmName); - rc = RETURN_ERROR; - break; - } - memset(pStack, 0, sizeof(*pStack)); - } - - /* Open files */ - if (reader_openrw(NULL, pFile)) - { - perror(aPgmName); - printf("%s: Can't write '%s'\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - if (bVerbose) - { - printf(" creating '%s'\r", pFile); - fflush(stdout); - } - - /* Walk and output the dependencies and users of the - * skeleton sources. - */ - nodes_initwalk(); - while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) - { - if (!(pNode->flags & (NODE_IGNORE)) - && (pNode->flags & (NODE_SOURCE|NODE_AVOID)) == NODE_SOURCE - && (!IS_SELECT_MODE || (pNode->flags & (NODE_SELECT|NODE_ISELECT))) - && !((pNode->flags & NODE_NOTFND) && bIgnoreMiss) - ) - { - rc = output_node_tree(pNode, FALSE, IS_SELECT_MODE); - if (!rc) - rc = output_node_tree(pNode, TRUE, IS_SELECT_MODE); - if (!rc && reader_writen("\n", 1)) - rc = RETURN_ERROR; - } - } - - /* Walk and output the dependencies and users of the - * non-skeleton sources - */ - nodes_initwalk(); - while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) - { - if (!(pNode->flags & (NODE_IGNORE|NODE_SOURCE)) - && (!IS_SELECT_MODE || (pNode->flags & (NODE_SELECT|NODE_ISELECT))) - && !((pNode->flags & NODE_NOTFND) && bIgnoreMiss) - ) - { - rc = output_node_tree(pNode, FALSE, IS_SELECT_MODE); - if (!rc) - rc = output_node_tree(pNode, TRUE, IS_SELECT_MODE); - if (!rc && reader_writen("\n", 1)) - rc = RETURN_ERROR; - } - } - - if (rc == RETURN_ERROR) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - if (reader_writeflush()) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, sDepfile); - rc = RETURN_ERROR; - break; - } - /* Finish up */ - if (bVerbose) - printf("%-78s\r", ""); - - if (reader_close()) - { - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - } while(0); - - while (pStack) - { - StackNode * pTop; - - pTop = pStack; - pStack = pStack->pNext; - free(pTop); - } - - /* Error cleanup */ - if (rc == RETURN_ERROR) - { - reader_close(); - remove(pFile); - } - - if (bVerbose && rc != RETURN_ERROR) - printf("%-78s\r", ""); - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -output_list_flat ( NodeRef * pRef, int startlen - , const char * pIndent, int bAsMake) - -/* Output the given list of dependencies/users, starting with pRef, - * with bAsMake interpreted as below. startlen is the line length - * printed at time of call, pIndent is the indentation string to use. - * - * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a - * severe error. - */ - -{ - int rc; - Node * pRNode; - size_t slen; /* Linelen so far */ - size_t len; - size_t ilen; /* Length of pIndent */ - char aObjname[FILENAME_MAX+1]; - - assert(pIndent); - - rc = RETURN_OK; - aObjname[FILENAME_MAX] = '\0'; - - slen = (size_t)startlen; - ilen = strlen(pIndent); - - for ( ; rc != RETURN_ERROR && pRef; pRef = pRef->pNext) - { - pRNode = pRef->pNode; - - /* If the file was not found and system include, skip the node */ - if (pRNode->flags & (NODE_IGNORE)) - continue; - - /* If the file was not found and the user wants to ignore missing - * includes, skip the node. - */ - if ((pRNode->flags & NODE_NOTFND) && bIgnoreMiss) - continue; - - /* Construct the name of the dependee */ - aObjname[0] = ' '; - aObjname[1] = '\0'; - if (pRNode->iInclude >= 0) - { - short bQuoteIt; - char * pIPath; - - if (aIncl[pRNode->iInclude].pSymbol) - pIPath = aIncl[pRNode->iInclude].pSymbol; - else - pIPath = aIncl[pRNode->iInclude].pPath; - - bQuoteIt = (NULL != strchr(pIPath, ' ')) - || (NULL != strchr(pRNode->pPath, ' ')) - || (NULL != strchr(pRNode->pBase, ' ')); - - if (bQuoteIt) strcat(aObjname, "\""); - strcat(aObjname, pIPath); - strcat(aObjname, pRNode->pPath); - strcat(aObjname, pRNode->pBase); - if (bQuoteIt) strcat(aObjname, "\""); - } - else - { - short bQuoteIt; - bQuoteIt = (NULL != strchr(pRNode->pName, ' ')); - - if (bQuoteIt) strcat(aObjname, "\""); - strcat(aObjname, pRNode->pName); - if (bQuoteIt) strcat(aObjname, "\""); - } - assert(aObjname[FILENAME_MAX] == '\0'); - len = strlen(aObjname); - - /* Fit it into the line */ - if (slen > 0) - { - if (slen+len > 75) - { - if (reader_writen(bAsMake ? " \\\n" : "\n", (size_t)(bAsMake ? 3 : 1))) - { - rc = RETURN_ERROR; - break; /* inner for */ - } - slen = 0; - } - } - if (!slen) - { - if (reader_writen(pIndent, ilen)) - { - rc = RETURN_ERROR; - break; /* inner for */ - } - slen = ilen; - } - if (reader_writen(aObjname, len)) - { - rc = RETURN_ERROR; - break; /* inner for */ - } - slen += len; - } /* for () */ - if (slen && reader_writen("\n", 1)) - rc = RETURN_ERROR; - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -output_node_flat (Node * pNode, int bAsMake, int bSelect) - -/* For a given node pNode Output the collected dependencies/users into a - * file, either as Makefile (bAsMake is TRUE) or as Depfile (bAsMake is - * FALSE). - * The file must have been opened by the caller in the reader module. - * If is true, only files marked as SELECTed are printed. - * - * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a - * severe error. - */ - -{ - int rc; - NodeRef * pList, * pRef; - long suffix; /* Suffix index */ - size_t slen; /* Linelen so far */ - size_t len; - char aObjname[FILENAME_MAX+1]; - - assert(pNode); - - rc = RETURN_OK; - aObjname[FILENAME_MAX] = '\0'; - - /* If bSelect is true, but the pNode is not marked as selected, - * there is nothing to print. - */ - if (bSelect && !(pNode->flags & (NODE_SELECT|NODE_ISELECT))) - return rc; - - /* First, output the dependencies list always */ - pList = nodes_deplist(pNode, FALSE, bSelect); - assert(pList); - pRef = pList; - - /* Check for a given suffix. - * Search backwards in case later definitions overwrote - * earlier ones. - */ - slen = strlen(pNode->pName); - len = 0; - if (!bAsMake) - suffix = -1; - else - for (suffix = aSrcExt.size-1; suffix >= 0; suffix--) - { - len = strlen(aSrcExt.strs[suffix]); - if (!strcmp(pNode->pName+slen-len, aSrcExt.strs[suffix])) - break; - } - - do { - /* Construct the name of the dependency target and write it */ - if (suffix >= 0) - { - char * pObjPat, * pObjExt; - short bQuoteIt; - - pObjExt = aObjExt.size ? aObjExt.strs[suffix] : NULL; - pObjPat = aObjPat.size ? aObjPat.strs[suffix] : NULL; - - make_objname( aObjname, pNode->pName, (int)len, pObjExt, pObjPat); - assert(aObjname[FILENAME_MAX] == '\0'); - bQuoteIt = (NULL != strchr(aObjname, ' ')); - - if ((bQuoteIt && reader_write("\"")) - || reader_write(aObjname) - || (bQuoteIt && reader_write("\"")) - ) - { - rc = RETURN_ERROR; - break; /* while */ - } - slen = strlen(aObjname); - - if (!((pObjExt || pObjPat) ? bGiveSrc[suffix] : bDefGSrc)) - pRef = pRef->pNext; - } - else - { - short bQuoteIt; - - bQuoteIt = (NULL != strchr(pNode->pName, ' ')); - if ((bQuoteIt && reader_write("\"")) - || reader_write(pNode->pName) - || (bQuoteIt && reader_write("\"")) - ) - { - rc = RETURN_ERROR; - break; /* outer while */ - } - pRef = pRef->pNext; - } - - if (bAsMake) - { - if (reader_write(" :")) - { - rc = RETURN_ERROR; - break; /* while */ - } - slen += 2; - rc = output_list_flat(pRef, (int)slen, " ", TRUE); - } - else - { - if (reader_write(" :\n")) - { - rc = RETURN_ERROR; - break; /* while */ - } - if (pRef) - rc = output_list_flat(pRef, 0, " <-", FALSE); - } - nodes_freelist(pList); - slen = 0; - - /* If demanded, output the list of users as well */ - if (RETURN_OK == rc && !bAsMake) - { - pList = nodes_deplist(pNode, TRUE, bSelect); - assert(pList); - if (pList->pNext) - rc = output_list_flat(pList->pNext, 0, " ->", FALSE); - nodes_freelist(pList); - } - - } while(0); - - if (reader_writen("\n", 1)) - rc = RETURN_ERROR; - - return rc; -} - -/*-------------------------------------------------------------------------*/ -static int -output (int bAsMake) - -/* Output the collected dependencies into the Makefile (bAsMake is TRUE) - * resp. into the Depfile (bAsMake is FALSE). - * Return 0 on success, RETURN_WARN on a mild error, RETURN_ERROR on a - * severe error. - */ - -{ - int rc; - char * pBackup; /* Name of the Makefilebackup */ - char * pFile; /* Name of file to create */ - Node * pNode; - - pBackup = NULL; - pFile = bAsMake ? sMake : sDepfile; - - assert(pFile); - - /* Rename old Makefile if necessary */ - if (bAsMake && bMakeExists) - { - pBackup = (char *)malloc(strlen(sMake)+5); - strcpy(pBackup, sMake); - strcat(pBackup, ".bak"); - remove(pBackup); - if (rename(sMake, pBackup)) - { - perror(aPgmName); - printf("%s: Can't rename '%s' to '%s'.\n", aPgmName, sMake, pBackup); - free(pBackup); - return RETURN_ERROR; - } - } - - rc = RETURN_OK; - do - { - char * pTagline; - - /* Open files */ - if (reader_openrw(pBackup, pFile)) - { - perror(aPgmName); - printf("%s: Can't write '%s'\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - if (bVerbose) - { - printf(" %s '%s'\r", (bMakeExists && bAsMake) ? "updating" : "creating", pFile); - fflush(stdout); - } - - /* Copy the Makefile up to the tagline */ - pTagline = IS_SELECT_MODE - ? "# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS FOLLOW ---\n" - : "# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS FOLLOW ---\n"; - if (bAsMake && reader_copymake(pTagline)) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error copying '%s' to '%s'.\n", aPgmName, pBackup, sMake); - rc = RETURN_ERROR; - break; - } - - /* Walk and output the dependencies and users. - * First all the files specified as root. - */ - nodes_initwalk(); - while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) - { - if ((pNode->flags & (NODE_SOURCE|NODE_AVOID|NODE_NOTFND)) == NODE_SOURCE) - rc = output_node_flat(pNode, bAsMake, IS_SELECT_MODE); - } /* while (treewalk */ - - /* Second (if wanted), all the files not specified as root. */ - if (RETURN_OK == rc && !bAsMake) - { - nodes_initwalk(); - while (rc != RETURN_ERROR && NULL != (pNode = nodes_inorder()) ) - { - if ((pNode->flags & (NODE_SOURCE|NODE_AVOID)) != NODE_SOURCE - && !(pNode->flags & NODE_NOTFND) - ) - rc = output_node_flat(pNode, bAsMake, IS_SELECT_MODE); - } /* while (treewalk */ - } - - if (rc == RETURN_ERROR) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - pTagline = IS_SELECT_MODE - ? "# --- DO NOT MODIFY THIS LINE -- SELECTED AUTO-DEPENDS PRECEDE ---\n" - : "# --- DO NOT MODIFY THIS LINE -- AUTO-DEPENDS PRECEDE ---\n"; - if (bAsMake && reader_copymake2(pTagline)) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error copying '%s' to '%s'.\n", aPgmName, pBackup, sMake); - rc = RETURN_ERROR; - break; - } - else if (!bAsMake && reader_writeflush()) - { - int i = errno; - if (bVerbose) - printf("%-78s\r", ""); - errno = i; - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, sDepfile); - rc = RETURN_ERROR; - break; - } - /* Finish up */ - if (bVerbose) - printf("%-78s\r", ""); - - if (reader_close()) - { - perror(aPgmName); - printf("%s: Error writing '%s'.\n", aPgmName, pFile); - rc = RETURN_ERROR; - break; - } - - if (bAsMake && bMakeExists && chmod(sMake, aMakeStat.st_mode)) - { - /* perror(aPgmName); */ - printf("%s: Warning: Can't update mode of '%s'.\n", aPgmName, sMake); - rc = RETURN_WARN; - } - - if (pBackup && remove(pBackup)) - { - perror(aPgmName); - printf("%s: Warning: Can't remove backup '%s'.\n", aPgmName, pBackup); - rc = RETURN_WARN; - break; - } - - } while(0); - - /* Error cleanup */ - if (rc == RETURN_ERROR) - { - reader_close(); - remove(pFile); - if (pBackup && rename(pBackup, sMake)) - { - perror(aPgmName); - printf("%s: Can't restore '%s' from backup '%s'\n", aPgmName, sMake, pBackup); - } - } - - if (bVerbose && rc != RETURN_ERROR) - printf("%-78s\r", ""); - - if (pBackup) - free(pBackup); - - return rc; -} - -/*-------------------------------------------------------------------------*/ -int main (int argc, char *argv[]) - -{ - int i; - - reader_init(); - - /* Get arguments, set up defaults */ - parseargs(argc, argv); - if (!aFiles.size) - { - if (add_expfile(&aFiles, "*.c")) - exit_nomem(" (main: add_expfile)"); - } - if (!sObjExt) - sObjExt = ".o"; - - if (!aSrcExt.size) - { - if (array_addfile(&aSrcExt, ".c") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".cc") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".cp") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".cpp") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".cxx") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".C") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".CC") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".CP") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".CPP") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - if (array_addfile(&aSrcExt, ".CXX") || array_addfile(&aObjExt, NULL)) - exit_nomem(" (main: add suffix)"); - } - - if (bVerbose) - { - printf("MkDepend %s -- Make Dependency Generator\n", VERSION); - putchar('\n'); - } - - /* Look for the Makefile to modify */ - if (sMake) - { - bMakeExists = !stat(sMake, &aMakeStat); - } - else if (!sDepfile) - { - sMake = "Makefile"; - bMakeExists = !stat(sMake, &aMakeStat); - if (!bMakeExists) - { - sMake = "makefile"; - bMakeExists = !stat(sMake, &aMakeStat); - } - if (!bMakeExists) - { - sMake = "Makefile.mk"; - bMakeExists = !stat(sMake, &aMakeStat); - } - if (!bMakeExists) - { - sMake = "makefile.mk"; - bMakeExists = !stat(sMake, &aMakeStat); - } - if (!bMakeExists) - { - sMake = "GNUMakefile"; - bMakeExists = !stat(sMake, &aMakeStat); - } - if (!bMakeExists) - sMake = "Makefile"; - } - - /* Add the source files to the tree */ - if (!aFiles.size) - { - printf("%s: No files given.\n", aPgmName); - set_rc(RETURN_WARN, TRUE); - } - else - { - struct stat aStat; /* buffer for stat() */ - - for (i = 0; i < aFiles.size; i++) - { - if (stat(aFiles.strs[i], &aStat)) - { - printf("%s: Warning: Can't find source '%s'.\n", aPgmName - , aFiles.strs[i]); - set_rc(RETURN_WARN, FALSE); - } - else if (nodes_addsource(aFiles.strs[i], FALSE)) - exit_nomem(" (main: add source)"); - } - - /* If this leaves us with no source files at all, readfiles() - * will complain. - */ - } - - /* Mark the exceptional files */ - for (i = 0; i < aAvoid.size; i++) - { - if (nodes_addsource(aAvoid.strs[i], TRUE)) - exit_nomem(" (main: add avoided source)"); - } - - /* Read and analyse all those files */ - set_rc(readfiles(), 0); - - /* Handle the selection of files */ - if (IS_SELECT_MODE) - { - Node * pNode; - - /* First, mark all nodes with selected files */ - for (i = 0; i < aSelect.size; i++) - { - pNode = nodes_find(aSelect.strs[i]); - if (pNode) - pNode->flags |= NODE_SELECT; - } - - /* Now walk the tree and propagate the select information */ - nodes_initwalk(); - while (NULL != (pNode = nodes_inorder()) ) - { - if (!(pNode->flags & (NODE_IGNORE)) - && (pNode->flags & (NODE_SOURCE|NODE_AVOID)) == NODE_SOURCE) - { - NODES_UNMARK(pNode); - nodes_mark_select(pNode); - } - } - } - - if (returncode < RETURN_ERROR && sMake) - set_rc(output(TRUE), 0); - - if (returncode < RETURN_ERROR && sMake && bVerbose) - printf("%s '%s'.\n", bMakeExists ? "Updated" : "Created", sMake); - - if (returncode < RETURN_ERROR && sDepfile) - set_rc(bFlat ? output(FALSE) : output_tree(), 0); - - if (returncode < RETURN_ERROR && sDepfile && bVerbose) - printf("Created '%s'.\n", sDepfile); - - return (returncode == RETURN_WARN && bNoWarnExit) ? RETURN_OK : returncode; -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/main.h b/src/bin/mkdepend/main.h deleted file mode 100644 index 6abdb545b8..0000000000 --- a/src/bin/mkdepend/main.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id: main.h 1.4 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved. -** This file is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -*/ - -#ifndef __MAIN_H__ -#define __MAIN_H__ 1 - -/* Return codes */ - -#define RETURN_OK 0 /* Everything is ok */ -#define RETURN_WARN 1 /* A warning was issued */ -#define RETURN_ERROR 2 /* An error occured */ -#define RETURN_FAIL 3 /* A fatal error occured */ - -/* Boolean values */ - -#define FALSE 0 -#define TRUE 1 - -/* Macros */ - -#define IS_SELECT_MODE (aSelect.size != 0) - /* The macro returns TRUE if only selected dependencies are to be - * generated. - */ - -/* Prototypes */ - -extern void set_rc (int, int); -extern void exit_doserr (int); -extern void exit_nomem (char *); - -#endif diff --git a/src/bin/mkdepend/mkdepend.rdef b/src/bin/mkdepend/mkdepend.rdef deleted file mode 100644 index 90e86d2909..0000000000 --- a/src/bin/mkdepend/mkdepend.rdef +++ /dev/null @@ -1,11 +0,0 @@ -resource app_version -{ - major = 1, - middle = 7, - minor = 1, - variety = 5, - internal = 0, - short_info = "1.7.1", - long_info = "1.7.1 © 1995-2001 Lars Düning. All rights reserved." -}; - diff --git a/src/bin/mkdepend/nodes.c b/src/bin/mkdepend/nodes.c deleted file mode 100644 index 0a5fe6aa50..0000000000 --- a/src/bin/mkdepend/nodes.c +++ /dev/null @@ -1,587 +0,0 @@ -/* $Id: nodes.c 1.6 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Management of the dependency tree and nodes. - * - * Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - * Each file (source or include) is associated one node which is kept in - * a binary search tree with the name as index. Glued to each node is - * a list of that nodes which files the master nodes includes. - * Each node contains an extra node pointer the module uses to implement - * tree-independant lists, namely the TODO list of files still to read - * and a virtual stack for inorder tree traversals. - * - * Adding and retrieving the files to analyse is done using the functions - * nodes_addsource() - * nodes_depend() - * nodes_todo() - * nodes_select_mark() - * - * The output of the dependency tree is done inorder using - * nodes_initwalk() - * nodes_inorder() - * - * The list of dependencies for one single node is managed using - * nodes_deplist() - * nodes_freelist() - * - * Tree traversal and creation must not be mixed! - *--------------------------------------------------------------------------- - */ - -#include -#include -#include -#include -#include "main.h" -#include "nodes.h" -#include "util.h" - -/*-------------------------------------------------------------------------*/ - -/* Types for block allocation of Nodes and NodeRefs. - * Note that Nodes are never freed. - */ - -#define NBLOCKSIZE 16 - -typedef struct nodeblock - { - struct nodeblock * pNext; /* Next nodeblock */ - int iFree; /* Number of first free node */ - Node aNodes[NBLOCKSIZE]; /* Block of nodes */ - } -NodeBlock; - -#define RBLOCKSIZE 16 - -typedef struct refblock - { - struct refblock * pNext; /* Next refblock */ - int iFree; /* Number of first free noderef */ - NodeRef aRefs[NBLOCKSIZE]; /* Block of noderefs */ - } -RefBlock; - -/*-------------------------------------------------------------------------*/ - -static NodeBlock *pFreeNBlocks = NULL; /* Nodeblocks */ -static RefBlock *pFreeRBlocks = NULL; /* Refblocks */ -static NodeRef *pFreeRefs = NULL; /* List of free NodeRefs */ -static Node *pTree = NULL; /* Dependency tree */ -static Node *pList = NULL; /* List of (tree) nodes */ - /* The List is used as TODO list for the files to analyse as well as - * stack simulation for the tree traversal. - */ - -/*-------------------------------------------------------------------------*/ -static Node * -nodes_newnode (void) - -/* Allocate a new Node. - * - * Result: - * Pointer to the new Node, or NULL on error. - * - * The memory of the Node is cleared, except for .flags which is set - * to NODE_NEW. - */ - -{ - Node * pNode; - - if (!pFreeNBlocks || !pFreeNBlocks->iFree) - { - NodeBlock * pNewBlock; - pNewBlock = (NodeBlock *)malloc(sizeof(*pNewBlock)); - if (!pNewBlock) - return NULL; - memset(pNewBlock, 0, sizeof(*pNewBlock)); - pNewBlock->iFree = NBLOCKSIZE; - pNewBlock->pNext = pFreeNBlocks; - pFreeNBlocks = pNewBlock; - } - pNode = &(pFreeNBlocks->aNodes[--pFreeNBlocks->iFree]); - pNode->flags |= NODE_NEW; - pNode->iInclude = -1; - return pNode; -} - -/*-------------------------------------------------------------------------*/ -static NodeRef * -nodes_newref (void) - -/* Allocate a new NodeRef. - * - * Result: - * Pointer to the new NodeRef, or NULL on error. - * - * The memory of the NodeRef is cleared. - */ - -{ - NodeRef * pRef; - - if (pFreeRefs) - { - pRef = pFreeRefs; - pFreeRefs = pRef->pNext; - } - else - { - if (!pFreeRBlocks || !pFreeRBlocks->iFree) - { - RefBlock * pNewBlock; - pNewBlock = (RefBlock *)malloc(sizeof(*pNewBlock)); - if (!pNewBlock) - return NULL; - pNewBlock->iFree = NBLOCKSIZE; - pNewBlock->pNext = pFreeRBlocks; - pFreeRBlocks = pNewBlock; - } - pRef = &(pFreeRBlocks->aRefs[--pFreeRBlocks->iFree]); - } - memset(pRef, 0, sizeof(*pRef)); - return pRef; -} - -/*-------------------------------------------------------------------------*/ -Node * -nodes_findadd (const char *pName, int bAddToList) - -/* Find the node associated with file *pName. - * If necessary, add the node. - * - * pName: Pointer to the (minimalized) filename of the node. - * bAddToList: If true, a newly allocated node is also added to - * the TODO list. - * - * Result: - * Pointer to the node associated with this filename, or NULL on error. - * - * If the node has been added by this call, NODE_NEW is set in its .flags, - * but it is empty otherwise. - */ - -{ - Node * pThis, * pPrev; - int i; - - assert(pName); - - if (!pTree) - { - pTree = nodes_newnode(); - if (bAddToList) - { - pTree->pNext = pList; - pList = pTree; - } - return pTree; - } - - pPrev = NULL; - pThis = pTree; - while(pThis) - { - i = strcmp(pThis->pName, pName); - if (!i) - return pThis; - pPrev = pThis; - if (i > 0) - pThis = pThis->pLeft; - else - pThis = pThis->pRight; - } - pThis = nodes_newnode(); - if (pThis) - { - if (i > 0) - pPrev->pLeft = pThis; - else - pPrev->pRight = pThis; - - if (bAddToList) - { - pThis->pNext = pList; - pList = pThis; - } - } - return pThis; -} - -/*-------------------------------------------------------------------------*/ -Node * -nodes_find (const char *pName) - -/* Find the node associated with file *pName. - * - * pName: Pointer to the (minimalized) filename of the node. - * - * Result: - * Pointer to the node associated with this filename, or NULL on error. - */ - -{ - Node * pThis, * pPrev; - int i; - - assert(pName); - - if (!pTree) - return NULL; - - pPrev = NULL; - pThis = pTree; - while(pThis) - { - i = strcmp(pThis->pName, pName); - if (!i) - return pThis; - pPrev = pThis; - if (i > 0) - pThis = pThis->pLeft; - else - pThis = pThis->pRight; - } - return NULL; -} - -/*-------------------------------------------------------------------------*/ -int -nodes_addsource (char *pName, int bAvoid) - -/* Add a source file to the dependency tree. - * - * pName : Name of the file to add (it will be duplicated). - * bAvoid: TRUE if this is a file to be avoided. - * - * Result: - * 0 on success, non-0 on error (out of memory). - * - * The file is also added to the internal TODO list of files if it is - * a genuine source file. - */ - -{ - Node *pNode; - char *pBasename; - - assert(pName); - - pName = util_getpath(pName, &pBasename); - if (!pName) - return 1; - pNode = nodes_findadd(pName, !bAvoid); - if (!pNode) - return 1; - if (pNode->flags & NODE_NEW) - { - pNode->flags = NODE_SOURCE; - pNode->pName = pName; - pNode->pBase = pBasename; - pNode->pPath = util_getpath(pName, NULL); - if (!pNode->pPath) - return 1; - } - else - free(pName); - - if (bAvoid) - pNode->flags |= NODE_AVOID; - - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -nodes_depend (Node * pChild, Node * pParent) - -/* Add node pChild to the list of dependees of pParent, vice versa add - * pParent to the list of users of pName. - * - * pChild : Node of the file included by pParent. - * pParent: Node which depends on pChild. - * - * Result: - * 0 on success, non-0 on error (out of memory). - * - * The file is added to the dependee- and user-lists. - */ - -{ - NodeRef * pRef; - - assert(pParent); - assert(pChild); - - /* Add pChild to pParent->pDeps if not already there */ - for ( pRef = pParent->pDeps - ; pRef && pRef->pNode != pChild - ; pRef = pRef->pNext - ) /* SKIP */; - if (!pRef) - { - pRef = nodes_newref(); - if (!pRef) - return 1; - pRef->pNode = pChild; - pRef->pNext = pParent->pDeps; - pParent->pDeps = pRef; - } - - /* Add pParent to pChild->pUsers if not already there */ - for ( pRef = pChild->pUsers - ; pRef && pRef->pNode != pParent - ; pRef = pRef->pNext - ) /* SKIP */; - if (!pRef) - { - pRef = nodes_newref(); - if (!pRef) - return 1; - pRef->pNode = pParent; - pRef->pNext = pChild->pUsers; - pChild->pUsers = pRef; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ -Node * -nodes_todo (void) - -/* Return the tree node of the next file to analyse. - * - * Result: - * Pointer to the node of the next file to analyse, or NULL if there is - * none. - */ - -{ - Node * pNode; - - /* NODE_DONE should not happen, but checking it is free */ - while (pList && (pList->flags & (NODE_AVOID|NODE_DONE))) - pList = pList->pNext; - if (pList) - { - pNode = pList; - pList = pList->pNext; - pNode->flags |= NODE_DONE; - } - else - pNode = NULL; - return pNode; -} - -/*-------------------------------------------------------------------------*/ -int -nodes_mark_select (Node *pNode) - -/* Check if this node, or one of its dependency nodes has been marked - * as selected. If yes, mark pNode as well and return TRUE, otherwise - * return FALSE. - * - * This is a recursive function. We avoid loops by temporarily marking - * the node. - */ - -{ - int rc; - NodeRef * pRef; - - assert(pNode); - - if (NODES_MARKED(pNode)) - return FALSE; - - if (pNode->flags & NODE_ISELECT) - return TRUE; - - NODES_MARK(pNode); - /* First, recurse into the dependency nodes */ - rc = FALSE; - for (pRef = pNode->pDeps; pRef != NULL; pRef = pRef->pNext) - { - if (nodes_mark_select(pRef->pNode)) - rc = TRUE; - } - - if (rc && !(pNode->flags & NODE_SELECT)) - { - pNode->flags |= NODE_ISELECT; - } - - NODES_UNMARK(pNode); - - return rc || (pNode->flags & (NODE_SELECT|NODE_ISELECT)); -} /* nodes_mark_select() */ - -/*-------------------------------------------------------------------------*/ -void -nodes_initwalk (void) - -/* Initialise a tree traversal. - */ - -{ - assert(!pList); - pList = pTree; - if (pList) - { - pList->iStage = 0; - pList->pNext = NULL; - } -} - -/*-------------------------------------------------------------------------*/ -Node * -nodes_inorder (void) - -/* Return the next Node of an inorder tree traversal. - * - * Result: - * Pointer to the next node, or NULL if traversal is complete. - */ - -{ - Node *pNode = NULL; - if (!pList) - return NULL; - while (pList) - { - switch (pList->iStage) - { - case 0: - pList->iStage++; - pNode = pList->pLeft; - break; - case 1: - pList->iStage++; - return pList; - break; - case 2: - pList->iStage++; - pNode = pList->pRight; - break; - case 3: - pList = pList->pNext; - pNode = NULL; - break; - default: - assert(0); - break; - } - if (pNode) - { - pNode->pNext = pList; - pList = pNode; - pNode->iStage = 0; - } - } - return NULL; -} - -/*-------------------------------------------------------------------------*/ -NodeRef * -nodes_deplist (Node * pNode, int bUsers, int bSelect) - -/* Gather the list of dependees or users of *pNode. - * - * pNode: the Node to get the list for. - * bUsers: TRUE: gather the list of users instead of the dependees. - * bSelect: TRUE: gather only files marked as NODE_SELECT. - * - * Result: - * Pointer to the list of dependees/users, or NULL if an error occurs. - * First entry in the list is pNode itself. - */ - -{ - NodeRef *pDList; - NodeRef *pMark; - NodeRef *pThis; - NodeRef *pRover; - Node *pDep; - - assert(pNode); - pDList = nodes_newref(); - if (!pDList) - return NULL; - - /* The list of dependencies is gathered in a wide search. */ - pDList->pNode = pNode; - NODES_MARK(pNode); - for ( pThis = pDList, pMark = pDList - ; pMark - ; pMark = pMark->pNext - ) - { - for ( pRover = (bUsers ? pMark->pNode->pUsers : pMark->pNode->pDeps) - ; pRover - ; pRover = pRover->pNext - ) - { - pDep = pRover->pNode; - if (!NODES_MARKED(pDep)) - { - pThis->pNext = nodes_newref(); - if (!pThis->pNext) - return NULL; - pThis = pThis->pNext; - pThis->pNode = pDep; - NODES_MARK(pDep); - } - } - } - - /* If bSelect is requested, remove all non-SELECT nodes from the list - * (but always keep the first one). - */ - if (bSelect) - { - pThis = pDList; - while (pThis->pNext != NULL) - { - pMark = pThis->pNext; - if (!(pMark->pNode->flags & NODE_SELECT)) - { - NODES_UNMARK(pMark->pNode); - pThis->pNext = pMark->pNext; - pMark->pNext = pFreeRefs; - pFreeRefs = pMark; - } - else - pThis = pMark; - } - } - - return pDList; -} - -/*-------------------------------------------------------------------------*/ -void -nodes_freelist (NodeRef * pDList) - -/* Free a dependency list produced earlier by nodes_deplist(). - * - * pDList: Base of the list to free. - */ - -{ - NodeRef * pThis; - - while (pDList) - { - NODES_UNMARK(pDList->pNode); - pThis = pDList; - pDList = pDList->pNext; - pThis->pNext = pFreeRefs; - pFreeRefs = pThis; - } -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/nodes.h b/src/bin/mkdepend/nodes.h deleted file mode 100644 index 65d7556fec..0000000000 --- a/src/bin/mkdepend/nodes.h +++ /dev/null @@ -1,95 +0,0 @@ -/* $Id: nodes.h 1.5 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Copyright (c) 1995-2000 by Lars Düning. All Rights Reserved. -** This file is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -*/ - -#ifndef __NODES_H__ -#define __NODES_H__ 1 - -struct noderef; /* forward */ - -/* Node structure to build the dependency tree - */ -typedef struct node - { - struct node * pLeft, * pRight; /* Tree pointers */ - struct node * pNext; /* List of Files to do; stack for traversals */ - - char * pName; - /* Searchkey: Name of this file. - * This is the minimal full pathname with which the file can be read. - * For source files (and files to be avoided) it is identical with the name - * given on the commandline. - */ - char * pBase; - /* The filename part of the the file's pathname. - * This is a pointer into pName. - */ - char * pPath; - /* The directory part of the file's pathname. - * Relative paths are interpreted depending on the type of the file: - * source files are relative to the current working directory, - * non-source files are relative to aIncl[.iInclude]. - */ - int iInclude; - /* Included non-sourcefiles: the index into aIncl[]/aSymbol[]. - * A negative index denotes an absolute filename, or one relative - * to the cwd. - */ - short flags; /* misc flags */ - struct noderef * pDeps; /* What this file depends on */ - struct noderef * pUsers; /* Who depends on this file */ - short iStage; /* Stage counter for tree traversals */ - } -Node; - -/* Node.flags - */ -#define NODE_MARK (1<<0) /* Generic Node marker, used e.g. in tree walks */ -#define NODE_NEW (1<<1) /* Node is unused */ -#define NODE_SOURCE (1<<2) /* Node is a skeleton source */ -#define NODE_AVOID (1<<3) /* Node is not part of the skeleton sources */ -#define NODE_NOTFND (1<<4) /* Node describes a non-existant file */ -#define NODE_DONE (1<<5) /* Node has been evaluated */ -#define NODE_SYSTEM (1<<6) /* File is an <>-include */ -#define NODE_IGNORE (1<<7) /* Data for this node shall not be printed */ -#define NODE_SELECT (1<<8) /* Marks selected include files */ -#define NODE_ISELECT (1<<9) /* Marks nodes between source and selected - * include files */ - -/* Node marking - */ -#define NODES_MARK(node) ((node)->flags |= NODE_MARK) -#define NODES_UNMARK(node) ((node)->flags &= (short)(~NODE_MARK)) -#define NODES_MARKED(node) ((node)->flags & NODE_MARK) - -/* Test if the _SYSTEM flag has a specific value - */ -#define NODES_SYSTEST(node,value) ( (node)->flags & NODE_SYSTEM ? (value) : !(value) ) - -/* Reference structure to treenodes - */ -typedef struct noderef - { - struct noderef * pNext; /* next NodeRef */ - Node * pNode; /* referenced Node */ - } -NodeRef; - -/* Prototypes */ - -extern Node * nodes_findadd (const char *, int); -extern Node * nodes_find (const char *); -extern int nodes_addsource (char *, int); -extern int nodes_depend (Node *, Node *); -extern int nodes_mark_select (Node *); -extern Node * nodes_todo (void); -extern void nodes_initwalk (void); -extern Node * nodes_inorder (void); -extern NodeRef * nodes_deplist (Node *, int, int); -extern void nodes_freelist (NodeRef *); - -#endif diff --git a/src/bin/mkdepend/reader.c b/src/bin/mkdepend/reader.c deleted file mode 100644 index 83dd4cc52d..0000000000 --- a/src/bin/mkdepend/reader.c +++ /dev/null @@ -1,658 +0,0 @@ -/* $Id: reader.c 1.9 Wed, 01 Mar 2000 22:36:57 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Reading of C-Sources and filter for #include statements. -** Also here are routines for the modification of Makefiles. -** -** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved. -** This files is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -** Credits: -** The buffering scheme was inspired by the input module of lcc (by -** Chris Fraser & David Hanson). -**--------------------------------------------------------------------------- -*/ - -#include -#include -#include -#include -#include -#include - -#include "reader.h" - -/*-------------------------------------------------------------------------*/ - -struct filestate - { - int len; /* Number of bytes buffered */ - char buf[1]; /* allocated to bytes */ - }; - -#define BUFSIZE 10240 /* Size of the file buffer */ -static char aBuffer[BUFSIZE+1]; /* File buffer */ -static int fdFile; /* Filehandle */ -static int fdFile2; /* Filehandle Writer */ -static char * pLimit; /* Pointer to closing sentinel in buffer */ -static char * pch; /* Pointer to actual char in buffer */ -static char * pIName; /* Start of include filename */ -static struct filestate * pState; /* Saved state of the Makefile */ - -#define END_OF_BUF() (pch >= pLimit) -#define END_OF_FILE() (pLimit == aBuffer) - -/*-------------------------------------------------------------------------*/ -void -reader_init (void) - -/* Initialize the reader. - */ - -{ - fdFile = -1; - fdFile2 = -1; - aBuffer[BUFSIZE] = '\n'; - pLimit = aBuffer+BUFSIZE; - pch = pLimit; - pIName = NULL; - pState = NULL; -} - -/*-------------------------------------------------------------------------*/ -static int -fillbuffer (void) - -/* Read in the next chunk from file such that incrementing pch will - * access the newly read data. - * - * Result: - * 0 on success, non-0 else (errno holds error code then). - * pch is set to the start of the new data. - */ - -{ - int iRead; - - if (END_OF_FILE()) - return 1; - if (pIName) - { - if (pch > pLimit) - pch = pLimit; - memcpy(aBuffer, pIName, (unsigned)(pLimit-pIName)); - pch -= (pLimit-pIName); - } - else - pch = aBuffer; - iRead = read(fdFile, pch, (unsigned)(aBuffer+BUFSIZE-pch)); - if (iRead >= 0) - { - pLimit = pch+iRead; - *pLimit = '\n'; - } - return iRead < 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_open (const char *pName) - -/* Open a file for reading. - * - * pName: Name of the file to read. - * - * Result: - * 0 on success, non-0 else (errno contains error code then). - * - * The reader is initialized to read and filter the file name *pName. - */ - -{ - assert(pName); - assert(fdFile < 0); - reader_init(); - fdFile = open(pName, O_RDONLY); - return fdFile >= 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_openrw (const char *pNameR, const char *pNameW) - -/* Open two makefiles for modification. - * - * pNameR: Name of the file to read, may be NULL. - * pNameW: Name of the file to read. - * - * Result: - * 0 on success, non-0 else (errno contains error code then). - * - * The reader is initialized to read the old makefile *pNameR and writing - * of new makefile *pNameW. - * If no pNameR is given, the reader is immediately initialized to - * write *pNameW. - */ - -{ - assert(pNameW); - assert(fdFile < 0); - assert(fdFile2 < 0); - reader_init(); - fdFile2 = open(pNameW, O_WRONLY|O_CREAT|O_TRUNC, 0664); - if (fdFile2 < 0) - return 1; - if (pNameR) - { - fdFile = open(pNameR, O_RDONLY); - if (fdFile < 0) - { - close(fdFile2); - fdFile2 = -1; - } - } - else - pch = aBuffer; - return fdFile2 < 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_close (void) - -/* Close the file currently read. - * Result: - * 0 on success, non-0 else. - * errno set to error code in case. - */ - -{ - int i; - - i = 0; - if (fdFile >= 0) - { - i = close(fdFile); - } - fdFile = -1; - if (fdFile2 >= 0) - { - i = close(fdFile2) || i; - } - fdFile2 = -1; - if (pState) - { - free(pState); - } - pState = NULL; - return i; -} - -/*-------------------------------------------------------------------------*/ -int -reader_eof (void) - -/* Test if the file read is at its end. - * - * Result: - * Non-0 on end of file. - */ - -{ - return END_OF_FILE(); -} - -/*-------------------------------------------------------------------------*/ -const char * -reader_get (int * pType) - -/* Extract the next include statement from the file being read. - * - * Result: - * Pointer to the filename extracted from the statement, or NULL on error - * or end of file. - * The memory is property of reader_get(), the pointer valid just until - * the next call to reader_get(). - * <*pType> is set to 0 for an ""-include, and non-zero for an <>-include. - * o set to an error code in case. - */ - -{ - enum { StartOfLine, InLine, FoundHash, SkipComment, SkipLComment, FoundInclude - } eState; - /* For debugging purposes: - char *stab[] - = { - "Start " - , "InLine" - , "Found#" - , "SkipC " - , "SkipLC" - , "FoundI" - }; - */ - char ch; - int iFound; /* Number of chars found of "include" */ - int bDone; /* 0: still searching, 1: found include */ - int bType; /* 0: ""-include, 1: <>-include */ - -#define GETCHAR() \ - ch = *pch++; \ - if (ch == '\n' && pch >= pLimit) \ - { \ - if (fillbuffer()) { \ - pIName = NULL; \ - return NULL; \ - } \ - ch = *pch++; \ - } - - if (pIName) - eState = InLine; - else - eState = StartOfLine; - pIName = NULL; - - iFound = 0; - bType = 0; - bDone = 0; - while (!bDone) - { - /* Get the next interesting non-linefeed character */ - do { - GETCHAR() - if (ch == '\n' || ch == '\r' || ch == '\v' || ch == '\f') - { - eState = StartOfLine; - pIName = NULL; - } - else - break; - } while (1); - - switch(eState) - { - case StartOfLine: - switch (ch) - { - case '#': - eState = FoundHash; - iFound = 0; - break; - case '/': - GETCHAR() - if (ch == '/') - eState = SkipLComment; - else if (ch == '*') - eState = SkipComment; - else - eState = InLine; - break; - case ' ': case '\t': - /* still: eState = StartOfLine; */ - break; - default: - eState = InLine; - break; - } - break; - - case InLine: - switch (ch) - { - case '/': - GETCHAR() - if (ch == '/') - eState = SkipLComment; - else if (ch == '*') - eState = SkipComment; - else - eState = InLine; - break; - case '\\': - GETCHAR() - /* still: eState = InLine; */ - break; - default: - /* still: eState = InLine; */ - break; - } - break; - - case FoundHash: - switch(ch) - { - case ' ': case '\t': - if (iFound) - { - eState = InLine; - iFound = 0; - } - /* else still: eState = FoundHash */ - break; - case 'i': case 'n': case 'c': case 'l': - case 'u': case 'd': case 'e': - if ("include"[iFound] != ch) - { - eState = InLine; - iFound = 0; - } - else if (ch == 'e') - { - eState = FoundInclude; - pIName = NULL; - } - else - iFound++; - break; - default: - eState = InLine; - } - break; - - case FoundInclude: - switch(ch) - { - case ' ': case '\t': - /* still: eState = FoundInclude */ - break; - case '<': - if (!pIName) - { - pIName = pch; - bType = 1; - } - else - eState = InLine; - break; - case '>': - if (!pIName) - { - eState = InLine; - } - else if (bType) - { - *(pch-1) = '\0'; - if (pch-1 == pIName) - pIName = NULL; - else - bDone = 1; - eState = InLine; - } - break; - case '"': - if (!pIName) - { - pIName = pch; - bType = 0; - } - else if (!bType) - { - *(pch-1) = '\0'; - if (pch-1 == pIName) - pIName = NULL; - else - bDone = 1; - eState = InLine; - } - break; - - default: - if (!pIName) - eState = InLine; - break; - } - break; - - case SkipComment: - case SkipLComment: - break; - } /* switch (eState) */ - - /* Skip comments immediately */ - if (eState == SkipComment) - { - while(1) { - do { - GETCHAR() - } while (ch != '*'); - GETCHAR() - if (ch == '/') - break; - } - eState = StartOfLine; - } - else if (eState == SkipLComment) - { - do { - GETCHAR() - } while (ch != '\n' && ch != '\r' && ch != '\v' && ch != '\f'); - eState = StartOfLine; - } - } /* while(!bDone) */ - - *pType = bType; - return pIName; - -#undef GETCHAR -} - -/*-------------------------------------------------------------------------*/ -int -reader_writeflush (void) - -/* Write out the buffer to the written makefile. - * Return 0 on success, non-0 else (errno holds the error code then). - */ - -{ - if (pch > aBuffer - && write(fdFile2, aBuffer, (unsigned)(pch-aBuffer)) != pch-aBuffer) - return 1; - pch = aBuffer; - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_writen (const char *pText, size_t len) - -/* Append the first characters of to the written file. - * Return 0 on success, non-0 else (errno holds the error code then) - */ - -{ - assert(pText); - assert(fdFile2 >= 0); - if (pLimit-pch < (signed)len && reader_writeflush()) - return 1; - memcpy(pch, pText, len); - pch += len; - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_write (const char *pText) - -/* Append to the written file. - * Return 0 on success, non-0 else (errno holds the error code then) - */ - -{ - return reader_writen(pText, strlen(pText)); -} - -/*-------------------------------------------------------------------------*/ -int -reader_copymake (const char * pTagline) - -/* Copy the file from fdFile to fdFile2 up to including the tagline. - * If the tagline is not found, it is appended. - * The tagline MUST end in a newline character! - * Return 0 on success, non-0 on error (errno holds the error code then). - */ - -{ - size_t len; - int count; /* Next charactor to compare in pTagline, or -1 if to skip - * up to the next Newline */ - char ch; - - - assert(pTagline); - assert(fdFile2); - len = strlen(pTagline); - assert(len < 120); - - /* Simplest case: no old makefile to copy */ - if (fdFile < 0) - { - strcpy(aBuffer, pTagline); - pch = aBuffer+len; - return 0; - } - if (fillbuffer()) - return 1; - count = 0; - - while (!END_OF_FILE() && count < (signed)len) - { - if (END_OF_BUF()) - { - if (write(fdFile2, aBuffer, (unsigned)(pch-aBuffer)) != pch-aBuffer) - return 1; - if (fillbuffer()) - return 1; - if (END_OF_FILE()) - break; - } - ch = *pch; - if (count < 0) - { - if (ch == '\n') - count = 0; - } - else - { - if (ch == pTagline[count]) - count++; - else if (ch == '\n') - count = 0; - else - count = -1; - } - pch++; - } - - /* Remember the state of the Makefile read */ - if (!END_OF_FILE()) - { - pState = (struct filestate *) malloc(sizeof(*pState)+(pLimit-pch)); - if (pState) - { - pState->len = pLimit-pch; - memcpy(pState->buf, pch, (size_t)pState->len); - } - } - - /* Switch to write mode */ - pLimit = aBuffer+BUFSIZE; - - /* Append a newline if missing */ - if (count < 0 && reader_writen("\n", 1)) - return 1; - - /* Put the Tagline into the buffer if necessary */ - if (count < (signed)len && reader_writen(pTagline, (size_t)len)) - return 1; - - return 0; -} - -/*-------------------------------------------------------------------------*/ -int -reader_copymake2 (const char * pTagline) - -/* Copy the remainder from fdFile to fdFile2 starting with the tagline. - * The tagline MUST end in a newline character! - * Return 0 on success, non-0 on error (errno holds the error code then). - */ - -{ - size_t len; - int count; /* Next charactor to compare in pTagline, or -1 if to skip - * up to the next Newline */ - char ch; - - - assert(pTagline); - assert(fdFile); - assert(fdFile2); - len = strlen(pTagline); - assert(len < 120); - - /* Append the tagline to the file written */ - if (reader_write(pTagline) || reader_writeflush()) - return 1; - - /* Easiest case: nothing to left copy */ - if (!pState) - return 0; - - /* Restore the aBuffer to the point where the reading stopped */ - pLimit = aBuffer+BUFSIZE; - pch = pLimit-pState->len; - memcpy(pch, pState->buf, (size_t)pState->len); - free(pState); - pState = NULL; - pIName = NULL; - - /* Fill up the buffer */ - if (END_OF_BUF() && fillbuffer()) - return 1; - - /* Skip the Makefile read until the tagline has been found */ - count = 0; - while (!END_OF_FILE() && count < (signed)len) - { - if (END_OF_BUF()) - { - if (fillbuffer()) - return 1; - if (END_OF_FILE()) - break; - } - ch = *pch; - if (count < 0) - { - if (ch == '\n') - count = 0; - } - else - { - if (ch == pTagline[count]) - count++; - else if (ch == '\n') - count = 0; - else - count = -1; - } - pch++; - } - - /* Copy the remainder of the Makefile */ - do - { - if (!END_OF_BUF() - && write(fdFile2, pch, (unsigned)(pLimit-pch)) != pLimit-pch) - return 1; - if (!END_OF_FILE() && fillbuffer()) - return 1; - } - while (!END_OF_FILE()); - - return 0; -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/reader.h b/src/bin/mkdepend/reader.h deleted file mode 100644 index 9b3112512d..0000000000 --- a/src/bin/mkdepend/reader.h +++ /dev/null @@ -1,24 +0,0 @@ -/* $Id: reader.h 1.4 Wed, 01 Mar 2000 21:15:40 -0700 lars $ */ - -/*--------------------------------------------------------------------------- -** Copyright (c) 1995-1998 by Lars Düning. All Rights Reserved. -** This file is free software. For terms of use see the file LICENSE. -**--------------------------------------------------------------------------- -*/ - -#ifndef __READER_H__ -#define __READER_H__ 1 - -extern void reader_init (void); -extern int reader_open (const char *); -extern int reader_openrw (const char *, const char *); -extern int reader_close (void); -extern int reader_eof (void); -extern const char * reader_get (int *); -extern int reader_writeflush (void); -extern int reader_writen (const char *, size_t); -extern int reader_write (const char *); -extern int reader_copymake (const char *); -extern int reader_copymake2 (const char *); - -#endif diff --git a/src/bin/mkdepend/util.c b/src/bin/mkdepend/util.c deleted file mode 100644 index 1d7c1ad0b1..0000000000 --- a/src/bin/mkdepend/util.c +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id: util.c 1.2 Wed, 01 Mar 2000 21:23:27 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Useful functions. - * - * Copyright (c) 1999 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - */ - -#include -#include -#include - -#include "util.h" - -/*-------------------------------------------------------------------------*/ -char * -util_getpath (const char * pDirtyName, char ** ppBasename) - -/* Take the and eliminate as many '.' and '..' from it - * as possible. Return a freshly allocated copy of the cleaned up path. - * If ppBasename is NULL, the returned name will only contain the - * directory parts, the filename will be dropped. If ppBasename is not - * NULL, the returned name will contain the filename, and *ppBasename - * will be set to point to its first character. - * - * Return NULL when out of memory. - */ - -{ - char * pPath; /* The newly created pathname */ - char * pStart; /* The first non-'/'-character of pPath */ - char * pSrc, * pDest; /* Working pointers */ - size_t oFilename; /* Offset of filename in pDirtyName */ - - assert(pDirtyName); - - pPath = strdup(pDirtyName); - if (!pPath) - return NULL; - - pStart = ('/' == *pPath) ? pPath+1 : pPath; - - /* First scan: find the first character of the filename - * and end the string there, leaving just the directory path. - * But remember the offset of the filename. - */ - pDest = pStart; /* First character after last '/' found */ - pSrc = pStart; /* Rover */ - while ('\0' != *pSrc) - { - if ('/' == *pSrc++) - pDest = pSrc; - } - *pDest = '\0'; - oFilename = (unsigned)(pDest - pPath); - - /* pPath now ends in a '/', or *pStart is a '\0' */ - - /* Second scan: visit all directory parts and eliminate '.' - * and '..' where possible. - */ - pDest = pStart; /* First character after last valid '/' */ - pSrc = pStart; - - /* Skip initial '.' entries */ - while ('.' == *pSrc) - { - if ('/' == pSrc[1]) - { - pSrc += 2; - } - else - break; - } - - while ('\0' != *pSrc) - { - char ch; - - /* Copy forward until the next '/' */ - do - { - ch = *pSrc++; - *pDest++ = ch; - } while ('/' != ch); - - /* If a '.' follows, it might be a '.' or '..' entry */ - while ('.' == *pSrc) - { - pSrc++; - - if ('/' == *pSrc) - { - /* Simply skip the '.' entry */ - pSrc++; - } - else if ('.' == pSrc[0] && '/' == pSrc[1] && pDest != pStart) - { - /* For a '..' entry, move pDest back one directory unless - * it is at the start of the string - */ - char * pLastDest; - - for ( pLastDest = pDest-1 - ; pLastDest != pStart && '/' != pLastDest[-1] - ; pLastDest--) /* SKIP */; - - /* Special case: if the part just unrolled is '..' itself, - * don't do the unrolling and instead break the loop. - */ - if (pLastDest + 3 == pDest && pLastDest[0] == '.' && pLastDest[1] == '.') - { - *pDest++ = '.'; - break; - } - else - { - pSrc += 2; - pDest = pLastDest; - } - } - else - { - /* Its not a '.' or handleable '..' entry */ - *pDest++ = '.'; - break; - } - } - } - *pDest = '\0'; - - /* If the caller wants to have the filename too, append it to - * the clean directory. - */ - if (ppBasename) - { - strcpy(pDest, pDirtyName+oFilename); - *ppBasename = pDest; - } - - return pPath; -} - -/***************************************************************************/ diff --git a/src/bin/mkdepend/util.h b/src/bin/mkdepend/util.h deleted file mode 100644 index 60f2cc46d1..0000000000 --- a/src/bin/mkdepend/util.h +++ /dev/null @@ -1,14 +0,0 @@ -/* $Id: util.h 1.1 Tue, 02 Feb 1999 17:57:55 -0700 lars $ */ - -/*--------------------------------------------------------------------------- - * Copyright (c) 1999 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - */ - -#ifndef __UTIL_H__ -#define __UTIL_H__ 1 - -extern char * util_getpath(const char *, char **); - -#endif diff --git a/src/bin/mkdepend/version.h b/src/bin/mkdepend/version.h deleted file mode 100644 index c8a98371ce..0000000000 --- a/src/bin/mkdepend/version.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $Id: version.h 1.2 Sat, 24 Oct 1998 19:54:13 -0600 lars $ */ - -/*--------------------------------------------------------------------------- - * Version information for MkDepend. - * - * Copyright (c) 1998 by Lars Düning. All Rights Reserved. - * This file is free software. For terms of use see the file LICENSE. - *--------------------------------------------------------------------------- - * This macros are exported: - * - * VERSION: a string of the form "x.y" or "x.y.z", with z being >= 2. - * RELEASEDATE: a string with date and time when the current version was - * checked in. - * PRCS_LEVEL: the internal minor version of MkDepend, used for - * in VERSION when the value is >= 2. - * - * The values are created by PRCS. - *--------------------------------------------------------------------------- - */ - -#ifndef __VERSION_H__ -#define __VERSION_H__ - -/* $Format: "#define RELEASE_DATE \"$ReleaseDate$\""$ */ -#define RELEASE_DATE "Thu, 19 Mar 2009 11:20:00 -0100" - -/* $Format: "#define PRCS_LEVEL $ProjectMinorVersion$"$ */ -#define PRCS_LEVEL 1 - -#if PRCS_LEVEL > 1 -/* $Format: "#define VERSION \"$ReleaseVersion$.$ProjectMinorVersion$\""$ */ -#define VERSION "1.7.1" -#else -/* $Format: "#define VERSION \"$ReleaseVersion$\""$ */ -#define VERSION "1.7" -#endif - -#endif /* __VERSION_H__ */